diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/py_provider.py b/src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py similarity index 86% rename from src/core/widgets/base/sourceview/custom_completion_providers/py_provider.py rename to src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py index 9a9e772..a363516 100644 --- a/src/core/widgets/base/sourceview/custom_completion_providers/py_provider.py +++ b/src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py @@ -14,15 +14,19 @@ from gi.repository import GObject -class PythonProvider(GObject.GObject, GtkSource.CompletionProvider): +class ExampleCompletionProvider(GObject.GObject, GtkSource.CompletionProvider): """ - This is a custom Completion Provider for Python. + This is a custom Completion Example Provider. # NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/ """ + __gtype_name__ = 'CustomProvider' + + def __init__(self): + GObject.Object.__init__(self) def do_get_name(self): """ Returns: a new string containing the name of the provider. """ - return 'PythonProvider' + return _('ExampleProvider') def do_match(self, context): """ Get whether the provider match the context of completion detailed in context. """ @@ -45,7 +49,7 @@ class PythonProvider(GObject.GObject, GtkSource.CompletionProvider): # GtkSource.CompletionItem(label='Hello World!', text = 'Hello World!', icon = None, info = None) # NOTE: Always proposed... ] - # Gtk Versions differ on get_iter responses... + # Gtk Versions differ on get_iter responses... end_iter = context.get_iter() if not isinstance(end_iter, Gtk.TextIter): _, end_iter = context.get_iter() @@ -67,4 +71,4 @@ class PythonProvider(GObject.GObject, GtkSource.CompletionProvider): GtkSource.CompletionItem(label='bar', text='bar }}') # optionally proposed based on left search via regex ) - context.add_proposals(self, proposals, True) + context.add_proposals(self, proposals, True) \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/gedi_completion_provider.py b/src/core/widgets/base/sourceview/custom_completion_providers/gedi_completion_provider.py new file mode 100644 index 0000000..6e0ba9f --- /dev/null +++ b/src/core/widgets/base/sourceview/custom_completion_providers/gedi_completion_provider.py @@ -0,0 +1,102 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('GtkSource', '4') + +from gi.repository import Gtk +from gi.repository import GtkSource +from gi.repository import GObject + +from jedi.api import Script + +# Application imports + + + +# FIXME: Find real icon names... +icon_names = { + 'import': '', + 'module': '', + 'class': '', + 'function': '', + 'statement': '', + 'param': '' +} + + +class Jedi: + def get_script(file, buffer): + doc_text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False) + iter_cursor = buffer.get_iter_at_mark(buffer.get_insert()) + linenum = iter_cursor.get_line() + 1 + charnum = iter_cursor.get_line_index() + return Script(code = doc_text, path = file) + + +class GediCompletionProvider(GObject.Object, GtkSource.CompletionProvider): + """ + This code is A python code completion plugin for Gedit that's been modified accordingly to work for Newton. + # NOTE: Code pulled from here --> https://github.com/isamert/gedi + """ + __gtype_name__ = 'GediProvider' + + def __init__(self, file): + GObject.Object.__init__(self) + self._theme = Gtk.IconTheme.get_default() + self._file = file + + def do_get_name(self): + return _("Gedi Python Code Completion") + + def get_iter_correctly(self, context): + if isinstance(context.get_iter(), tuple): + return context.get_iter()[1]; + else: + return context.get_iter() + + def do_match(self, context): + iter = self.get_iter_correctly(context) + iter.backward_char() + buffer = iter.get_buffer() + if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']: + return False + ch = iter.get_char() + if not (ch in ('_', '.') or ch.isalnum()): + return False + + return True + + def do_get_priority(self): + return 1 + + def do_get_activation(self): + return GtkSource.CompletionActivation.INTERACTIVE + + def do_populate(self, context): + # TODO: Convert async maybe? + it = self.get_iter_correctly(context) + document = it.get_buffer() + proposals = [] + + # for completion in Jedi.get_script(document).completions(): + for completion in Jedi.get_script(self._file, document).complete(): + complete = completion.name + doc = completion.doc if jedi.__version__ <= (0,7,0) else completion.docstring() + + proposals.append(GtkSource.CompletionItem.new(completion.name, + completion.name, + self.get_icon_for_type(completion.type), + doc)) + + context.add_proposals(self, proposals, True) + + def get_icon_for_type(self, _type): + try: + return self._theme.load_icon(icon_names[_type.lower()], 16, 0) + except: + try: + return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0) + except: + return None diff --git a/src/core/widgets/base/sourceview/source_view.py b/src/core/widgets/base/sourceview/source_view.py index e7d7545..0ff8896 100644 --- a/src/core/widgets/base/sourceview/source_view.py +++ b/src/core/widgets/base/sourceview/source_view.py @@ -12,7 +12,8 @@ from gi.repository import GtkSource # Application imports from .source_view_events import SourceViewEventsMixin -from .custom_completion_providers.py_provider import PythonProvider +from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider +from .custom_completion_providers.gedi_completion_provider import GediCompletionProvider @@ -78,13 +79,24 @@ class SourceView(SourceViewEventsMixin, GtkSource.View): self.connect("drag-data-received", self._on_drag_data_received) self._buffer.connect("mark-set", self._on_cursor_move) self._buffer.connect('changed', self._is_modified) + # self._buffer.connect("loaded", self.on_document_load) + def _document_loaded(self): + for provider in self._completion.get_providers(): + self._completion.remove_provider(provider) + + # TODO: actually load a meaningful provider based on file type... + file = self._current_file.get_path() word_completion = GtkSource.CompletionWords.new("word_completion") word_completion.register(self._buffer) self._completion.add_provider(word_completion) - py_provider = PythonProvider() - self._completion.add_provider(py_provider) + # example_completion_provider = ExampleCompletionProvider() + # self._completion.add_provider(example_completion_provider) + + gedi_completion_provider = GediCompletionProvider(file) + self._completion.add_provider(gedi_completion_provider) + def _subscribe_to_events(self): ... @@ -223,4 +235,4 @@ class SourceView(SourceViewEventsMixin, GtkSource.View): (self._current_filename != "" and not save_as): self.open_file(gfile) else: - event_system.emit("create_view", (None, None, gfile,)) \ No newline at end of file + event_system.emit("create_view", (None, None, gfile,)) diff --git a/src/core/widgets/base/sourceview/source_view_events.py b/src/core/widgets/base/sourceview/source_view_events.py index ea3b0c5..4c7540a 100644 --- a/src/core/widgets/base/sourceview/source_view_events.py +++ b/src/core/widgets/base/sourceview/source_view_events.py @@ -102,6 +102,7 @@ class SourceViewEventsMixin: def finish_load_callback(obj, res, user_data=None): self._file_loader.load_finish(res) self._is_changed = False + self._document_loaded() self._file_loader.load_async(io_priority = 98, cancellable = None,