diff options
author | Vika <vika@fireburn.ru> | 2025-03-11 14:14:06 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2025-04-09 20:20:19 +0300 |
commit | 936ed2d5d00199c545a8cdac763909cc63be096b (patch) | |
tree | c171aafafe26fc648d64ea03481bfd3994bb4eb5 | |
parent | 2224f5557a3f2d522a82de27cee73234fa856298 (diff) | |
download | bowl-936ed2d5d00199c545a8cdac763909cc63be096b.tar.zst |
libspelling support
While libspelling is rather primitive (i.e. doesn't support mixing languages), it's better than nothing to detect simple spelling mistakes. Let's use it.
-rw-r--r-- | Cargo.lock | 66 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | default.nix | 3 | ||||
-rw-r--r-- | src/components/post_editor.rs | 24 | ||||
-rw-r--r-- | src/main.rs | 3 |
5 files changed, 93 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock index 58cb500..4074e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,6 +123,7 @@ dependencies = [ "kittybox-util", "libadwaita", "libsecret", + "libspelling", "log", "microformats", "relm4", @@ -132,6 +133,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "soup3", + "sourceview5", "thiserror", "tokio", "tracing", @@ -1050,6 +1052,35 @@ dependencies = [ ] [[package]] +name = "libspelling" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cbd36b794de5725e0b2be4cc90c57c5e3c7a5a3e5c317436e9e667305274c34" +dependencies = [ + "gio", + "glib", + "gtk4", + "libc", + "libspelling-sys", + "sourceview5", +] + +[[package]] +name = "libspelling-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2ec120461981daf9d0c5a8b0bc55ebf350292280e93fd6d063895593754484" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk4-sys", + "libc", + "sourceview5-sys", + "system-deps", +] + +[[package]] name = "litemap" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1714,6 +1745,41 @@ dependencies = [ ] [[package]] +name = "sourceview5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e07d99b15f12767aa1c84870c45667f42bf24fd6a989dc70088e32854ef56e" +dependencies = [ + "futures-channel", + "futures-core", + "gdk-pixbuf", + "gdk4", + "gio", + "glib", + "gtk4", + "libc", + "pango", + "sourceview5-sys", +] + +[[package]] +name = "sourceview5-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3759467713554a8063faa380237ee2c753e89026bbe1b8e9611d991cb106ff" +dependencies = [ + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk4-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 7b76f8c..2b6d3eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ gettext-rs = { version = "=0.7.0", features = ["gettext-system"] } gio = { version = "0.20.1", features = ["v2_80"] } glib = { version = "0.20.1", features = ["log"] } gtk = { version = "0.9.0", package = "gtk4", features = ["gnome_46", "v4_14"] } +sourceview5 = { version = "0.9.1" } kittybox-indieauth = { git = "https://git.vikanezrimaya.xyz/kittybox", version = "0.2.0" } kittybox-util = { git = "https://git.vikanezrimaya.xyz/kittybox", version = "0.3.0" } libsecret = { version = "0.7.0", features = ["v0_21_2"] } @@ -30,6 +31,7 @@ serde = { version = "1.0.208", features = ["derive"] } serde_json = "1.0.125" serde_urlencoded = "0.7.1" soup3 = "0.7.0" +spelling = { version = "0.3.0", package = "libspelling" } thiserror = "1.0.63" tokio = { version = "1.39.3", features = ["full", "tracing"] } tracing = { version = "0.1.40", features = ["log"] } diff --git a/default.nix b/default.nix index de622f9..ebd0f28 100644 --- a/default.nix +++ b/default.nix @@ -2,6 +2,7 @@ , pkg-config, wrapGAppsHook4, meson, ninja, gettext , desktop-file-utils , gtk4, libadwaita, libpanel, libsoup_3, libsecret +, libspelling, gtksourceview5 , librsvg, glib-networking , withLLMEnhancements ? true @@ -26,7 +27,7 @@ let strictDeps = true; buildInputs = [ - gtk4 libadwaita libsoup_3 libsecret + gtk4 libadwaita libsoup_3 libsecret libspelling gtksourceview5 librsvg glib-networking gettext ]; diff --git a/src/components/post_editor.rs b/src/components/post_editor.rs index 863e515..d08685a 100644 --- a/src/components/post_editor.rs +++ b/src/components/post_editor.rs @@ -88,10 +88,12 @@ impl Post { pub(crate) struct PostEditor<E> { #[no_eq] smart_summary_busy_guard: Option<gtk::gio::ApplicationBusyGuard>, sending: bool, + #[do_not_track] #[allow(dead_code)] spell_checker: spelling::Checker, + #[do_not_track] spelling_adapter: spelling::TextBufferAdapter, #[do_not_track] name_buffer: gtk::EntryBuffer, #[do_not_track] summary_buffer: gtk::EntryBuffer, - #[do_not_track] content_buffer: gtk::TextBuffer, + #[do_not_track] content_buffer: sourceview5::Buffer, #[do_not_track] pending_tag_buffer: gtk::EntryBuffer, #[do_not_track] tags: relm4::factory::FactoryVecDeque<TagPill>, @@ -241,6 +243,9 @@ impl<E: std::error::Error + std::fmt::Debug + Send + 'static> Component for Post #[name = "content_textarea"] gtk::TextView { set_buffer: Some(&model.content_buffer), + set_extra_menu: Some(&model.spelling_adapter.menu_model()), + insert_action_group: ("spelling", Some(&model.spelling_adapter)), + set_hexpand: true, #[iterate] add_css_class: &["frame", "view"], @@ -340,15 +345,25 @@ impl<E: std::error::Error + std::fmt::Debug + Send + 'static> Component for Post #[cfg(feature = "smart-summary")] let (http, init) = init; + let spell_checker = spelling::Checker::default(); + let content_buffer = Default::default(); + let mut model = Self { smart_summary_busy_guard: None, sending: false, + spelling_adapter: spelling::TextBufferAdapter::new( + &content_buffer, + &spell_checker + ), + spell_checker, + name_buffer: gtk::EntryBuffer::default(), summary_buffer: gtk::EntryBuffer::default(), - content_buffer: gtk::TextBuffer::default(), - pending_tag_buffer: gtk::EntryBuffer::default(), + content_buffer, + + pending_tag_buffer: gtk::EntryBuffer::default(), tags: FactoryVecDeque::builder() .launch({ let listbox = gtk::Box::default(); @@ -383,10 +398,11 @@ impl<E: std::error::Error + std::fmt::Debug + Send + 'static> Component for Post let visibility_model = adw::EnumListModel::new(Visibility::static_type()); let widgets = view_output!(); - #[cfg(feature = "smart-summary")] widgets.summary_field.append(model.smart_summary.widget()); + model.spelling_adapter.set_enabled(true); + widgets.visibility_selector.set_expression(Some( gtk::ClosureExpression::new::<String>( [] as [gtk::Expression; 0], diff --git a/src/main.rs b/src/main.rs index 9f531ea..989516a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,9 @@ fn main() { relm4_icons::initialize_icons(bowl::icons::GRESOURCE_BYTES, bowl::icons::RESOURCE_PREFIX); + sourceview5::init(); + spelling::init(); + let app = relm4::RelmApp::new(bowl::APPLICATION_ID); relm4::set_global_css("/* CSS for Bowl */ .tag-pill button { |