From 70b728369bf4eea0154a2ed0b0a20d03b7d1c6c6 Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 21 May 2020 07:20:27 -0500 Subject: [PATCH 01/15] Added IntelliJ platform files to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 026c70b..6458cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.idea test/bin/ target/ doc/ From 18fd78c3638f40f2c318ca900f997cdc0c3a627e Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 21 May 2020 13:40:23 -0500 Subject: [PATCH 02/15] Added Impl trait --- src/completion_provider.rs | 43 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 2 files changed, 45 insertions(+) create mode 100644 src/completion_provider.rs diff --git a/src/completion_provider.rs b/src/completion_provider.rs new file mode 100644 index 0000000..81d4858 --- /dev/null +++ b/src/completion_provider.rs @@ -0,0 +1,43 @@ +use crate::CompletionActivation; +use crate::CompletionContext; +use crate::CompletionInfo; +use crate::CompletionProposal; +use crate::CompletionProvider; +use glib::subclass::prelude::*; + +pub trait CompletionImpl: ObjectImpl + Send + 'static { + fn get_name(&self, obj: &CompletionProvider) -> glib::GString; + fn get_icon(&self, obj: &CompletionProvider) -> Option; + fn get_icon_name(&self, obj: &CompletionProvider) -> Option; + fn get_gicon(&self, obg: &CompletionProvider) -> Option; + fn populate(&self, obg: &CompletionProvider, context: &CompletionContext); + fn get_activation(&self, obg: &CompletionProvider) -> CompletionActivation; + fn provider_match(&self, obg: &CompletionProvider, context: &CompletionContext) -> bool; + fn get_info_widget( + &self, + obg: &CompletionProvider, + proposal: &CompletionProposal, + ) -> Option; + fn update_info( + &self, + obg: &CompletionProvider, + proposal: &CompletionProposal, + info: &CompletionInfo, + ); + fn get_start_iter( + &self, + obg: &CompletionProvider, + context: &CompletionContext, + proposal: &CompletionProposal, + iter: >k::TextIter, + ) -> bool; + fn activate_proposal( + &self, + obg: &CompletionProvider, + proposal: &CompletionProposal, + iter: >k::TextIter, + ) -> bool; + fn get_interactive_delay(&self, obj: &CompletionProvider) -> i32; + fn get_priority(&self, obg: &CompletionProvider) -> i32; +} + diff --git a/src/lib.rs b/src/lib.rs index 66c0862..7451494 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ extern crate bitflags; pub use auto::*; pub use completion::*; pub use completion_info::*; +pub use completion_provider::*; #[cfg(any(feature = "v3_14", feature = "dox"))] pub use file_loader::*; #[cfg(any(feature = "v3_14", feature = "dox"))] @@ -62,6 +63,7 @@ mod rt; mod auto; mod completion; mod completion_info; +mod completion_provider; #[cfg(any(feature = "v3_14", feature = "dox"))] mod file_loader; #[cfg(any(feature = "v3_14", feature = "dox"))] From 708f9e31f5cc1405bd8ba04d43e0004b953028a5 Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 21 May 2020 17:52:58 -0500 Subject: [PATCH 03/15] Fixed trait name --- src/completion_provider.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/completion_provider.rs b/src/completion_provider.rs index 81d4858..053b43d 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -4,8 +4,9 @@ use crate::CompletionInfo; use crate::CompletionProposal; use crate::CompletionProvider; use glib::subclass::prelude::*; +use gtk_source_sys::gtk_source_completion_provider_get_name; -pub trait CompletionImpl: ObjectImpl + Send + 'static { +pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { fn get_name(&self, obj: &CompletionProvider) -> glib::GString; fn get_icon(&self, obj: &CompletionProvider) -> Option; fn get_icon_name(&self, obj: &CompletionProvider) -> Option; From 4be3f26300bf8426baeb39f338e5cbe7fcb6bd27 Mon Sep 17 00:00:00 2001 From: john01dav Date: Sat, 23 May 2020 13:13:10 -0500 Subject: [PATCH 04/15] Added part of the glue logic --- src/completion_provider.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/completion_provider.rs b/src/completion_provider.rs index 053b43d..c863ce4 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -3,8 +3,9 @@ use crate::CompletionContext; use crate::CompletionInfo; use crate::CompletionProposal; use crate::CompletionProvider; +use glib::prelude::*; +use glib::translate::*; use glib::subclass::prelude::*; -use gtk_source_sys::gtk_source_completion_provider_get_name; pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { fn get_name(&self, obj: &CompletionProvider) -> glib::GString; @@ -42,3 +43,15 @@ pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { fn get_priority(&self, obg: &CompletionProvider) -> i32; } +unsafe impl IsImplementable for CompletionProvider { + unsafe extern "C" fn interface_init(iface: glib::glib_sys::gpointer, _iface_data: glib::glib_sys::gpointer) { + let iface = &mut *(iface as *mut gtk_source_sys::GtkSourceCompletionProviderIface); + iface.get_name = Some(completion_provider_get_name::); + } +} + +unsafe extern "C" fn completion_provider_get_name(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *const libc::c_char{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.get_name(&from_glib_borrow(completion_provider)).to_glib_full() +} \ No newline at end of file From e1712587b442a6626694c1bf108d064551d9a63f Mon Sep 17 00:00:00 2001 From: john01dav Date: Mon, 25 May 2020 17:02:05 -0500 Subject: [PATCH 05/15] Added all of glue logic --- Cargo.toml | 1 + src/completion_provider.rs | 194 ++++++++++++++++++++++++++++++++++++- src/lib.rs | 1 + 3 files changed, 194 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cd69e04..ac559c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ features = ["dox", "embed-lgpl-docs"] [dependencies] libc = "0.2" bitflags = "1.0" +once_cell = "1.0" [dependencies.gtk-source-sys] path = "./sourceview-sys" diff --git a/src/completion_provider.rs b/src/completion_provider.rs index c863ce4..dd8e4ea 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -6,15 +6,16 @@ use crate::CompletionProvider; use glib::prelude::*; use glib::translate::*; use glib::subclass::prelude::*; +use once_cell::sync::Lazy; pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { fn get_name(&self, obj: &CompletionProvider) -> glib::GString; fn get_icon(&self, obj: &CompletionProvider) -> Option; fn get_icon_name(&self, obj: &CompletionProvider) -> Option; - fn get_gicon(&self, obg: &CompletionProvider) -> Option; + fn get_gicon(&self, obg: &CompletionProvider) -> Option; fn populate(&self, obg: &CompletionProvider, context: &CompletionContext); fn get_activation(&self, obg: &CompletionProvider) -> CompletionActivation; - fn provider_match(&self, obg: &CompletionProvider, context: &CompletionContext) -> bool; + fn provide_match(&self, obg: &CompletionProvider, context: &CompletionContext) -> bool; fn get_info_widget( &self, obg: &CompletionProvider, @@ -47,6 +48,18 @@ unsafe impl IsImplementable for C unsafe extern "C" fn interface_init(iface: glib::glib_sys::gpointer, _iface_data: glib::glib_sys::gpointer) { let iface = &mut *(iface as *mut gtk_source_sys::GtkSourceCompletionProviderIface); iface.get_name = Some(completion_provider_get_name::); + iface.get_icon = Some(completion_provider_get_icon::); + iface.get_icon_name = Some(completion_provider_get_icon_name::); + iface.get_gicon = Some(completion_provider_get_gicon::); + iface.populate = Some(completion_provider_populate::); + iface.get_activation = Some(completion_provider_get_activation::); + iface.match_ = Some(completion_provider_provide_match::); + iface.get_info_widget = Some(completion_provider_get_info_widget::); + iface.update_info = Some(completion_provider_update_info::); + iface.get_start_iter = Some(completion_provider_get_start_iter::); + iface.activate_proposal = Some(completion_provider_activate_proposal::); + iface.get_interactive_delay = Some(completion_provider_get_interactive_delay::); + iface.get_priority = Some(completion_provider_get_priority::); } } @@ -54,4 +67,181 @@ unsafe extern "C" fn completion_provider_get_name = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon")); + +unsafe extern "C" fn completion_provider_get_icon(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *mut gdk_pixbuf_sys::GdkPixbuf{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + + let ret = imp.get_icon(&from_glib_borrow(completion_provider)); + let ret_ptr = match ret{ + Some(ref ret) => ret.as_ptr(), + None => std::ptr::null_mut() + }; + + let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_ICON_QUARK.to_glib()); + if !old_ptr.is_null() { + assert_eq!( + old_ptr as *mut _, + ret_ptr, + "Did not return same icon again" + ); + } + + gobject_sys::g_object_set_qdata_full( + completion_provider as *mut _, + COMPLETION_PROVIDER_ICON_QUARK.to_glib(), + ret_ptr as *mut libc::c_void, + Some(unref), + ); + + ret.to_glib_none().0 +} + +static COMPLETION_PROVIDER_ICON_NAME_QUARK: Lazy = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon-name")); + +unsafe extern "C" fn completion_provider_get_icon_name(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *const libc::c_char{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + + let ret = imp.get_icon_name(&from_glib_borrow(completion_provider)); + let ret_ptr = match ret{ + Some(ref ret) => ret.as_ptr(), + None => std::ptr::null() + }; + + let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_ICON_NAME_QUARK.to_glib()); + if !old_ptr.is_null() { + assert_eq!( + old_ptr as *const _, + ret_ptr, + "Did not return same icon again" + ); + } + + gobject_sys::g_object_set_qdata_full( + completion_provider as *mut _, + COMPLETION_PROVIDER_ICON_NAME_QUARK.to_glib(), + ret_ptr as *mut libc::c_void, + Some(unref), + ); + + ret.to_glib_none().0 +} + +static COMPLETION_PROVIDER_GICON_QUARK: Lazy = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-gicon")); + +unsafe extern "C" fn completion_provider_get_gicon(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *mut gio_sys::GIcon{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + + let ret = imp.get_gicon(&from_glib_borrow(completion_provider)); + let ret_ptr = match ret{ + Some(ref ret) => ret.as_ptr(), + None => std::ptr::null_mut() + }; + + let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_GICON_QUARK.to_glib()); + if !old_ptr.is_null() { + assert_eq!( + old_ptr as *mut _, + ret_ptr, + "Did not return same icon again" + ); + } + + gobject_sys::g_object_set_qdata_full( + completion_provider as *mut _, + COMPLETION_PROVIDER_GICON_QUARK.to_glib(), + ret_ptr as *mut libc::c_void, + Some(unref), + ); + + ret.to_glib_none().0 +} + +unsafe extern "C" fn completion_provider_populate(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext){ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.populate(&from_glib_borrow(completion_provider), &from_glib_borrow(context)) +} + +unsafe extern "C" fn completion_provider_get_activation(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> gtk_source_sys::GtkSourceCompletionActivation{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.get_activation(&from_glib_borrow(completion_provider)).to_glib() +} + +unsafe extern "C" fn completion_provider_provide_match(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext) -> glib_sys::gboolean{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.provide_match(&from_glib_borrow(completion_provider), &from_glib_borrow(context)).to_glib() +} + +static COMPLETION_PROVIDER_INFO_WIDGET: Lazy = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-info-widget")); + +unsafe extern "C" fn completion_provider_get_info_widget(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal) -> *mut gtk_sys::GtkWidget{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + + let ret = imp.get_info_widget(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal)); + let ret_ptr = match ret{ + Some(ref ret) => ret.as_ptr(), + None => std::ptr::null_mut() + }; + + let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_INFO_WIDGET.to_glib()); + if !old_ptr.is_null() { + assert_eq!( + old_ptr as *mut _, + ret_ptr, + "Did not return same icon again" + ); + } + + gobject_sys::g_object_set_qdata_full( + completion_provider as *mut _, + COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), + ret_ptr as *mut libc::c_void, + Some(unref), + ); + + ret.to_glib_none().0 + +} + +unsafe extern "C" fn completion_provider_update_info(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, completion_info: *mut gtk_source_sys::GtkSourceCompletionInfo) { + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.update_info(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal), &from_glib_borrow(completion_info)) +} + +unsafe extern "C" fn completion_provider_get_start_iter(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, iter: *mut gtk_sys::GtkTextIter) -> glib_sys::gboolean{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.get_start_iter(&from_glib_borrow(completion_provider), &from_glib_borrow(context), &from_glib_borrow(proposal), &from_glib_borrow(iter)).to_glib() +} + +unsafe extern "C" fn completion_provider_activate_proposal(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, iter: *mut gtk_sys::GtkTextIter) -> glib_sys::gboolean{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.activate_proposal(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal), &from_glib_borrow(iter)).to_glib() +} + +unsafe extern "C" fn completion_provider_get_interactive_delay(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> libc::c_int{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.get_interactive_delay(&from_glib_borrow(completion_provider)) +} + +unsafe extern "C" fn completion_provider_get_priority(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> libc::c_int{ + let instance = &*(completion_provider as *mut T::Instance); + let imp = instance.get_impl(); + imp.get_priority(&from_glib_borrow(completion_provider)) +} + +unsafe extern "C" fn unref(ptr: glib_sys::gpointer) { + gobject_sys::g_object_unref(ptr as *mut _); } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 7451494..93c0ace 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,7 @@ extern crate gtk; extern crate gtk_source_sys; extern crate gtk_sys; extern crate pango; +extern crate once_cell; extern crate libc; #[macro_use] From 3f52aaf6e2e707e3c86636733bb2f4dd687e14d5 Mon Sep 17 00:00:00 2001 From: john01dav Date: Mon, 25 May 2020 17:21:54 -0500 Subject: [PATCH 06/15] Added examples for words autocompletion, and a view without autocompletion --- Cargo.toml | 3 + examples/autocomplete_words.rs | 30 +++++ examples/plain_sourceview.rs | 27 +++++ src/completion_provider.rs | 200 +++++++++++++++++++++++---------- src/lib.rs | 2 +- 5 files changed, 203 insertions(+), 59 deletions(-) create mode 100644 examples/autocomplete_words.rs create mode 100644 examples/plain_sourceview.rs diff --git a/Cargo.toml b/Cargo.toml index ac559c5..4527b0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,3 +92,6 @@ git = "https://github.com/gtk-rs/gio" [dev-dependencies] gir-format-check = "^0.1" + +[dev-dependencies.gtk] +git = "https://github.com/gtk-rs/gtk" \ No newline at end of file diff --git a/examples/autocomplete_words.rs b/examples/autocomplete_words.rs new file mode 100644 index 0000000..ec45563 --- /dev/null +++ b/examples/autocomplete_words.rs @@ -0,0 +1,30 @@ +extern crate gio; +extern crate gtk; +extern crate sourceview; +use gio::prelude::*; +use gtk::prelude::*; +use sourceview::prelude::*; + +use std::env; + +fn main() { + let uiapp = gtk::Application::new( + None, + gio::ApplicationFlags::FLAGS_NONE, + ) + .expect("Application::new failed"); + uiapp.connect_activate(|app| { + let win = gtk::ApplicationWindow::new(app); + win.set_default_size(320, 200); + win.set_title("Basic example"); + + let sourceview = sourceview::View::new(); + let completion = sourceview::CompletionWords::new(Some("Words"), None); + completion.register(&sourceview.get_buffer().expect("Sourceview has no buffer.")); + sourceview.get_completion().expect("Sourceview has no completion").add_provider(&completion); + win.add(&sourceview); + + win.show_all(); + }); + uiapp.run(&env::args().collect::>()); +} diff --git a/examples/plain_sourceview.rs b/examples/plain_sourceview.rs new file mode 100644 index 0000000..bf69186 --- /dev/null +++ b/examples/plain_sourceview.rs @@ -0,0 +1,27 @@ +extern crate gio; +extern crate gtk; +extern crate sourceview; +use gio::prelude::*; +use gtk::prelude::*; +use sourceview::prelude::*; + +use std::env; + +fn main() { + let uiapp = gtk::Application::new( + None, + gio::ApplicationFlags::FLAGS_NONE, + ) + .expect("Application::new failed"); + uiapp.connect_activate(|app| { + let win = gtk::ApplicationWindow::new(app); + win.set_default_size(320, 200); + win.set_title("Basic example"); + + let sourceview = sourceview::View::new(); + win.add(&sourceview); + + win.show_all(); + }); + uiapp.run(&env::args().collect::>()); +} diff --git a/src/completion_provider.rs b/src/completion_provider.rs index dd8e4ea..1c00d11 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -4,8 +4,8 @@ use crate::CompletionInfo; use crate::CompletionProposal; use crate::CompletionProvider; use glib::prelude::*; -use glib::translate::*; use glib::subclass::prelude::*; +use glib::translate::*; use once_cell::sync::Lazy; pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { @@ -45,7 +45,10 @@ pub trait CompletionProviderImpl: ObjectImpl + Send + 'static { } unsafe impl IsImplementable for CompletionProvider { - unsafe extern "C" fn interface_init(iface: glib::glib_sys::gpointer, _iface_data: glib::glib_sys::gpointer) { + unsafe extern "C" fn interface_init( + iface: glib::glib_sys::gpointer, + _iface_data: glib::glib_sys::gpointer, + ) { let iface = &mut *(iface as *mut gtk_source_sys::GtkSourceCompletionProviderIface); iface.get_name = Some(completion_provider_get_name::); iface.get_icon = Some(completion_provider_get_icon::); @@ -63,31 +66,36 @@ unsafe impl IsImplementable for C } } -unsafe extern "C" fn completion_provider_get_name(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *const libc::c_char{ +unsafe extern "C" fn completion_provider_get_name( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> *const libc::c_char { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.get_name(&from_glib_borrow(completion_provider)).to_glib_full() + imp.get_name(&from_glib_borrow(completion_provider)) + .to_glib_full() } -static COMPLETION_PROVIDER_ICON_QUARK: Lazy = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon")); +static COMPLETION_PROVIDER_ICON_QUARK: Lazy = + Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon")); -unsafe extern "C" fn completion_provider_get_icon(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *mut gdk_pixbuf_sys::GdkPixbuf{ +unsafe extern "C" fn completion_provider_get_icon( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> *mut gdk_pixbuf_sys::GdkPixbuf { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); let ret = imp.get_icon(&from_glib_borrow(completion_provider)); - let ret_ptr = match ret{ + let ret_ptr = match ret { Some(ref ret) => ret.as_ptr(), - None => std::ptr::null_mut() + None => std::ptr::null_mut(), }; - let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_ICON_QUARK.to_glib()); + let old_ptr = gobject_sys::g_object_get_qdata( + completion_provider as *mut _, + COMPLETION_PROVIDER_ICON_QUARK.to_glib(), + ); if !old_ptr.is_null() { - assert_eq!( - old_ptr as *mut _, - ret_ptr, - "Did not return same icon again" - ); + assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same icon again"); } gobject_sys::g_object_set_qdata_full( @@ -100,23 +108,30 @@ unsafe extern "C" fn completion_provider_get_icon = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon-name")); +static COMPLETION_PROVIDER_ICON_NAME_QUARK: Lazy = + Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-icon-name")); -unsafe extern "C" fn completion_provider_get_icon_name(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *const libc::c_char{ +unsafe extern "C" fn completion_provider_get_icon_name< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> *const libc::c_char { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); let ret = imp.get_icon_name(&from_glib_borrow(completion_provider)); - let ret_ptr = match ret{ + let ret_ptr = match ret { Some(ref ret) => ret.as_ptr(), - None => std::ptr::null() + None => std::ptr::null(), }; - let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_ICON_NAME_QUARK.to_glib()); + let old_ptr = gobject_sys::g_object_get_qdata( + completion_provider as *mut _, + COMPLETION_PROVIDER_ICON_NAME_QUARK.to_glib(), + ); if !old_ptr.is_null() { assert_eq!( - old_ptr as *const _, - ret_ptr, + old_ptr as *const _, ret_ptr, "Did not return same icon again" ); } @@ -131,25 +146,27 @@ unsafe extern "C" fn completion_provider_get_icon_name = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-gicon")); +static COMPLETION_PROVIDER_GICON_QUARK: Lazy = + Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-gicon")); -unsafe extern "C" fn completion_provider_get_gicon(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> *mut gio_sys::GIcon{ +unsafe extern "C" fn completion_provider_get_gicon( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> *mut gio_sys::GIcon { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); let ret = imp.get_gicon(&from_glib_borrow(completion_provider)); - let ret_ptr = match ret{ + let ret_ptr = match ret { Some(ref ret) => ret.as_ptr(), - None => std::ptr::null_mut() + None => std::ptr::null_mut(), }; - let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_GICON_QUARK.to_glib()); + let old_ptr = gobject_sys::g_object_get_qdata( + completion_provider as *mut _, + COMPLETION_PROVIDER_GICON_QUARK.to_glib(), + ); if !old_ptr.is_null() { - assert_eq!( - old_ptr as *mut _, - ret_ptr, - "Did not return same icon again" - ); + assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same icon again"); } gobject_sys::g_object_set_qdata_full( @@ -162,43 +179,71 @@ unsafe extern "C" fn completion_provider_get_gicon(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext){ +unsafe extern "C" fn completion_provider_populate( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + context: *mut gtk_source_sys::GtkSourceCompletionContext, +) { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.populate(&from_glib_borrow(completion_provider), &from_glib_borrow(context)) + imp.populate( + &from_glib_borrow(completion_provider), + &from_glib_borrow(context), + ) } -unsafe extern "C" fn completion_provider_get_activation(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> gtk_source_sys::GtkSourceCompletionActivation{ +unsafe extern "C" fn completion_provider_get_activation< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> gtk_source_sys::GtkSourceCompletionActivation { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.get_activation(&from_glib_borrow(completion_provider)).to_glib() + imp.get_activation(&from_glib_borrow(completion_provider)) + .to_glib() } -unsafe extern "C" fn completion_provider_provide_match(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext) -> glib_sys::gboolean{ +unsafe extern "C" fn completion_provider_provide_match< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + context: *mut gtk_source_sys::GtkSourceCompletionContext, +) -> glib_sys::gboolean { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.provide_match(&from_glib_borrow(completion_provider), &from_glib_borrow(context)).to_glib() + imp.provide_match( + &from_glib_borrow(completion_provider), + &from_glib_borrow(context), + ) + .to_glib() } -static COMPLETION_PROVIDER_INFO_WIDGET: Lazy = Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-info-widget")); +static COMPLETION_PROVIDER_INFO_WIDGET: Lazy = + Lazy::new(|| glib::Quark::from_string("gtk-sourceview-subclass-info-widget")); -unsafe extern "C" fn completion_provider_get_info_widget(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal) -> *mut gtk_sys::GtkWidget{ +unsafe extern "C" fn completion_provider_get_info_widget< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, +) -> *mut gtk_sys::GtkWidget { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - let ret = imp.get_info_widget(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal)); - let ret_ptr = match ret{ + let ret = imp.get_info_widget( + &from_glib_borrow(completion_provider), + &from_glib_borrow(proposal), + ); + let ret_ptr = match ret { Some(ref ret) => ret.as_ptr(), - None => std::ptr::null_mut() + None => std::ptr::null_mut(), }; - let old_ptr = gobject_sys::g_object_get_qdata(completion_provider as *mut _, COMPLETION_PROVIDER_INFO_WIDGET.to_glib()); + let old_ptr = gobject_sys::g_object_get_qdata( + completion_provider as *mut _, + COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), + ); if !old_ptr.is_null() { - assert_eq!( - old_ptr as *mut _, - ret_ptr, - "Did not return same icon again" - ); + assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same icon again"); } gobject_sys::g_object_set_qdata_full( @@ -209,34 +254,73 @@ unsafe extern "C" fn completion_provider_get_info_widget(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, completion_info: *mut gtk_source_sys::GtkSourceCompletionInfo) { +unsafe extern "C" fn completion_provider_update_info( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, + completion_info: *mut gtk_source_sys::GtkSourceCompletionInfo, +) { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.update_info(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal), &from_glib_borrow(completion_info)) + imp.update_info( + &from_glib_borrow(completion_provider), + &from_glib_borrow(proposal), + &from_glib_borrow(completion_info), + ) } -unsafe extern "C" fn completion_provider_get_start_iter(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, iter: *mut gtk_sys::GtkTextIter) -> glib_sys::gboolean{ +unsafe extern "C" fn completion_provider_get_start_iter< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + context: *mut gtk_source_sys::GtkSourceCompletionContext, + proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, + iter: *mut gtk_sys::GtkTextIter, +) -> glib_sys::gboolean { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.get_start_iter(&from_glib_borrow(completion_provider), &from_glib_borrow(context), &from_glib_borrow(proposal), &from_glib_borrow(iter)).to_glib() + imp.get_start_iter( + &from_glib_borrow(completion_provider), + &from_glib_borrow(context), + &from_glib_borrow(proposal), + &from_glib_borrow(iter), + ) + .to_glib() } -unsafe extern "C" fn completion_provider_activate_proposal(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, iter: *mut gtk_sys::GtkTextIter) -> glib_sys::gboolean{ +unsafe extern "C" fn completion_provider_activate_proposal< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, + proposal: *mut gtk_source_sys::GtkSourceCompletionProposal, + iter: *mut gtk_sys::GtkTextIter, +) -> glib_sys::gboolean { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); - imp.activate_proposal(&from_glib_borrow(completion_provider), &from_glib_borrow(proposal), &from_glib_borrow(iter)).to_glib() + imp.activate_proposal( + &from_glib_borrow(completion_provider), + &from_glib_borrow(proposal), + &from_glib_borrow(iter), + ) + .to_glib() } -unsafe extern "C" fn completion_provider_get_interactive_delay(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> libc::c_int{ +unsafe extern "C" fn completion_provider_get_interactive_delay< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> libc::c_int { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); imp.get_interactive_delay(&from_glib_borrow(completion_provider)) } -unsafe extern "C" fn completion_provider_get_priority(completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider) -> libc::c_int{ +unsafe extern "C" fn completion_provider_get_priority< + T: ObjectSubclass + CompletionProviderImpl, +>( + completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, +) -> libc::c_int { let instance = &*(completion_provider as *mut T::Instance); let imp = instance.get_impl(); imp.get_priority(&from_glib_borrow(completion_provider)) @@ -244,4 +328,4 @@ unsafe extern "C" fn completion_provider_get_priority Date: Thu, 28 May 2020 10:53:08 -0500 Subject: [PATCH 07/15] Added unsafe but working subclass for custom autocompletion (it has undefined behaviour) --- Cargo.toml | 5 +- examples/autocomplete_words.rs | 12 +- examples/custom_autocompletion_subclass.rs | 172 +++++++++++++++++++++ examples/plain_sourceview.rs | 7 +- src/completion_provider.rs | 9 +- 5 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 examples/custom_autocompletion_subclass.rs diff --git a/Cargo.toml b/Cargo.toml index 4527b0a..bb56618 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,4 +94,7 @@ git = "https://github.com/gtk-rs/gio" gir-format-check = "^0.1" [dev-dependencies.gtk] -git = "https://github.com/gtk-rs/gtk" \ No newline at end of file +git = "https://github.com/gtk-rs/gtk" + +[dev-dependencies.glib] +git = "https://github.com/gtk-rs/glib" \ No newline at end of file diff --git a/examples/autocomplete_words.rs b/examples/autocomplete_words.rs index ec45563..23add56 100644 --- a/examples/autocomplete_words.rs +++ b/examples/autocomplete_words.rs @@ -8,11 +8,8 @@ use sourceview::prelude::*; use std::env; fn main() { - let uiapp = gtk::Application::new( - None, - gio::ApplicationFlags::FLAGS_NONE, - ) - .expect("Application::new failed"); + let uiapp = gtk::Application::new(None, gio::ApplicationFlags::FLAGS_NONE) + .expect("Application::new failed"); uiapp.connect_activate(|app| { let win = gtk::ApplicationWindow::new(app); win.set_default_size(320, 200); @@ -21,7 +18,10 @@ fn main() { let sourceview = sourceview::View::new(); let completion = sourceview::CompletionWords::new(Some("Words"), None); completion.register(&sourceview.get_buffer().expect("Sourceview has no buffer.")); - sourceview.get_completion().expect("Sourceview has no completion").add_provider(&completion); + sourceview + .get_completion() + .expect("Sourceview has no completion") + .add_provider(&completion); win.add(&sourceview); win.show_all(); diff --git a/examples/custom_autocompletion_subclass.rs b/examples/custom_autocompletion_subclass.rs new file mode 100644 index 0000000..2da4dc8 --- /dev/null +++ b/examples/custom_autocompletion_subclass.rs @@ -0,0 +1,172 @@ +extern crate gio; +extern crate glib; +extern crate gtk; +extern crate sourceview; + +use gio::prelude::*; +use glib::glib_object_wrapper; +use glib::subclass::types::ObjectSubclass; +use glib::translate::*; +use gtk::prelude::*; +use sourceview::prelude::*; + +use glib::subclass::object::ObjectImpl; +use glib::GString; +use sourceview::{CompletionInfo, CompletionProvider}; +use std::env; + +fn main() { + let uiapp = gtk::Application::new(None, gio::ApplicationFlags::FLAGS_NONE) + .expect("Application::new failed"); + uiapp.connect_activate(|app| { + let win = gtk::ApplicationWindow::new(app); + win.set_default_size(320, 200); + win.set_title("Basic example"); + + let sourceview = sourceview::View::new(); + let completion = CustomAutocomplete::new(); + sourceview + .get_completion() + .expect("Sourceview has no completion") + .add_provider(&completion); + win.add(&sourceview); + + win.show_all(); + }); + uiapp.run(&env::args().collect::>()); +} + +glib::glib_wrapper! { + pub struct CustomAutocomplete(Object, glib::subclass::simple::ClassStruct, CustomAutocompleteClass>) @implements crate::CompletionProvider; + + match fn { + get_type => || imp::CustomAutocomplete::get_type().to_glib(), + } +} + +impl CustomAutocomplete { + fn new() -> CustomAutocomplete { + glib::Object::new(Self::static_type(), &[]) + .expect("Failed to create CustomAutocomplete instance.") + .downcast() + .expect("Created CustomAutocomplete is of wrong type.") + } +} + +mod imp { + use super::*; + use sourceview::CompletionProposal; + + pub struct CustomAutocomplete; + + impl ObjectSubclass for CustomAutocomplete { + const NAME: &'static str = "CustomAutocomplete"; + type ParentType = glib::Object; + type Instance = glib::subclass::simple::InstanceStruct; + type Class = glib::subclass::simple::ClassStruct; + + glib::glib_object_subclass!(); + + fn type_init(type_: &mut glib::subclass::InitializingType) { + type_.add_interface::(); + } + + fn new() -> Self { + CustomAutocomplete + } + } + + impl ObjectImpl for CustomAutocomplete { + glib::glib_object_impl!(); + } + + impl sourceview::CompletionProviderImpl for CustomAutocomplete { + fn get_name(&self, obj: &CompletionProvider) -> GString { + GString::from("CustomAutocomplete") + } + + fn get_icon(&self, obj: &CompletionProvider) -> Option { + None + } + + fn get_icon_name(&self, obj: &CompletionProvider) -> Option { + None + } + + fn get_gicon(&self, obg: &CompletionProvider) -> Option { + None + } + + fn populate(&self, obg: &CompletionProvider, context: &sourceview::CompletionContext) { + for i in 1..10 { + let item = sourceview::CompletionItem::new( + &format!("Test {}", i), + &format!("Test {};", i), + None, + Some("This is a test proposal"), + ); + context.add_proposals(obg, &[item.upcast::()], i == 9); + } + } + + fn get_activation(&self, obg: &CompletionProvider) -> sourceview::CompletionActivation { + sourceview::CompletionActivation::all() + } + + fn provide_match( + &self, + obg: &CompletionProvider, + context: &sourceview::CompletionContext, + ) -> bool { + true + } + + fn get_info_widget( + &self, + obg: &CompletionProvider, + proposal: &sourceview::CompletionProposal, + ) -> Option { + let label = gtk::Label::new(Some(match proposal.get_label() { + Some(ref label_text_gstring) => label_text_gstring.as_str(), + None => "", + })); + + Some(label.upcast::()) + } + + fn update_info( + &self, + obg: &CompletionProvider, + proposal: &sourceview::CompletionProposal, + info: &CompletionInfo, + ) { + } + + fn get_start_iter( + &self, + obg: &CompletionProvider, + context: &sourceview::CompletionContext, + proposal: &sourceview::CompletionProposal, + iter: >k::TextIter, + ) -> bool { + false + } + + fn activate_proposal( + &self, + obg: &CompletionProvider, + proposal: &sourceview::CompletionProposal, + iter: >k::TextIter, + ) -> bool { + false + } + + fn get_interactive_delay(&self, obj: &CompletionProvider) -> i32 { + 0 + } + + fn get_priority(&self, obg: &CompletionProvider) -> i32 { + 1 + } + } +} diff --git a/examples/plain_sourceview.rs b/examples/plain_sourceview.rs index bf69186..598435e 100644 --- a/examples/plain_sourceview.rs +++ b/examples/plain_sourceview.rs @@ -8,11 +8,8 @@ use sourceview::prelude::*; use std::env; fn main() { - let uiapp = gtk::Application::new( - None, - gio::ApplicationFlags::FLAGS_NONE, - ) - .expect("Application::new failed"); + let uiapp = gtk::Application::new(None, gio::ApplicationFlags::FLAGS_NONE) + .expect("Application::new failed"); uiapp.connect_activate(|app| { let win = gtk::ApplicationWindow::new(app); win.set_default_size(320, 200); diff --git a/src/completion_provider.rs b/src/completion_provider.rs index 1c00d11..40657a3 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -132,7 +132,7 @@ unsafe extern "C" fn completion_provider_get_icon_name< if !old_ptr.is_null() { assert_eq!( old_ptr as *const _, ret_ptr, - "Did not return same icon again" + "Did not return same icon name again" ); } @@ -166,7 +166,10 @@ unsafe extern "C" fn completion_provider_get_gicon Date: Thu, 28 May 2020 13:44:55 -0500 Subject: [PATCH 08/15] Fixed undefined behaviour --- examples/custom_autocompletion_subclass.rs | 7 +------ src/completion_provider.rs | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/custom_autocompletion_subclass.rs b/examples/custom_autocompletion_subclass.rs index 2da4dc8..2b4e719 100644 --- a/examples/custom_autocompletion_subclass.rs +++ b/examples/custom_autocompletion_subclass.rs @@ -126,12 +126,7 @@ mod imp { obg: &CompletionProvider, proposal: &sourceview::CompletionProposal, ) -> Option { - let label = gtk::Label::new(Some(match proposal.get_label() { - Some(ref label_text_gstring) => label_text_gstring.as_str(), - None => "", - })); - - Some(label.upcast::()) + None } fn update_info( diff --git a/src/completion_provider.rs b/src/completion_provider.rs index 40657a3..b3665c1 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -246,7 +246,7 @@ unsafe extern "C" fn completion_provider_get_info_widget< COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), ); if !old_ptr.is_null() { - //assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same info widget again"); + assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same info widget again"); } gobject_sys::g_object_set_qdata_full( From f6a60964d23c6eaf30b75160bb620fc3c572c8ce Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 28 May 2020 13:58:39 -0500 Subject: [PATCH 09/15] Fixed naming bug --- src/completion_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/completion_provider.rs b/src/completion_provider.rs index b3665c1..b83f15d 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -56,7 +56,7 @@ unsafe impl IsImplementable for C iface.get_gicon = Some(completion_provider_get_gicon::); iface.populate = Some(completion_provider_populate::); iface.get_activation = Some(completion_provider_get_activation::); - iface.match_ = Some(completion_provider_provide_match::); + iface.match_ = Some(completion_provider_match::); iface.get_info_widget = Some(completion_provider_get_info_widget::); iface.update_info = Some(completion_provider_update_info::); iface.get_start_iter = Some(completion_provider_get_start_iter::); @@ -205,7 +205,7 @@ unsafe extern "C" fn completion_provider_get_activation< .to_glib() } -unsafe extern "C" fn completion_provider_provide_match< +unsafe extern "C" fn completion_provider_match< T: ObjectSubclass + CompletionProviderImpl, >( completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, From f90125894af62e1ad324a4295440aa2a89399dcb Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 28 May 2020 13:59:59 -0500 Subject: [PATCH 10/15] Fixed warnings --- examples/custom_autocompletion_subclass.rs | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/custom_autocompletion_subclass.rs b/examples/custom_autocompletion_subclass.rs index 2b4e719..c467ad1 100644 --- a/examples/custom_autocompletion_subclass.rs +++ b/examples/custom_autocompletion_subclass.rs @@ -25,7 +25,7 @@ fn main() { let sourceview = sourceview::View::new(); let completion = CustomAutocomplete::new(); - sourceview + let _ = sourceview .get_completion() .expect("Sourceview has no completion") .add_provider(&completion); @@ -81,19 +81,19 @@ mod imp { } impl sourceview::CompletionProviderImpl for CustomAutocomplete { - fn get_name(&self, obj: &CompletionProvider) -> GString { + fn get_name(&self, _obj: &CompletionProvider) -> GString { GString::from("CustomAutocomplete") } - fn get_icon(&self, obj: &CompletionProvider) -> Option { + fn get_icon(&self, _obj: &CompletionProvider) -> Option { None } - fn get_icon_name(&self, obj: &CompletionProvider) -> Option { + fn get_icon_name(&self, _obj: &CompletionProvider) -> Option { None } - fn get_gicon(&self, obg: &CompletionProvider) -> Option { + fn get_gicon(&self, _obg: &CompletionProvider) -> Option { None } @@ -109,58 +109,58 @@ mod imp { } } - fn get_activation(&self, obg: &CompletionProvider) -> sourceview::CompletionActivation { + fn get_activation(&self, _obg: &CompletionProvider) -> sourceview::CompletionActivation { sourceview::CompletionActivation::all() } fn provide_match( &self, - obg: &CompletionProvider, - context: &sourceview::CompletionContext, + _obg: &CompletionProvider, + _context: &sourceview::CompletionContext, ) -> bool { true } fn get_info_widget( &self, - obg: &CompletionProvider, - proposal: &sourceview::CompletionProposal, + _obg: &CompletionProvider, + _proposal: &sourceview::CompletionProposal, ) -> Option { None } fn update_info( &self, - obg: &CompletionProvider, - proposal: &sourceview::CompletionProposal, - info: &CompletionInfo, + _obg: &CompletionProvider, + _proposal: &sourceview::CompletionProposal, + _info: &CompletionInfo, ) { } fn get_start_iter( &self, - obg: &CompletionProvider, - context: &sourceview::CompletionContext, - proposal: &sourceview::CompletionProposal, - iter: >k::TextIter, + _obg: &CompletionProvider, + _context: &sourceview::CompletionContext, + _proposal: &sourceview::CompletionProposal, + _iter: >k::TextIter, ) -> bool { false } fn activate_proposal( &self, - obg: &CompletionProvider, - proposal: &sourceview::CompletionProposal, - iter: >k::TextIter, + _obg: &CompletionProvider, + _proposal: &sourceview::CompletionProposal, + _iter: >k::TextIter, ) -> bool { false } - fn get_interactive_delay(&self, obj: &CompletionProvider) -> i32 { + fn get_interactive_delay(&self, _obj: &CompletionProvider) -> i32 { 0 } - fn get_priority(&self, obg: &CompletionProvider) -> i32 { + fn get_priority(&self, _obg: &CompletionProvider) -> i32 { 1 } } From 74d56d69693cbfd938abf5cad603307a22d447d3 Mon Sep 17 00:00:00 2001 From: john01dav Date: Thu, 28 May 2020 17:42:18 -0500 Subject: [PATCH 11/15] Ran cargo fmt --- src/completion_provider.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/completion_provider.rs b/src/completion_provider.rs index b83f15d..1b5a2cf 100644 --- a/src/completion_provider.rs +++ b/src/completion_provider.rs @@ -205,9 +205,7 @@ unsafe extern "C" fn completion_provider_get_activation< .to_glib() } -unsafe extern "C" fn completion_provider_match< - T: ObjectSubclass + CompletionProviderImpl, ->( +unsafe extern "C" fn completion_provider_match( completion_provider: *mut gtk_source_sys::GtkSourceCompletionProvider, context: *mut gtk_source_sys::GtkSourceCompletionContext, ) -> glib_sys::gboolean { @@ -246,7 +244,10 @@ unsafe extern "C" fn completion_provider_get_info_widget< COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), ); if !old_ptr.is_null() { - assert_eq!(old_ptr as *mut _, ret_ptr, "Did not return same info widget again"); + assert_eq!( + old_ptr as *mut _, ret_ptr, + "Did not return same info widget again" + ); } gobject_sys::g_object_set_qdata_full( From f82bb0cf956194fb33ee81e49a7a94640c57f190 Mon Sep 17 00:00:00 2001 From: john01dav Date: Fri, 29 May 2020 12:48:24 -0500 Subject: [PATCH 12/15] Moved completion provider subclass infrastructure into subclass module --- examples/custom_autocompletion_subclass.rs | 3 ++- examples/plain_sourceview.rs | 1 - src/lib.rs | 4 ++-- src/{ => subclass}/completion_provider.rs | 0 src/subclass/mod.rs | 2 ++ 5 files changed, 6 insertions(+), 4 deletions(-) rename src/{ => subclass}/completion_provider.rs (100%) create mode 100644 src/subclass/mod.rs diff --git a/examples/custom_autocompletion_subclass.rs b/examples/custom_autocompletion_subclass.rs index c467ad1..8c72d08 100644 --- a/examples/custom_autocompletion_subclass.rs +++ b/examples/custom_autocompletion_subclass.rs @@ -9,6 +9,7 @@ use glib::subclass::types::ObjectSubclass; use glib::translate::*; use gtk::prelude::*; use sourceview::prelude::*; +use sourceview::subclass::CompletionProviderImpl; use glib::subclass::object::ObjectImpl; use glib::GString; @@ -80,7 +81,7 @@ mod imp { glib::glib_object_impl!(); } - impl sourceview::CompletionProviderImpl for CustomAutocomplete { + impl CompletionProviderImpl for CustomAutocomplete { fn get_name(&self, _obj: &CompletionProvider) -> GString { GString::from("CustomAutocomplete") } diff --git a/examples/plain_sourceview.rs b/examples/plain_sourceview.rs index 598435e..3cb1dce 100644 --- a/examples/plain_sourceview.rs +++ b/examples/plain_sourceview.rs @@ -3,7 +3,6 @@ extern crate gtk; extern crate sourceview; use gio::prelude::*; use gtk::prelude::*; -use sourceview::prelude::*; use std::env; diff --git a/src/lib.rs b/src/lib.rs index 796c792..4a89a46 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,6 @@ extern crate bitflags; pub use auto::*; pub use completion::*; pub use completion_info::*; -pub use completion_provider::*; #[cfg(any(feature = "v3_14", feature = "dox"))] pub use file_loader::*; #[cfg(any(feature = "v3_14", feature = "dox"))] @@ -58,13 +57,14 @@ pub mod prelude { pub use file_saver::FileSaverExtManual; } +pub mod subclass; + #[macro_use] mod rt; mod auto; mod completion; mod completion_info; -mod completion_provider; #[cfg(any(feature = "v3_14", feature = "dox"))] mod file_loader; #[cfg(any(feature = "v3_14", feature = "dox"))] diff --git a/src/completion_provider.rs b/src/subclass/completion_provider.rs similarity index 100% rename from src/completion_provider.rs rename to src/subclass/completion_provider.rs diff --git a/src/subclass/mod.rs b/src/subclass/mod.rs new file mode 100644 index 0000000..88e6965 --- /dev/null +++ b/src/subclass/mod.rs @@ -0,0 +1,2 @@ +mod completion_provider; +pub use self::completion_provider::*; From 112fee8c7619cc99d13b57f7043ea79b2ff8b071 Mon Sep 17 00:00:00 2001 From: john01dav Date: Fri, 29 May 2020 12:50:08 -0500 Subject: [PATCH 13/15] Fixed bug where the custom widget had to be the same for each call to get_info_widget, even when the proposal differs --- src/subclass/completion_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/subclass/completion_provider.rs b/src/subclass/completion_provider.rs index 1b5a2cf..3298245 100644 --- a/src/subclass/completion_provider.rs +++ b/src/subclass/completion_provider.rs @@ -240,7 +240,7 @@ unsafe extern "C" fn completion_provider_get_info_widget< }; let old_ptr = gobject_sys::g_object_get_qdata( - completion_provider as *mut _, + proposal as *mut _, COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), ); if !old_ptr.is_null() { @@ -251,7 +251,7 @@ unsafe extern "C" fn completion_provider_get_info_widget< } gobject_sys::g_object_set_qdata_full( - completion_provider as *mut _, + proposal as *mut _, COMPLETION_PROVIDER_INFO_WIDGET.to_glib(), ret_ptr as *mut libc::c_void, Some(unref), From b8970bd8ceae668ce13b5b5da7b40eeeaa488515 Mon Sep 17 00:00:00 2001 From: john01dav Date: Fri, 29 May 2020 12:55:34 -0500 Subject: [PATCH 14/15] Fixed quark usage to handle the None case properly --- src/subclass/completion_provider.rs | 56 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/subclass/completion_provider.rs b/src/subclass/completion_provider.rs index 3298245..ffaa8e6 100644 --- a/src/subclass/completion_provider.rs +++ b/src/subclass/completion_provider.rs @@ -98,12 +98,14 @@ unsafe extern "C" fn completion_provider_get_icon Date: Fri, 29 May 2020 21:16:15 -0500 Subject: [PATCH 15/15] Fixed type inference error and double free --- src/subclass/completion_provider.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/subclass/completion_provider.rs b/src/subclass/completion_provider.rs index ffaa8e6..2bc99ee 100644 --- a/src/subclass/completion_provider.rs +++ b/src/subclass/completion_provider.rs @@ -102,7 +102,7 @@ unsafe extern "C" fn completion_provider_get_icon