generated from itdominator/Python-With-Gtk-Template
Completion providfer efforts; Snippits stubbing message
This commit is contained in:
parent
5280667789
commit
37bff1eb3d
|
@ -48,6 +48,7 @@ class LSPController:
|
|||
json_rpc_endpoint = pylspclient.JsonRpcEndpoint(server_proc.stdin, server_proc.stdout)
|
||||
|
||||
callbacks = {
|
||||
"window/showMessage": print,
|
||||
"textDocument/symbolStatus": print,
|
||||
"textDocument/publishDiagnostics": self._blame,
|
||||
}
|
||||
|
@ -117,6 +118,41 @@ class LSPController:
|
|||
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
|
||||
pylspclient.lsp_structs.Position(line, offset)
|
||||
)
|
||||
|
||||
return []
|
||||
|
||||
def do_change(self, language_id, line, start, end, text):
|
||||
if language_id in self.lsp_clients.keys():
|
||||
|
||||
start_pos = pylspclient.lsp_structs.Position(line, start.get_line_offset())
|
||||
end_pos = pylspclient.lsp_structs.Position(line, end.get_line_offset())
|
||||
range_info = pylspclient.lsp_structs.Range(start_pos, end_pos)
|
||||
text_length = len(text)
|
||||
change_event = pylspclient.lsp_structs.TextDocumentContentChangeEvent(range_info, text_length, text)
|
||||
|
||||
return self.lsp_clients[language_id].didChange( None, change_event )
|
||||
|
||||
return []
|
||||
|
||||
def do_completion(self, language_id, uri, line, offset, _char, is_invoked = False):
|
||||
if language_id in self.lsp_clients.keys():
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
|
||||
|
||||
if _char in [".", " "]:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
|
||||
elif is_invoked:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.Invoked
|
||||
else:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerForIncompleteCompletions
|
||||
|
||||
return self.lsp_clients[language_id].completion(
|
||||
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
|
||||
pylspclient.lsp_structs.Position(line, offset),
|
||||
pylspclient.lsp_structs.CompletionContext(trigger, _char)
|
||||
)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def load_lsp_server(self, language_id):
|
||||
if not language_id in self.lsp_servers_config.keys():
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# Python imports
|
||||
import os
|
||||
import json
|
||||
import threading
|
||||
|
||||
# Lib imports
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
|
||||
|
@ -12,7 +14,6 @@ from .lsp_controller import LSPController
|
|||
|
||||
|
||||
|
||||
|
||||
class LSPPliginException(Exception):
|
||||
...
|
||||
|
||||
|
@ -27,6 +28,8 @@ class Plugin(PluginBase):
|
|||
self.lsp_config_path: str = os.path.dirname(os.path.realpath(__file__)) + "/../../lsp_servers_config.json"
|
||||
self.lsp_servers_config: dict = {}
|
||||
self.lsp_controller = None
|
||||
self.timer = None
|
||||
|
||||
|
||||
def generate_reference_ui_element(self):
|
||||
...
|
||||
|
@ -39,63 +42,76 @@ class Plugin(PluginBase):
|
|||
text = f"LSP NOT Enabled.\nFile:\n\t{self.lsp_config_path}\ndoes no exsist..."
|
||||
self._event_system.emit("bubble_message", ("warning", self.name, text,))
|
||||
return
|
||||
|
||||
self.lsp_controller = LSPController(self.lsp_servers_config)
|
||||
self.inner_subscribe_to_events()
|
||||
|
||||
if len(self.lsp_servers_config.keys()) > 0:
|
||||
self.lsp_controller = LSPController(self.lsp_servers_config)
|
||||
self.inner_subscribe_to_events()
|
||||
|
||||
def subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def inner_subscribe_to_events(self):
|
||||
self._event_system.subscribe("shutting_down", self._shutting_down)
|
||||
self._event_system.subscribe("buffer_changed", self._buffer_changed)
|
||||
|
||||
self._event_system.subscribe("textDocument/didChange", self._buffer_changed)
|
||||
self._event_system.subscribe("textDocument/didOpen", self.lsp_controller.do_open)
|
||||
self._event_system.subscribe("textDocument/didSave", self.lsp_controller.do_save)
|
||||
self._event_system.subscribe("textDocument/didClose", self.lsp_controller.do_close)
|
||||
self._event_system.subscribe("textDocument/definition", self._do_goto)
|
||||
self._event_system.subscribe("textDocument/completion", self.completion)
|
||||
|
||||
def _shutting_down(self):
|
||||
if self.lsp_controller:
|
||||
self.lsp_controller._shutting_down()
|
||||
self.lsp_controller._shutting_down()
|
||||
|
||||
def cancel_timer(self):
|
||||
if self.timer:
|
||||
self.timer.cancel()
|
||||
GLib.idle_remove_by_data(None)
|
||||
|
||||
def _buffer_changed(self, buffer):
|
||||
# self._do_completion()
|
||||
...
|
||||
def delay_completion_glib(self, source_view, context, callback):
|
||||
GLib.idle_add(self._do_completion, source_view, context, callback)
|
||||
|
||||
|
||||
def _do_completion(self, is_invoked = False):
|
||||
fpath = self._active_src_view.get_current_filepath()
|
||||
|
||||
if not fpath: return
|
||||
|
||||
uri = fpath.get_uri()
|
||||
iter = self._buffer.get_iter_at_mark( self._buffer.get_insert() )
|
||||
line = iter.get_line()
|
||||
offset = iter.get_line_offset()
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
|
||||
_char = iter.get_char()
|
||||
trigger = None
|
||||
|
||||
if _char in [".", " "]:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerCharacter
|
||||
elif is_invoked:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.Invoked
|
||||
else:
|
||||
trigger = pylspclient.lsp_structs.CompletionTriggerKind.TriggerForIncompleteCompletions
|
||||
|
||||
result = self.lsp_controller.completion(
|
||||
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
|
||||
pylspclient.lsp_structs.Position(line, offset),
|
||||
pylspclient.lsp_structs.CompletionContext(trigger, _char)
|
||||
)
|
||||
def delay_completion(self, source_view, context, callback):
|
||||
self.timer = threading.Timer(0.8, self.delay_completion_glib, (source_view, context, callback,))
|
||||
self.timer.daemon = True
|
||||
self.timer.start()
|
||||
|
||||
if result.items:
|
||||
for item in result.items:
|
||||
print(item.label)
|
||||
else:
|
||||
print(result.label)
|
||||
def _buffer_changed(self, language_id, buffer):
|
||||
iter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
line = iter.get_line()
|
||||
start = iter.copy()
|
||||
end = iter.copy()
|
||||
|
||||
start.backward_line()
|
||||
start.forward_line()
|
||||
end.forward_to_line_end()
|
||||
|
||||
text = buffer.get_text(start, end, include_hidden_chars = False)
|
||||
result = self.lsp_controller.do_change(language_id, line, start, end, text)
|
||||
# print(result)
|
||||
|
||||
|
||||
def completion(self, source_view, context, callback):
|
||||
self.cancel_timer()
|
||||
self.delay_completion(source_view, context, callback)
|
||||
|
||||
def _do_completion(self, source_view, context, callback):
|
||||
filepath = source_view.get_current_filepath()
|
||||
|
||||
if not filepath: return
|
||||
|
||||
uri = filepath.get_uri()
|
||||
buffer = source_view.get_buffer()
|
||||
iter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
line = iter.get_line() + 1
|
||||
|
||||
_char = iter.get_char()
|
||||
if iter.backward_char():
|
||||
_char = iter.get_char()
|
||||
|
||||
offset = iter.get_line_offset()
|
||||
result = self.lsp_controller.do_completion(source_view.get_filetype(), uri, line, offset, _char)
|
||||
callback(context, result)
|
||||
|
||||
def _do_goto(self, language_id, uri, line, offset):
|
||||
results = self.lsp_controller.do_goto(language_id, uri, line, offset)
|
||||
|
@ -105,5 +121,4 @@ class Plugin(PluginBase):
|
|||
file = result.uri[7:]
|
||||
line = result.range.end.line
|
||||
message = f"FILE|{file}:{line}"
|
||||
self._event_system.emit("post_file_to_ipc", message)
|
||||
|
||||
self._event_system.emit("post_file_to_ipc", message)
|
|
@ -41,7 +41,7 @@ class LspEndpoint(threading.Thread):
|
|||
params = jsonrpc_message.get("params")
|
||||
|
||||
if method:
|
||||
if rpc_id:
|
||||
if rpc_id is not None:
|
||||
if method not in self.method_callbacks:
|
||||
raise lsp_structs.ResponseError(
|
||||
lsp_structs.ErrorCodes.MethodNotFound,
|
||||
|
|
|
@ -436,7 +436,7 @@ class CompletionItem(object):
|
|||
detail = None, \
|
||||
documentation = None, \
|
||||
deprecated = None, \
|
||||
presented = None, \
|
||||
preselect = None, \
|
||||
sortText = None, \
|
||||
filterText = None, \
|
||||
insertText = None, \
|
||||
|
@ -455,7 +455,7 @@ class CompletionItem(object):
|
|||
:param str detail: A human-readable string with additional information about this item, like type or symbol information.
|
||||
:param tr ocumentation: A human-readable string that represents a doc-comment.
|
||||
:param bool deprecated: Indicates if this item is deprecated.
|
||||
:param bool presented: Select this item when showing. Note: that only one completion item can be selected and that the
|
||||
:param bool preselect: Select this item when showing. Note: that only one completion item can be selected and that the
|
||||
tool / client decides which item that is. The rule is that the first item of those that match best is selected.
|
||||
:param str sortText: A string that should be used when comparing this item with other items. When `falsy` the label is used.
|
||||
:param str filterText: A string that should be used when filtering a set of completion items. When `falsy` the label is used.
|
||||
|
@ -487,7 +487,7 @@ class CompletionItem(object):
|
|||
self.detail = detail
|
||||
self.documentation = documentation
|
||||
self.deprecated = deprecated
|
||||
self.presented = presented
|
||||
self.preselect = preselect
|
||||
self.sortText = sortText
|
||||
self.filterText = filterText
|
||||
self.insertText = insertText
|
||||
|
@ -530,7 +530,7 @@ class CompletionItemKind(enum.Enum):
|
|||
|
||||
class CompletionList(object):
|
||||
"""
|
||||
Represents a collection of [completion items](#CompletionItem) to be presented in the editor.
|
||||
Represents a collection of [completion items](#CompletionItem) to be preselect in the editor.
|
||||
"""
|
||||
def __init__(self, isIncomplete, items):
|
||||
"""
|
||||
|
|
|
@ -99,4 +99,5 @@ class Plugin(PluginBase):
|
|||
body = self.snippet_data[self.active_snippit_group][key]["body"]
|
||||
snippits.append(body)
|
||||
|
||||
print(snippits)
|
||||
# print(snippits)
|
||||
print("Snippits Plugin: _handle_update > results > stub...")
|
|
@ -0,0 +1,73 @@
|
|||
# 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
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
"""
|
||||
This code is A python code completion plugin for Newton.
|
||||
# NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi
|
||||
"""
|
||||
__gtype_name__ = 'PythonProvider'
|
||||
|
||||
def __init__(self, source_view):
|
||||
GObject.Object.__init__(self)
|
||||
|
||||
self._theme = Gtk.IconTheme.get_default()
|
||||
self._source_view = source_view
|
||||
|
||||
def do_get_name(self):
|
||||
return "LSP Code Completion"
|
||||
|
||||
def get_iter_correctly(self, context):
|
||||
return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter()
|
||||
|
||||
def do_match(self, context):
|
||||
event_system.emit("textDocument/completion", (self._source_view, context, self.do_populate))
|
||||
return True
|
||||
|
||||
def do_get_priority(self):
|
||||
return 1
|
||||
|
||||
def do_get_activation(self):
|
||||
return GtkSource.CompletionActivation.INTERACTIVE
|
||||
|
||||
def do_populate(self, context, result = None):
|
||||
proposals = []
|
||||
if result:
|
||||
if result.items:
|
||||
for item in result.items:
|
||||
comp_item = GtkSource.CompletionItem.new()
|
||||
comp_item.set_label(item.label)
|
||||
comp_item.set_text(item.textEdit)
|
||||
comp_item.set_icon( self.get_icon_for_type(item.kind) )
|
||||
comp_item.set_info(item.documentation)
|
||||
proposals.append(comp_item)
|
||||
else:
|
||||
comp_item = GtkSource.CompletionItem.new()
|
||||
comp_item.set_label(item.label)
|
||||
comp_item.set_text(item.textEdit)
|
||||
comp_item.set_icon( self.get_icon_for_type(item.kind) )
|
||||
comp_item.set_info(item.documentation)
|
||||
proposals.append(comp_item)
|
||||
|
||||
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
|
|
@ -10,6 +10,7 @@ from gi.repository import Gio
|
|||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from ..custom_completion_providers.lsp_completion_provider import LSPCompletionProvider
|
||||
|
||||
|
||||
|
||||
|
@ -135,8 +136,7 @@ class FileEventsMixin:
|
|||
def _document_loaded(self, line: int = 0):
|
||||
for provider in self._completion.get_providers():
|
||||
self._completion.remove_provider(provider)
|
||||
|
||||
file = self._current_file.get_path()
|
||||
|
||||
uri = self._current_file.get_uri()
|
||||
buffer = self.get_buffer()
|
||||
|
||||
|
@ -145,19 +145,11 @@ class FileEventsMixin:
|
|||
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)
|
||||
|
||||
# TODO: actually load a meaningful provider based on file type...
|
||||
# example_completion_provider = ExampleCompletionProvider()
|
||||
# self._completion.add_provider(example_completion_provider)
|
||||
|
||||
# py_completion_provider = PythonCompletionProvider(file)
|
||||
# self._completion.add_provider(py_completion_provider)
|
||||
self.got_to_line(buffer, line)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ from gi.repository import GtkSource
|
|||
# Application imports
|
||||
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 .custom_completion_providers.example_completion_provider import ExampleCompletionProvider
|
||||
# from .custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,10 +21,12 @@ class SourceViewEvents(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin):
|
|||
general_style_tag.set_property('scale', 100)
|
||||
|
||||
def _is_modified(self, *args):
|
||||
buffer = self.get_buffer()
|
||||
buffer = self.get_buffer()
|
||||
file_type = self.get_filetype()
|
||||
|
||||
if not self._loading_file:
|
||||
event_system.emit("buffer_changed", (buffer, ))
|
||||
event_system.emit("textDocument/didChange", (file_type, buffer, ))
|
||||
else:
|
||||
event_system.emit("buffer_changed_first_load", (buffer, ))
|
||||
|
||||
|
|
|
@ -123,4 +123,4 @@ class IPCServer:
|
|||
logger.error("IPC Socket no longer valid.... Removing.")
|
||||
os.unlink(self._ipc_address)
|
||||
except Exception as e:
|
||||
logger.error( repr(e) )
|
||||
logger.error( repr(e) )
|
Loading…
Reference in New Issue