Added word completion and simplistic custom completion example
|
@ -29,7 +29,7 @@ def daemon_threaded_wrapper(fn):
|
||||||
|
|
||||||
# NOTE: Just reminding myself we can add to builtins two different ways...
|
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||||
# __builtins__.update({"event_system": Builtins()})
|
# __builtins__.update({"event_system": Builtins()})
|
||||||
builtins.app_name = "Newton_Editor"
|
builtins.app_name = "Newton"
|
||||||
builtins.keybindings = Keybindings()
|
builtins.keybindings = Keybindings()
|
||||||
builtins.event_system = EventSystem()
|
builtins.event_system = EventSystem()
|
||||||
builtins.endpoint_registry = EndpointRegistry()
|
builtins.endpoint_registry = EndpointRegistry()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
Custom Completion Providers Module
|
||||||
|
"""
|
|
@ -0,0 +1,70 @@
|
||||||
|
# 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 GtkSource
|
||||||
|
from gi.repository import GObject
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PythonProvider(GObject.GObject, GtkSource.CompletionProvider):
|
||||||
|
"""
|
||||||
|
This is a custom Completion Provider for Python.
|
||||||
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
|
"""
|
||||||
|
|
||||||
|
def do_get_name(self):
|
||||||
|
""" Returns: a new string containing the name of the provider. """
|
||||||
|
return 'PythonProvider'
|
||||||
|
|
||||||
|
def do_match(self, context):
|
||||||
|
""" Get whether the provider match the context of completion detailed in context. """
|
||||||
|
# NOTE: True for debugging but context needs to normally get checked for actual usage needs.
|
||||||
|
# TODO: Fix me
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_populate(self, context):
|
||||||
|
"""
|
||||||
|
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 = [
|
||||||
|
# GtkSource.CompletionItem(label='Hello World!', text = 'Hello World!', icon = None, info = None) # NOTE: Always proposed...
|
||||||
|
]
|
||||||
|
|
||||||
|
# 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 end_iter:
|
||||||
|
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):
|
||||||
|
proposals.append(
|
||||||
|
GtkSource.CompletionItem(label='foo', text='foo }}') # optionally proposed based on left search via regex
|
||||||
|
)
|
||||||
|
proposals.append(
|
||||||
|
GtkSource.CompletionItem(label='bar', text='bar }}') # optionally proposed based on left search via regex
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add_proposals(self, proposals, True)
|
|
@ -12,6 +12,7 @@ from gi.repository import GtkSource
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from .source_view_events import SourceViewEventsMixin
|
from .source_view_events import SourceViewEventsMixin
|
||||||
|
from .custom_completion_providers.py_provider import PythonProvider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self._current_filename: str = ""
|
self._current_filename: str = ""
|
||||||
self._file_loader = None
|
self._file_loader = None
|
||||||
self._buffer = self.get_buffer()
|
self._buffer = self.get_buffer()
|
||||||
|
self._completion = self.get_completion()
|
||||||
|
|
||||||
self._file_filter_text = Gtk.FileFilter()
|
self._file_filter_text = Gtk.FileFilter()
|
||||||
self._file_filter_text.set_name("Text Files")
|
self._file_filter_text.set_name("Text Files")
|
||||||
|
@ -76,8 +78,13 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self.connect("drag-data-received", self._on_drag_data_received)
|
self.connect("drag-data-received", self._on_drag_data_received)
|
||||||
self._buffer.connect("mark-set", self._on_cursor_move)
|
self._buffer.connect("mark-set", self._on_cursor_move)
|
||||||
self._buffer.connect('changed', self._is_modified)
|
self._buffer.connect('changed', self._is_modified)
|
||||||
# self.completion.add_provider(srcCompleteonSnippets)
|
|
||||||
# self.completion.add_provider(srcCompleteonWords)
|
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)
|
||||||
|
|
||||||
def _subscribe_to_events(self):
|
def _subscribe_to_events(self):
|
||||||
...
|
...
|
||||||
|
@ -188,7 +195,7 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
if self._current_filename == "":
|
if self._current_filename == "":
|
||||||
dlg.set_current_name("new.txt")
|
dlg.set_current_name("new.txt")
|
||||||
else:
|
else:
|
||||||
dlg.set_current_folder(self._current_file.get_parent())
|
dlg.set_current_folder(self._current_file.get_parent().get_path())
|
||||||
dlg.set_current_name(self._current_filename)
|
dlg.set_current_name(self._current_filename)
|
||||||
|
|
||||||
response = dlg.run()
|
response = dlg.run()
|
||||||
|
@ -212,7 +219,8 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
f.write(text)
|
f.write(text)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
if self._current_filename == "" and save_as:
|
if (self._current_filename == "" and save_as) or \
|
||||||
|
(self._current_filename != "" and not save_as):
|
||||||
self.open_file(gfile)
|
self.open_file(gfile)
|
||||||
else:
|
else:
|
||||||
event_system.emit("create_view", (None, None, gfile,))
|
event_system.emit("create_view", (None, None, gfile,))
|
|
@ -19,11 +19,11 @@ function main() {
|
||||||
|
|
||||||
# NOTE: Remove if you want to pass file(s) besides directories...
|
# NOTE: Remove if you want to pass file(s) besides directories...
|
||||||
if [ ! -d "${path}" ]; then
|
if [ ! -d "${path}" ]; then
|
||||||
echo "Newton Editor: Path given not a directory..."
|
echo "Newton: Path given not a directory..."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "/opt/"
|
cd "/opt/"
|
||||||
python /opt/newton_editor.zip "$@"
|
python /opt/newton.zip "$@"
|
||||||
}
|
}
|
||||||
main "$@";
|
main "$@";
|
|
@ -1,9 +1,9 @@
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Newton Editor
|
Name=Newton
|
||||||
GenericName=Code IDE
|
GenericName=Text editor and mini IDE
|
||||||
Comment=General purpose IDE
|
Comment=General purpose text editor and IDE
|
||||||
Exec=/bin/newton_editor %F
|
Exec=/bin/newton %F
|
||||||
Icon=/usr/share/newton_editor/icons/newton_editor.png
|
Icon=/usr/share/newton/icons/newton.png
|
||||||
Type=Application
|
Type=Application
|
||||||
StartupNotify=true
|
StartupNotify=true
|
||||||
Categories=GNOME;GTK;Utility;TextEditor;Development;
|
Categories=GNOME;GTK;Utility;TextEditor;Development;
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 858 B After Width: | Height: | Size: 858 B |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 850 B After Width: | Height: | Size: 850 B |
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 925 B After Width: | Height: | Size: 925 B |
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 882 B |
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 707 B |
Before Width: | Height: | Size: 798 B After Width: | Height: | Size: 798 B |
Before Width: | Height: | Size: 989 B After Width: | Height: | Size: 989 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |