generated from itdominator/Python-With-Gtk-Template
Compare commits
No commits in common. "c06df187a6ab81f3f6331bbb28efc4b89290d5e3" and "c5f0d8e59762b8344c2f19a92b4f963e88970535" have entirely different histories.
c06df187a6
...
c5f0d8e597
@ -1,5 +1,3 @@
|
||||
PyGObject
|
||||
pyxdg
|
||||
setproctitle
|
||||
python-lsp-server[all]
|
||||
python-lsp-server[websockets]
|
||||
|
@ -1,19 +1,10 @@
|
||||
# Python imports
|
||||
import urllib.parse as url_parse
|
||||
|
||||
# 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.dto.lsp_message_structs import LSPResponseTypes, LSPResponseRequest, LSPResponseNotification, LSPIDResponseNotification
|
||||
from .key_input_controller import KeyInputController
|
||||
from .editor_events import EditorEventsMixin
|
||||
from ...completion_item import CompletionItem
|
||||
|
||||
|
||||
|
||||
@ -39,117 +30,4 @@ class EditorControllerMixin(KeyInputController, EditorEventsMixin):
|
||||
if action == "set_buffer_language":
|
||||
self.set_buffer_language(source_view, query)
|
||||
if action == "set_buffer_style":
|
||||
self.set_buffer_style(source_view, query)
|
||||
|
||||
def _handle_lsp_message(self, message: dict or LSPResponseType):
|
||||
if not self.is_editor_focused: return # TODO: Find way to converge this
|
||||
page_num, container, source_view = self.get_active_view()
|
||||
page_num = None
|
||||
container = None
|
||||
|
||||
logger.debug( f"\n\n{repr(message)}\n\n" )
|
||||
|
||||
if isinstance(message, dict):
|
||||
...
|
||||
|
||||
if hasattr(message, "result"):
|
||||
if type(message.result) is dict:
|
||||
keys = message.result.keys()
|
||||
|
||||
if "items" in keys: # completion
|
||||
if source_view.completion_view.get_parent():
|
||||
source_view.remove(source_view.completion_view)
|
||||
|
||||
if len( message.result["items"] ) == 0:
|
||||
return
|
||||
|
||||
source_view.completion_view.clear_items()
|
||||
x, y = self._get_insert_line_xy(source_view)
|
||||
source_view.add_child_in_window(source_view.completion_view, Gtk.TextWindowType.WIDGET, x, y)
|
||||
completion_list = self.filter_completion_list( message.result["items"] )
|
||||
|
||||
for item in completion_list:
|
||||
ci = CompletionItem()
|
||||
ci.populate_completion_item(item)
|
||||
source_view.completion_view.add_completion_item(ci)
|
||||
|
||||
source_view.completion_view.show_all()
|
||||
GLib.idle_add( source_view.completion_view.select_first_row )
|
||||
|
||||
# completion = source_view.get_completion()
|
||||
# providers = completion.get_providers()
|
||||
|
||||
# for provider in providers:
|
||||
# if provider.__class__.__name__ == 'LSPCompletionProvider':
|
||||
# source_view.completion_items = message.result["items"]
|
||||
# source_view.emit("show-completion")
|
||||
|
||||
|
||||
if "result" in keys:
|
||||
...
|
||||
|
||||
if type(message.result) is list:
|
||||
if len(message.result) == 1: # goto/aka definition
|
||||
result = message.result[0]
|
||||
line = result["range"]["start"]["line"]
|
||||
uri = result["uri"].replace("file://", "")
|
||||
if "jdt:" in uri:
|
||||
uri = self.parse_java_jdt_to_uri(uri)
|
||||
|
||||
file = f"{uri}:{line}"
|
||||
event_system.emit("handle_file_from_ipc", file)
|
||||
|
||||
if hasattr(message, "method"):
|
||||
if message.method == "textDocument/publshDiagnostics":
|
||||
...
|
||||
|
||||
source_view = None
|
||||
|
||||
def parse_java_jdt_to_uri(self, uri):
|
||||
parse_str = url_parse.unquote(uri)
|
||||
post_stub, \
|
||||
pre_stub = parse_str.split("?=")
|
||||
|
||||
post_stub = post_stub.replace("jdt://contents/", "")
|
||||
replace_stub = post_stub[
|
||||
post_stub.index(".jar") + 4 : post_stub.index(".class")
|
||||
]
|
||||
post_stub = post_stub.replace(replace_stub, replace_stub.replace(".", "/") ) \
|
||||
.replace(".jar", "-sources.jar:")
|
||||
post_stub = post_stub.replace(".class", ".java")
|
||||
|
||||
pre_stub = pre_stub[
|
||||
pre_stub.index("/\\/") + 2 : pre_stub.index(".jar")
|
||||
]
|
||||
pre_stub = pre_stub[: pre_stub.rfind("/") + 1 ].replace("\\", "")
|
||||
|
||||
return f"file://{pre_stub}{post_stub}"
|
||||
|
||||
# Gotten logic from:
|
||||
# https://stackoverflow.com/questions/7139645/find-the-cursor-position-on-a-gtksourceview-window
|
||||
def _get_insert_line_xy(self, source_view):
|
||||
buffer = source_view.get_buffer()
|
||||
iter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
iter_loc = source_view.get_iter_location(iter)
|
||||
|
||||
win_loc = source_view.buffer_to_window_coords(Gtk.TextWindowType.WIDGET, iter_loc.x, iter_loc.y)
|
||||
|
||||
win = source_view.get_window( Gtk.TextWindowType.WIDGET )
|
||||
view_pos = win.get_position()
|
||||
|
||||
xx = win_loc[0] + view_pos[0]
|
||||
yy = win_loc[1] + view_pos[1] + iter_loc.height
|
||||
|
||||
return xx, yy
|
||||
|
||||
# Note: What I really need to do (long term) is keep all results and then just
|
||||
# toggle show/hide of the CompletionItems relevent to the request context.
|
||||
def filter_completion_list(self, completion_list: list) -> list:
|
||||
filtered_list = []
|
||||
|
||||
for item in completion_list:
|
||||
keys = item.keys()
|
||||
if "insertText" in keys or "textEdit" in keys:
|
||||
filtered_list.append(item)
|
||||
|
||||
return filtered_list
|
||||
self.set_buffer_style(source_view, query)
|
@ -43,7 +43,7 @@ class EditorEventsMixin:
|
||||
file_type = source_view.get_filetype()
|
||||
if not file_type == "buffer":
|
||||
uri = source_view.get_current_file().get_uri()
|
||||
event_system.emit("textDocument/didClose", (uri,))
|
||||
event_system.emit("textDocument/didClose", (file_type, uri,))
|
||||
|
||||
page_num = notebook.page_num(container)
|
||||
source_view._cancel_current_file_watchers()
|
||||
|
@ -1,5 +1,4 @@
|
||||
# Python imports
|
||||
import zipfile
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
@ -59,8 +58,6 @@ class EditorNotebook(EditorControllerMixin, Gtk.Notebook):
|
||||
self.connect("key-release-event", self._key_release_event)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("handle-lsp-message", self._handle_lsp_message)
|
||||
|
||||
event_system.subscribe("create_view", self._create_view)
|
||||
event_system.subscribe("set_buffer_style", self.action_controller)
|
||||
event_system.subscribe("set_buffer_language", self.action_controller)
|
||||
@ -123,22 +120,12 @@ class EditorNotebook(EditorControllerMixin, Gtk.Notebook):
|
||||
return
|
||||
|
||||
if isinstance(gfile, str):
|
||||
parts = gfile.replace("file://", "").split(":")
|
||||
if len(parts) > 2:
|
||||
with zipfile.ZipFile(parts[0], 'r') as file:
|
||||
file.extract(parts[1][1:], "/tmp/newton_extracts")
|
||||
|
||||
gfile = Gio.File.new_for_path( f"/tmp/newton_extracts/{ parts[1][1:] }" )
|
||||
try:
|
||||
line = int(parts[2])
|
||||
except Exception:
|
||||
...
|
||||
else:
|
||||
gfile = Gio.File.new_for_path(parts[0])
|
||||
try:
|
||||
line = int(parts[1]) if len(parts) > 1 else 0
|
||||
except Exception:
|
||||
...
|
||||
parts = gfile.split(":")
|
||||
gfile = Gio.File.new_for_path(parts[0])
|
||||
try:
|
||||
line = int(parts[1]) if len(parts) > 1 else 0
|
||||
except Exception:
|
||||
...
|
||||
|
||||
self.create_view(None, None, gfile, line)
|
||||
|
||||
|
@ -25,7 +25,7 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
|
||||
self._theme = Gtk.IconTheme.get_default()
|
||||
self._source_view = source_view
|
||||
|
||||
|
||||
|
||||
def do_get_name(self):
|
||||
return "LSP Code Completion"
|
||||
@ -34,21 +34,36 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter()
|
||||
|
||||
def do_match(self, context):
|
||||
iter = self.get_iter_correctly(context)
|
||||
buffer = iter.get_buffer()
|
||||
if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']:
|
||||
return False
|
||||
|
||||
ch = iter.get_char()
|
||||
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||
# As is it slows down the editor in certain contexts...
|
||||
if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||
# 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.USER_REQUESTED
|
||||
|
||||
def do_populate(self, context, items = []):
|
||||
if hasattr(self._source_view, "completion_items"):
|
||||
items = self._source_view.completion_items
|
||||
return GtkSource.CompletionActivation.INTERACTIVE
|
||||
|
||||
def do_populate(self, context, result = None):
|
||||
result = event_system.emit_and_await("textDocument/completion", (self._source_view,))
|
||||
proposals = []
|
||||
for item in items:
|
||||
proposals.append( self.create_completion_item(item) )
|
||||
|
||||
if result:
|
||||
if not result.items is None:
|
||||
for item in result.items:
|
||||
proposals.append( self.create_completion_item(item) )
|
||||
else:
|
||||
proposals.append( self.create_completion_item(result) )
|
||||
|
||||
context.add_proposals(self, proposals, True)
|
||||
|
||||
@ -67,31 +82,17 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
|
||||
def create_completion_item(self, item):
|
||||
comp_item = GtkSource.CompletionItem.new()
|
||||
keys = item.keys()
|
||||
comp_item.set_label(item["label"])
|
||||
comp_item.set_label(item.label)
|
||||
|
||||
if "insertText" in keys:
|
||||
comp_item.set_text(item["insertText"])
|
||||
if item.textEdit:
|
||||
if isinstance(item.textEdit, dict):
|
||||
comp_item.set_text(item.textEdit["newText"])
|
||||
else:
|
||||
comp_item.set_text(item.textEdit)
|
||||
else:
|
||||
comp_item.set_text(item.insertText)
|
||||
|
||||
if "additionalTextEdits" in keys:
|
||||
comp_item.additionalTextEdits = item["additionalTextEdits"]
|
||||
comp_item.set_icon( self.get_icon_for_type(item.kind) )
|
||||
comp_item.set_info(item.documentation)
|
||||
|
||||
return comp_item
|
||||
|
||||
|
||||
# def create_completion_item(self, item):
|
||||
# comp_item = GtkSource.CompletionItem.new()
|
||||
# comp_item.set_label(item.label)
|
||||
|
||||
# if item.textEdit:
|
||||
# if isinstance(item.textEdit, dict):
|
||||
# comp_item.set_text(item.textEdit["newText"])
|
||||
# else:
|
||||
# comp_item.set_text(item.textEdit)
|
||||
# else:
|
||||
# comp_item.set_text(item.insertText)
|
||||
|
||||
# comp_item.set_icon( self.get_icon_for_type(item.kind) )
|
||||
# comp_item.set_info(item.documentation)
|
||||
|
||||
# return comp_item
|
||||
return comp_item
|
@ -31,38 +31,12 @@ class KeyInputController:
|
||||
return True
|
||||
|
||||
if keyname in [ "slash", "Up", "Down", "m", "z", "y" ]:
|
||||
if keyname == "Up" and not self.completion_view.get_parent():
|
||||
self.keyboard_move_lines_up()
|
||||
if keyname == "Down" and not self.completion_view.get_parent():
|
||||
self.keyboard_move_lines_down()
|
||||
|
||||
if keyname == "z":
|
||||
self.keyboard_undo()
|
||||
if keyname == "y":
|
||||
self.keyboard_redo()
|
||||
|
||||
return True
|
||||
|
||||
if is_alt:
|
||||
if keyname in [ "Up", "Down", "Left", "Right" ]:
|
||||
return True
|
||||
|
||||
if keyname in [ "Up", "Down", "Left", "Right" ]:
|
||||
if self.completion_view.get_parent() and self.completion_view.is_visible():
|
||||
if keyname == "Up":
|
||||
self.completion_view.move_selection_up()
|
||||
if keyname == "Down":
|
||||
self.completion_view.move_selection_down()
|
||||
if keyname == "Left":
|
||||
self.remove( self.completion_view )
|
||||
if keyname == "Right":
|
||||
self.remove( self.completion_view )
|
||||
|
||||
return True
|
||||
|
||||
if keyname in [ "Return", "Enter" ]:
|
||||
if self.completion_view.get_parent() and self.completion_view.is_visible():
|
||||
return True
|
||||
|
||||
if len(self._multi_insert_marks) > 0:
|
||||
if keyname == "BackSpace":
|
||||
@ -107,7 +81,11 @@ class KeyInputController:
|
||||
|
||||
return True
|
||||
|
||||
if keyname in ["z", "y", "m", "s", "h", "g", "d", "k", "u", "space", "equal", "minus"]:
|
||||
if keyname in ["z", "y", "m", "s", "h", "g", "d", "k", "u", "equal", "minus", "Up", "Down"]:
|
||||
if keyname == "z":
|
||||
self.keyboard_undo()
|
||||
if keyname == "y":
|
||||
self.keyboard_redo()
|
||||
if keyname == "m":
|
||||
self.keyboard_insert_mark()
|
||||
if keyname == "s":
|
||||
@ -122,14 +100,17 @@ class KeyInputController:
|
||||
self.cut_to_buffer()
|
||||
if keyname == "u":
|
||||
self.paste_cut_buffer()
|
||||
if keyname == "space":
|
||||
event_system.emit("textDocument/completion", (self, ))
|
||||
|
||||
if keyname == "equal":
|
||||
self.scale_up_text()
|
||||
if keyname == "minus":
|
||||
self.scale_down_text()
|
||||
|
||||
if keyname == "Up":
|
||||
self.keyboard_move_lines_up()
|
||||
if keyname == "Down":
|
||||
self.keyboard_move_lines_down()
|
||||
|
||||
return True
|
||||
|
||||
# Note: Sink these requets
|
||||
@ -141,12 +122,7 @@ class KeyInputController:
|
||||
self.keyboard_clear_marks()
|
||||
|
||||
|
||||
if keyname in [ "Return", "Enter" ]:
|
||||
if self.completion_view.get_parent() and self.completion_view.is_visible():
|
||||
self.completion_view.activate_completion()
|
||||
|
||||
return True
|
||||
|
||||
if keyname in {"Return", "Enter"}:
|
||||
if len(self._multi_insert_marks) > 0:
|
||||
self.begin_user_action(buffer)
|
||||
with buffer.freeze_notify():
|
||||
|
@ -11,8 +11,8 @@ from gi.repository import Gio
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from ..custom_completion_providers.lsp_completion_provider import LSPCompletionProvider
|
||||
# from ..custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
||||
# from ..custom_completion_providers.lsp_completion_provider import LSPCompletionProvider
|
||||
from ..custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
||||
|
||||
|
||||
class FileEventsMixin:
|
||||
@ -31,7 +31,6 @@ class FileEventsMixin:
|
||||
def save_file(self):
|
||||
self._skip_file_load = True
|
||||
gfile = event_system.emit_and_await("save_file_dialog", (self._current_filename, self._current_file)) if not self._current_file else self._current_file
|
||||
event_system.emit("textDocument/didSave", (self._current_file.get_uri(), self.get_text()))
|
||||
|
||||
if not gfile:
|
||||
self._skip_file_load = False
|
||||
@ -147,14 +146,18 @@ class FileEventsMixin:
|
||||
buffer.uri = uri
|
||||
buffer.language_id = self._current_filetype
|
||||
|
||||
event_system.emit("textDocument/didOpen", (self._current_filetype, uri, self.get_text()))
|
||||
event_system.emit("textDocument/didOpen", (self._current_filetype, uri,))
|
||||
|
||||
# word_completion = GtkSource.CompletionWords.new("word_completion")
|
||||
# word_completion.register(buffer)
|
||||
# self._completion.add_provider(word_completion)
|
||||
word_completion = GtkSource.CompletionWords.new("word_completion")
|
||||
word_completion.register(buffer)
|
||||
self._completion.add_provider(word_completion)
|
||||
|
||||
# lsp_completion_provider = LSPCompletionProvider(self)
|
||||
# self._completion.add_provider(lsp_completion_provider)
|
||||
|
||||
# if self._current_filetype in ("python", "python3"):
|
||||
# py_lsp_completion_provider = PythonCompletionProvider(uri)
|
||||
# self._completion.add_provider(py_lsp_completion_provider)
|
||||
|
||||
self.got_to_line(buffer, line)
|
||||
event_system.emit("buffer_changed_first_load", (buffer, ))
|
@ -17,7 +17,6 @@ from .source_view_controller import SourceViewControllerMixin
|
||||
|
||||
# from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider
|
||||
# from .custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
||||
from ...completion_view import CompletionView
|
||||
|
||||
|
||||
|
||||
@ -38,7 +37,6 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
self._cut_buffer: str = ""
|
||||
self._timer: threading.Timer = None
|
||||
self._idle_id: int = None
|
||||
self._version_id: int = 1
|
||||
|
||||
self._skip_file_load = False
|
||||
self._ignore_internal_change = False
|
||||
@ -49,9 +47,6 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
self._multi_insert_marks = []
|
||||
self.freeze_multi_line_insert = False
|
||||
|
||||
self.completion_view = CompletionView()
|
||||
# self.completion_items = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
@ -91,7 +86,6 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
self.connect("key-press-event", self._key_press_event)
|
||||
self.connect("key-release-event", self._key_release_event)
|
||||
self.connect("button-press-event", self._button_press_event)
|
||||
self.connect("button-release-event", self._button_release_event)
|
||||
self.connect("scroll-event", self._scroll_event)
|
||||
|
||||
buffer = self.get_buffer()
|
||||
@ -100,6 +94,7 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
buffer.connect('insert-text', self._insert_text)
|
||||
buffer.connect('modified-changed', self._buffer_modified_changed)
|
||||
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
|
@ -13,20 +13,12 @@ from .source_view_events import SourceViewEvents
|
||||
|
||||
|
||||
class SourceViewControllerMixin(KeyInputController, SourceViewEvents):
|
||||
def get_text(self):
|
||||
buffer = self.get_buffer()
|
||||
start_itr, end_itr = buffer.get_bounds()
|
||||
return buffer.get_text(start_itr, end_itr, True)
|
||||
|
||||
def get_current_file(self):
|
||||
return self._current_file
|
||||
|
||||
def get_filetype(self):
|
||||
return self._current_filetype
|
||||
|
||||
def get_version_id(self):
|
||||
return self._version_id
|
||||
|
||||
def set_buffer_language(self, buffer, language = "python3"):
|
||||
buffer.set_language( self._language_manager.get_language(language) )
|
||||
|
||||
@ -43,40 +35,25 @@ class SourceViewControllerMixin(KeyInputController, SourceViewEvents):
|
||||
event_system.emit("textDocument/definition", (self.get_filetype(), uri, line, offset,))
|
||||
|
||||
def duplicate_line(self, buffer = None):
|
||||
buffer = self.get_buffer() if not buffer else buffer
|
||||
if not buffer.get_has_selection():
|
||||
had_selection = False
|
||||
itr = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
start_itr = itr.copy()
|
||||
end_itr = itr.copy()
|
||||
start_line = itr.get_line() + 1
|
||||
start_char = itr.get_line_offset()
|
||||
else:
|
||||
had_selection = True
|
||||
start_itr, end_itr = buffer.get_selection_bounds()
|
||||
sline = start_itr.get_line()
|
||||
eline = end_itr.get_line()
|
||||
start_line = eline + 1
|
||||
start_char = start_itr.get_line_offset()
|
||||
end_char = end_itr.get_line_offset()
|
||||
range_line_size = eline - sline
|
||||
buffer = self.get_buffer() if not buffer else buffer
|
||||
itr = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
start_itr = itr.copy()
|
||||
end_itr = itr.copy()
|
||||
start_line = itr.get_line() + 1
|
||||
start_char = itr.get_line_offset()
|
||||
|
||||
start_itr.backward_visible_line()
|
||||
start_itr.forward_line()
|
||||
end_itr.forward_line()
|
||||
end_itr.backward_char()
|
||||
|
||||
line_str = buffer.get_slice(start_itr, end_itr, True)
|
||||
line_str = buffer.get_slice(start_itr, end_itr, True)
|
||||
|
||||
end_itr.forward_char()
|
||||
buffer.insert(end_itr, f"{line_str}\n", -1)
|
||||
|
||||
if not had_selection:
|
||||
new_itr = buffer.get_iter_at_line_offset(start_line, start_char)
|
||||
buffer.place_cursor(new_itr)
|
||||
else:
|
||||
new_itr = buffer.get_iter_at_line_offset(start_line, start_char)
|
||||
new_end_itr = buffer.get_iter_at_line_offset((start_line + range_line_size), end_char)
|
||||
buffer.select_range(new_itr, new_end_itr)
|
||||
new_itr = buffer.get_iter_at_line_offset(start_line, start_char)
|
||||
buffer.place_cursor(new_itr)
|
||||
|
||||
def cut_to_buffer(self, buffer = None):
|
||||
self.cancel_timer()
|
||||
|
@ -14,7 +14,6 @@ from .mixins.source_file_events_mixin import FileEventsMixin
|
||||
from .mixins.source_mark_events_mixin import MarkEventsMixin
|
||||
|
||||
|
||||
|
||||
class SourceViewEvents(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin):
|
||||
def _create_default_tag(self, buffer):
|
||||
general_style_tag = buffer.create_tag('general_style')
|
||||
@ -26,11 +25,8 @@ class SourceViewEvents(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin):
|
||||
file_type = self.get_filetype()
|
||||
|
||||
if not self._loading_file:
|
||||
buffer.version_id = self._version_id
|
||||
self._version_id += 1
|
||||
|
||||
event_system.emit("buffer_changed", (buffer, ))
|
||||
event_system.emit("textDocument/didChange", (file_type, self.get_current_file().get_uri(), buffer, ))
|
||||
# event_system.emit("textDocument/didChange", (file_type, buffer, ))
|
||||
# event_system.emit("textDocument/completion", (self, ))
|
||||
|
||||
self.update_cursor_position(buffer)
|
||||
@ -48,23 +44,13 @@ class SourceViewEvents(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin):
|
||||
|
||||
|
||||
def _button_press_event(self, widget = None, eve = None, user_data = None):
|
||||
if eve.button == 1 : # l-click
|
||||
...
|
||||
elif eve.button == 2: # m-click
|
||||
...
|
||||
elif eve.button == 3: # r-click
|
||||
...
|
||||
|
||||
def _button_release_event(self, widget = None, eve = None, user_data = None):
|
||||
if eve.button == 1 : # l-click
|
||||
self.keyboard_clear_marks()
|
||||
if eve.state & Gdk.ModifierType.CONTROL_MASK:
|
||||
self.go_to_call()
|
||||
elif eve.button == 2: # m-click
|
||||
if eve.type == Gdk.EventType.BUTTON_PRESS and eve.button == 1 : # l-click
|
||||
if eve.state & Gdk.ModifierType.CONTROL_MASK:
|
||||
self.button_press_insert_mark(eve)
|
||||
return True
|
||||
elif eve.button == 3: # r-click
|
||||
else:
|
||||
self.keyboard_clear_marks()
|
||||
elif eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 3: # r-click
|
||||
...
|
||||
|
||||
def _scroll_event(self, widget, eve):
|
||||
|
@ -1,51 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class CompletionItem(Gtk.Label):
|
||||
def __init__(self):
|
||||
super(CompletionItem, self).__init__()
|
||||
|
||||
self.kind: int = -1
|
||||
self.newText: str = ""
|
||||
self.insertText: str = ""
|
||||
self.textEdit: [] = []
|
||||
self.additionalTextEdits: [] = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("completion-item")
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
|
||||
def populate_completion_item(self, item):
|
||||
keys = item.keys()
|
||||
self.set_label(item["label"])
|
||||
|
||||
if "kind" in keys:
|
||||
self.kind = item["kind"]
|
||||
|
||||
if "insertText" in keys:
|
||||
self.insertText = item["insertText"]
|
||||
|
||||
if "textEdit" in keys:
|
||||
self.textEdit = item["textEdit"]
|
||||
self.newText = item["textEdit"]["newText"]
|
||||
|
||||
if "additionalTextEdits" in keys:
|
||||
self.additionalTextEdits = item["additionalTextEdits"]
|
@ -1,228 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from .completion_item import CompletionItem
|
||||
|
||||
|
||||
|
||||
class CompletionView(Gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
super(CompletionView, self).__init__()
|
||||
|
||||
self.vadjustment = self.get_vadjustment()
|
||||
self.button_box = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("completion-view")
|
||||
self.set_margin_top(10)
|
||||
self.set_margin_bottom(10)
|
||||
self.set_margin_start(10)
|
||||
self.set_margin_end(10)
|
||||
self.set_size_request(320, -1)
|
||||
self.set_min_content_height(120)
|
||||
self.set_max_content_height(480)
|
||||
|
||||
self.set_overlay_scrolling(False)
|
||||
self.set_policy( Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC ) # hbar, vbar
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
viewport = Gtk.Viewport()
|
||||
self.button_box = Gtk.ListBox()
|
||||
|
||||
self.button_box.set_hexpand( True )
|
||||
self.button_box.set_placeholder( Gtk.Label(label = "No completion data...") )
|
||||
self.button_box.set_selection_mode( Gtk.SelectionMode.BROWSE )
|
||||
|
||||
self.button_box.connect("key-release-event", self._key_release_event)
|
||||
self.button_box.connect("button-release-event", self._button_release_event)
|
||||
|
||||
viewport.add(self.button_box)
|
||||
self.add(viewport)
|
||||
|
||||
def _key_release_event(self, widget, eve):
|
||||
keyname = Gdk.keyval_name(eve.keyval)
|
||||
modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
is_control = True if modifiers & Gdk.ModifierType.CONTROL_MASK else False
|
||||
is_shift = True if modifiers & Gdk.ModifierType.SHIFT_MASK else False
|
||||
|
||||
if is_control:
|
||||
return True
|
||||
|
||||
if keyname in [ "Enter", "Return" ]:
|
||||
self.activate_completion()
|
||||
return True
|
||||
|
||||
def _button_release_event(self, widget, eve):
|
||||
if eve.button == 1: # lclick
|
||||
self.activate_completion()
|
||||
return True
|
||||
|
||||
def clear_items(self):
|
||||
for child in self.button_box.get_children():
|
||||
self.button_box.remove(child)
|
||||
|
||||
def add_completion_item(self, item: CompletionItem):
|
||||
self.button_box.add(item)
|
||||
|
||||
def move_selection_up(self):
|
||||
srow = self.button_box.get_selected_row()
|
||||
if not srow:
|
||||
self.select_last_row()
|
||||
return
|
||||
|
||||
index = srow.get_index() - 1
|
||||
if index == -1:
|
||||
self.select_last_row()
|
||||
return
|
||||
|
||||
row = self.button_box.get_row_at_index(index)
|
||||
self.select_and_scroll_to_view(row, self.vadjustment.get_value() - row.get_allocation().height)
|
||||
|
||||
def move_selection_down(self):
|
||||
srow = self.button_box.get_selected_row()
|
||||
if not srow:
|
||||
self.select_first_row()
|
||||
return
|
||||
|
||||
index = srow.get_index() + 1
|
||||
if index > (len( self.button_box.get_children() ) - 1):
|
||||
index = 0
|
||||
self.select_first_row()
|
||||
return
|
||||
|
||||
row = self.button_box.get_row_at_index(index)
|
||||
self.select_and_scroll_to_view(row, self.vadjustment.get_value() + row.get_allocation().height)
|
||||
|
||||
def select_first_row(self):
|
||||
row = self.button_box.get_row_at_index(0)
|
||||
if not row: return
|
||||
self.select_and_scroll_to_view(row, self.vadjustment.get_lower())
|
||||
|
||||
def select_last_row(self):
|
||||
row = self.button_box.get_row_at_index( len( self.button_box.get_children() ) - 1 )
|
||||
if not row: return
|
||||
self.select_and_scroll_to_view(row, self.vadjustment.get_upper())
|
||||
|
||||
def select_and_scroll_to_view(self, row, adjustment: float):
|
||||
self.button_box.select_row(row)
|
||||
self.vadjustment.set_value( adjustment )
|
||||
|
||||
def activate_completion(self):
|
||||
completion_item = self.button_box.get_selected_row().get_child()
|
||||
source_view = self.get_parent()
|
||||
buffer = source_view.get_buffer()
|
||||
siter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
pre_char = self.get_pre_char(siter)
|
||||
|
||||
if completion_item.textEdit:
|
||||
self.process_range_insert(buffer, completion_item.textEdit, completion_item.newText)
|
||||
|
||||
for edit in completion_item.additionalTextEdits:
|
||||
self.process_range_insert(buffer, edit, edit["newText"])
|
||||
|
||||
source_view.remove(self)
|
||||
GLib.idle_add( source_view.grab_focus )
|
||||
|
||||
return
|
||||
|
||||
if pre_char == '.':
|
||||
buffer.insert(siter, completion_item.insertText, -1)
|
||||
|
||||
source_view.remove(self)
|
||||
GLib.idle_add( source_view.grab_focus )
|
||||
|
||||
return
|
||||
|
||||
if siter.inside_word() or siter.ends_word() or pre_char == '_':
|
||||
eiter = siter.copy()
|
||||
siter.backward_visible_word_start()
|
||||
self.get_word_start(siter)
|
||||
|
||||
if not eiter.ends_word() and not pre_char == '_':
|
||||
eiter.forward_word_end()
|
||||
|
||||
buffer.delete(siter, eiter)
|
||||
|
||||
buffer.insert(siter, completion_item.insertText, -1)
|
||||
|
||||
source_view.remove(self)
|
||||
GLib.idle_add( source_view.grab_focus )
|
||||
|
||||
def process_range_insert(self, buffer, insert_data: {}, text: str):
|
||||
sline = insert_data["range"]["start"]["line"]
|
||||
schar = insert_data["range"]["start"]["character"]
|
||||
eline = insert_data["range"]["end"]["line"]
|
||||
echar = insert_data["range"]["end"]["character"]
|
||||
siter = buffer.get_iter_at_line_offset( sline, schar )
|
||||
eiter = buffer.get_iter_at_line_offset( eline, echar )
|
||||
|
||||
buffer.delete(siter, eiter)
|
||||
buffer.insert(siter, text, -1)
|
||||
|
||||
def get_word_start(self, iter):
|
||||
pre_char = self.get_pre_char(iter)
|
||||
while pre_char == '_':
|
||||
iter.backward_visible_word_start()
|
||||
pre_char = self.get_pre_char(iter)
|
||||
|
||||
def get_pre_char(self, iter):
|
||||
pre_char = None
|
||||
if iter.backward_char():
|
||||
pre_char = iter.get_char()
|
||||
iter.forward_char()
|
||||
|
||||
return pre_char
|
||||
|
||||
# export const Text = 1;
|
||||
# export const Method = 2;
|
||||
# export const Function = 3;
|
||||
# export const Constructor = 4;
|
||||
# export const Field = 5;
|
||||
# export const Variable = 6;
|
||||
# export const Class = 7;
|
||||
# export const Interface = 8;
|
||||
# export const Module = 9;
|
||||
# export const Property = 10;
|
||||
# export const Unit = 11;
|
||||
# export const Value = 12;
|
||||
# export const Enum = 13;
|
||||
# export const Keyword = 14;
|
||||
# export const Snippet = 15;
|
||||
# export const Color = 16;
|
||||
# export const File = 17;
|
||||
# export const Reference = 18;
|
||||
# export const Folder = 19;
|
||||
# export const EnumMember = 20;
|
||||
# export const Constant = 21;
|
||||
# export const Struct = 22;
|
||||
# export const Event = 23;
|
||||
# export const Operator = 24;
|
||||
# export const TypeParameter = 25;
|
||||
def sort_completion_list(self, completion_list: list) -> list:
|
||||
new_completion_list = []
|
||||
|
||||
for item in filtered_list:
|
||||
keys = item.keys()
|
||||
if "insertText" in keys or "textEdit" in keys:
|
||||
new_completion_list.append(item)
|
||||
|
||||
return new_completion_list
|
@ -1,3 +0,0 @@
|
||||
"""
|
||||
Dasta Class module
|
||||
"""
|
@ -1,54 +0,0 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass
|
||||
import json
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def get_message_obj(data: str):
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
@dataclass
|
||||
class LSPResponseRequest(object):
|
||||
"""
|
||||
Constructs a new LSP Response Request instance.
|
||||
|
||||
:param id result: The id of the given message.
|
||||
:param dict result: The arguments of the given method.
|
||||
"""
|
||||
jsonrpc: str
|
||||
id: int
|
||||
result: dict
|
||||
|
||||
@dataclass
|
||||
class LSPResponseNotification(object):
|
||||
"""
|
||||
Constructs a new LSP Response Notification instance.
|
||||
|
||||
:param str method: The type of lsp notification being made.
|
||||
:params dict result: The arguments of the given method.
|
||||
"""
|
||||
jsonrpc: str
|
||||
method: str
|
||||
params: dict
|
||||
|
||||
@dataclass
|
||||
class LSPIDResponseNotification(object):
|
||||
"""
|
||||
Constructs a new LSP Response Notification instance.
|
||||
|
||||
:param str method: The type of lsp notification being made.
|
||||
:params dict result: The arguments of the given method.
|
||||
"""
|
||||
jsonrpc: str
|
||||
id: int
|
||||
method: str
|
||||
params: dict
|
||||
|
||||
|
||||
class LSPResponseTypes(LSPResponseRequest, LSPResponseNotification, LSPIDResponseNotification):
|
||||
...
|
Loading…
Reference in New Issue
Block a user