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)
|
json_rpc_endpoint = pylspclient.JsonRpcEndpoint(server_proc.stdin, server_proc.stdout)
|
||||||
|
|
||||||
callbacks = {
|
callbacks = {
|
||||||
|
"window/showMessage": print,
|
||||||
"textDocument/symbolStatus": print,
|
"textDocument/symbolStatus": print,
|
||||||
"textDocument/publishDiagnostics": self._blame,
|
"textDocument/publishDiagnostics": self._blame,
|
||||||
}
|
}
|
||||||
@ -117,6 +118,41 @@ class LSPController:
|
|||||||
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
|
pylspclient.lsp_structs.TextDocumentIdentifier(uri),
|
||||||
pylspclient.lsp_structs.Position(line, offset)
|
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):
|
def load_lsp_server(self, language_id):
|
||||||
if not language_id in self.lsp_servers_config.keys():
|
if not language_id in self.lsp_servers_config.keys():
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import threading
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
|
||||||
@ -12,7 +14,6 @@ from .lsp_controller import LSPController
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LSPPliginException(Exception):
|
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_config_path: str = os.path.dirname(os.path.realpath(__file__)) + "/../../lsp_servers_config.json"
|
||||||
self.lsp_servers_config: dict = {}
|
self.lsp_servers_config: dict = {}
|
||||||
self.lsp_controller = None
|
self.lsp_controller = None
|
||||||
|
self.timer = None
|
||||||
|
|
||||||
|
|
||||||
def generate_reference_ui_element(self):
|
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..."
|
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,))
|
self._event_system.emit("bubble_message", ("warning", self.name, text,))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.lsp_controller = LSPController(self.lsp_servers_config)
|
if len(self.lsp_servers_config.keys()) > 0:
|
||||||
self.inner_subscribe_to_events()
|
self.lsp_controller = LSPController(self.lsp_servers_config)
|
||||||
|
self.inner_subscribe_to_events()
|
||||||
|
|
||||||
def subscribe_to_events(self):
|
def subscribe_to_events(self):
|
||||||
...
|
...
|
||||||
|
|
||||||
def inner_subscribe_to_events(self):
|
def inner_subscribe_to_events(self):
|
||||||
self._event_system.subscribe("shutting_down", self._shutting_down)
|
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/didOpen", self.lsp_controller.do_open)
|
||||||
self._event_system.subscribe("textDocument/didSave", self.lsp_controller.do_save)
|
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/didClose", self.lsp_controller.do_close)
|
||||||
self._event_system.subscribe("textDocument/definition", self._do_goto)
|
self._event_system.subscribe("textDocument/definition", self._do_goto)
|
||||||
|
self._event_system.subscribe("textDocument/completion", self.completion)
|
||||||
|
|
||||||
def _shutting_down(self):
|
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):
|
def delay_completion_glib(self, source_view, context, callback):
|
||||||
# self._do_completion()
|
GLib.idle_add(self._do_completion, source_view, context, callback)
|
||||||
...
|
|
||||||
|
|
||||||
|
def delay_completion(self, source_view, context, callback):
|
||||||
def _do_completion(self, is_invoked = False):
|
self.timer = threading.Timer(0.8, self.delay_completion_glib, (source_view, context, callback,))
|
||||||
fpath = self._active_src_view.get_current_filepath()
|
self.timer.daemon = True
|
||||||
|
self.timer.start()
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
if result.items:
|
def _buffer_changed(self, language_id, buffer):
|
||||||
for item in result.items:
|
iter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||||
print(item.label)
|
line = iter.get_line()
|
||||||
else:
|
start = iter.copy()
|
||||||
print(result.label)
|
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):
|
def _do_goto(self, language_id, uri, line, offset):
|
||||||
results = self.lsp_controller.do_goto(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:]
|
file = result.uri[7:]
|
||||||
line = result.range.end.line
|
line = result.range.end.line
|
||||||
message = f"FILE|{file}:{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")
|
params = jsonrpc_message.get("params")
|
||||||
|
|
||||||
if method:
|
if method:
|
||||||
if rpc_id:
|
if rpc_id is not None:
|
||||||
if method not in self.method_callbacks:
|
if method not in self.method_callbacks:
|
||||||
raise lsp_structs.ResponseError(
|
raise lsp_structs.ResponseError(
|
||||||
lsp_structs.ErrorCodes.MethodNotFound,
|
lsp_structs.ErrorCodes.MethodNotFound,
|
||||||
|
@ -436,7 +436,7 @@ class CompletionItem(object):
|
|||||||
detail = None, \
|
detail = None, \
|
||||||
documentation = None, \
|
documentation = None, \
|
||||||
deprecated = None, \
|
deprecated = None, \
|
||||||
presented = None, \
|
preselect = None, \
|
||||||
sortText = None, \
|
sortText = None, \
|
||||||
filterText = None, \
|
filterText = None, \
|
||||||
insertText = 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 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 tr ocumentation: A human-readable string that represents a doc-comment.
|
||||||
:param bool deprecated: Indicates if this item is deprecated.
|
: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.
|
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 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.
|
: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.detail = detail
|
||||||
self.documentation = documentation
|
self.documentation = documentation
|
||||||
self.deprecated = deprecated
|
self.deprecated = deprecated
|
||||||
self.presented = presented
|
self.preselect = preselect
|
||||||
self.sortText = sortText
|
self.sortText = sortText
|
||||||
self.filterText = filterText
|
self.filterText = filterText
|
||||||
self.insertText = insertText
|
self.insertText = insertText
|
||||||
@ -530,7 +530,7 @@ class CompletionItemKind(enum.Enum):
|
|||||||
|
|
||||||
class CompletionList(object):
|
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):
|
def __init__(self, isIncomplete, items):
|
||||||
"""
|
"""
|
||||||
|
@ -99,4 +99,5 @@ class Plugin(PluginBase):
|
|||||||
body = self.snippet_data[self.active_snippit_group][key]["body"]
|
body = self.snippet_data[self.active_snippit_group][key]["body"]
|
||||||
snippits.append(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
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..custom_completion_providers.lsp_completion_provider import LSPCompletionProvider
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -135,8 +136,7 @@ class FileEventsMixin:
|
|||||||
def _document_loaded(self, line: int = 0):
|
def _document_loaded(self, line: int = 0):
|
||||||
for provider in self._completion.get_providers():
|
for provider in self._completion.get_providers():
|
||||||
self._completion.remove_provider(provider)
|
self._completion.remove_provider(provider)
|
||||||
|
|
||||||
file = self._current_file.get_path()
|
|
||||||
uri = self._current_file.get_uri()
|
uri = self._current_file.get_uri()
|
||||||
buffer = self.get_buffer()
|
buffer = self.get_buffer()
|
||||||
|
|
||||||
@ -145,19 +145,11 @@ class FileEventsMixin:
|
|||||||
word_completion = GtkSource.CompletionWords.new("word_completion")
|
word_completion = GtkSource.CompletionWords.new("word_completion")
|
||||||
word_completion.register(buffer)
|
word_completion.register(buffer)
|
||||||
self._completion.add_provider(word_completion)
|
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)
|
self.got_to_line(buffer, line)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ from gi.repository import GtkSource
|
|||||||
# Application imports
|
# Application imports
|
||||||
from .source_view_controller import SourceViewControllerMixin
|
from .source_view_controller import SourceViewControllerMixin
|
||||||
|
|
||||||
from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider
|
# from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider
|
||||||
from .custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
# 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)
|
general_style_tag.set_property('scale', 100)
|
||||||
|
|
||||||
def _is_modified(self, *args):
|
def _is_modified(self, *args):
|
||||||
buffer = self.get_buffer()
|
buffer = self.get_buffer()
|
||||||
|
file_type = self.get_filetype()
|
||||||
|
|
||||||
if not self._loading_file:
|
if not self._loading_file:
|
||||||
event_system.emit("buffer_changed", (buffer, ))
|
event_system.emit("buffer_changed", (buffer, ))
|
||||||
|
event_system.emit("textDocument/didChange", (file_type, buffer, ))
|
||||||
else:
|
else:
|
||||||
event_system.emit("buffer_changed_first_load", (buffer, ))
|
event_system.emit("buffer_changed_first_load", (buffer, ))
|
||||||
|
|
||||||
|
@ -123,4 +123,4 @@ class IPCServer:
|
|||||||
logger.error("IPC Socket no longer valid.... Removing.")
|
logger.error("IPC Socket no longer valid.... Removing.")
|
||||||
os.unlink(self._ipc_address)
|
os.unlink(self._ipc_address)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error( repr(e) )
|
logger.error( repr(e) )
|
Loading…
Reference in New Issue
Block a user