Moved completers to new dir; improved completers and added word completion

This commit is contained in:
2026-02-16 01:39:23 -06:00
parent 5273c58ed6
commit b922415f98
35 changed files with 669 additions and 44 deletions

View File

@@ -0,0 +1,3 @@
"""
Pligin Module
"""

View File

@@ -0,0 +1,3 @@
"""
Pligin Package
"""

View File

@@ -0,0 +1,7 @@
{
"name": "Example Completer",
"author": "John Doe",
"version": "0.0.1",
"support": "",
"requests": {}
}

View File

@@ -0,0 +1,40 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from libs.dto.base_event import BaseEvent
from libs.event_factory import Event_Factory
from plugins.plugin_types import PluginCode
from .provider import Provider
class Plugin(PluginCode):
def __init__(self):
super(Plugin, self).__init__()
self.provider: Provider = None
def _controller_message(self, event: BaseEvent):
...
def load(self):
self.provider = Provider()
event = Event_Factory.create_event(
"register_provider",
provider_name = "Example Completer",
provider = self.provider,
language_ids = []
)
self.message_to("completion", event)
def run(self):
...

View File

@@ -0,0 +1,76 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GObject.GObject, GtkSource.CompletionProvider):
"""
This is a custom Completion Example Provider.
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
"""
__gtype_name__ = 'ExampleCompletionProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def do_get_name(self):
""" Returns: a new string containing the name of the provider. """
return 'Example Code Completion'
def do_match(self, context):
# word = context.get_word()
# if not word or len(word) < 2: return False
""" Get whether the provider match the context of completion detailed in context. """
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
return True
def do_get_priority(self):
""" Determin position in result list along other providor results. """
return 5
def do_activate_proposal(self, proposal, iter_):
""" Manually handle actual completion insert or set flags and handle normally. """
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
# return GtkSource.CompletionActivation.USER_REQUESTED
# return GtkSource.CompletionActivation.USER_REQUESTED | GtkSource.CompletionActivation.INTERACTIVE
return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context):
results = self.response_cache.filter_with_context(context)
proposals = []
for entry in results:
proposals.append(
self.response_cache.create_completion_item(
entry["label"],
entry["text"],
entry["info"]
)
)
context.add_proposals(self, proposals, True)

View File

@@ -0,0 +1,109 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
from libs.event_factory import Code_Event_Types
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
class ProviderResponseCache(ProviderResponseCacheBase):
def __init__(self):
super(ProviderResponseCache, self).__init__()
self.matchers: dict = {
"hello": {
"label": "Hello, World!",
"text": "Hello, World!",
"info": GLib.markup_escape_text( "<b>Says the first ever program developers write...</b>" )
},
"foo": {
"label": "foo",
"text": "foo }}"
},
"bar": {
"label": "bar",
"text": "bar }}"
}
}
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
...
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
...
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
...
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
...
def filter(self, word: str) -> list[dict]:
...
def filter_with_context(self, context) -> list[dict]:
"""
In this instance, it will do 2 things:
1) always provide Hello World! (Not ideal but an option so its in the example)
2) Utilizes the Gtk.TextIter from the TextBuffer to determine if there is a jinja
example of '{{ custom.' if so it will provide you with the options of foo and bar.
If selected it will insert foo }} or bar }}, completing your syntax...
PLEASE NOTE the GtkTextIter Logic and regex are really rough and should be adjusted and tuned
"""
proposals: list[dict] = [
{
"label": self.matchers[ "hello" ]["label"],
"text": self.matchers[ "hello" ]["text"],
"info": self.matchers[ "hello" ]["info"]
}
]
# Gtk Versions differ on get_iter responses...
end_iter = context.get_iter()
if not isinstance(end_iter, Gtk.TextIter):
_, end_iter = context.get_iter()
if not end_iter: return
buf = end_iter.get_buffer()
mov_iter = end_iter.copy()
if mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY):
mov_iter, _ = mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY)
left_text = buf.get_text(mov_iter, end_iter, True)
else:
left_text = ''
if re.match(r'.*\{\{\s*custom\.$', left_text):
# optionally proposed based on left search via regex
proposals.append(
{
"label": self.matchers[ "foo" ]["label"],
"text": self.matchers[ "foo" ]["text"],
"info": ""
}
)
# optionally proposed based on left search via regex
proposals.append(
{
"label": self.matchers[ "bar" ]["label"],
"text": self.matchers[ "bar" ]["text"],
"info": ""
}
)
return proposals