Reworking completion call and didChange logic

This commit is contained in:
itdominator 2024-01-29 22:11:14 -06:00
parent 0c6af185a2
commit defff39e25
7 changed files with 79 additions and 65 deletions

View File

@ -13,7 +13,10 @@ from .capabilities import Capabilities
class ReadPipe(threading.Thread):
def __init__(self, pipe):
threading.Thread.__init__(self)
self.pipe = pipe
self.daemon = True
self.pipe = pipe
def run(self):
line = self.pipe.readline().decode('utf-8')
@ -63,7 +66,7 @@ class LSPController:
if not language or not server_proc: return False
root_path = None
# root_uri = 'file:///home/abaddon/Coding/Projects/Active/C_n_CPP_Projects/gtk/Newton/src/'
# root_uri = 'file:///home/abaddon/Coding/Projects/Active/Python_Projects/000_Usable/gtk/Newton_Editor/src/'
# workspace_folders = [{'name': 'python-lsp', 'uri': root_uri}]
root_uri = ''
workspace_folders = [{'name': '', 'uri': root_uri}]
@ -76,6 +79,7 @@ class LSPController:
initializationOptions = initialization_options, \
capabilities = Capabilities.data, \
trace = "off", \
# trace = "on", \
workspaceFolders = workspace_folders
)
@ -123,16 +127,17 @@ class LSPController:
return []
def do_change(self, language_id, line, start, end, text):
def do_change(self, uri, 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)
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)
text_document = pylspclient.lsp_structs.TextDocumentItem(uri, language_id, 1, text)
change_event = pylspclient.lsp_structs.TextDocumentContentChangeEvent(range_info, text_length, text)
return self.lsp_clients[language_id].didChange( None, change_event )
return self.lsp_clients[language_id].didChange( text_document, change_event )
return []
@ -155,7 +160,7 @@ class LSPController:
)
return []
def load_lsp_server(self, language_id):
if not language_id in self.lsp_servers_config.keys():

View File

@ -24,7 +24,7 @@ class Plugin(PluginBase):
super().__init__()
self.name = "LSP Client" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
# where self.name should not be needed for message comms
# where self.name should not be needed for message comms
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
@ -58,24 +58,11 @@ class Plugin(PluginBase):
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)
self._event_system.subscribe("textDocument/completion", self._do_completion)
def _shutting_down(self):
self.lsp_controller._shutting_down()
def cancel_timer(self):
if self.timer:
self.timer.cancel()
GLib.idle_remove_by_data(None)
def delay_completion_glib(self, source_view, context, callback):
GLib.idle_add(self._do_completion, source_view, context, callback)
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()
def _buffer_changed(self, language_id, buffer):
iter = buffer.get_iter_at_mark( buffer.get_insert() )
line = iter.get_line()
@ -86,14 +73,10 @@ class Plugin(PluginBase):
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)
text = buffer.get_text(start, end, include_hidden_chars = False)
result = self.lsp_controller.do_change(buffer.uri, language_id, line, start, end, text)
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):
def _do_completion(self, source_view):
filepath = source_view.get_current_file()
if not filepath: return
@ -101,16 +84,22 @@ class Plugin(PluginBase):
uri = filepath.get_uri()
buffer = source_view.get_buffer()
iter = buffer.get_iter_at_mark( buffer.get_insert() )
line = iter.get_line() + 1
line = iter.get_line()
_char = iter.get_char()
# if iter.backward_char():
# _char = iter.get_char()
if iter.backward_char():
_char = iter.get_char()
offset = iter.get_line_index() + 1
# offset = iter.get_line_offset()
result = self.lsp_controller.do_completion(source_view.get_filetype(), uri, line, offset, _char)
callback(context, result)
offset = iter.get_line_offset()
result = self.lsp_controller.do_completion(
source_view.get_filetype(),
uri,
line,
offset,
_char
)
return result
def _do_goto(self, language_id, uri, line, offset):
results = self.lsp_controller.do_goto(language_id, uri, line, offset)

View File

@ -1,3 +1,8 @@
# Python imports
# Lib imports
# Application imports
from . import lsp_structs
@ -40,13 +45,13 @@ class LspClient(object):
"""
self.lsp_endpoint.start()
return self.lsp_endpoint.call_method("initialize", \
processId = processId, \
rootPath = rootPath, \
rootUri = rootUri, \
initializationOptions = initializationOptions, \
capabilities = capabilities, \
trace = trace, \
return self.lsp_endpoint.call_method("initialize",
processId = processId,
rootPath = rootPath,
rootUri = rootUri,
initializationOptions = initializationOptions,
capabilities = capabilities,
trace = trace,
workspaceFolders = workspaceFolders
)
@ -61,18 +66,12 @@ class LspClient(object):
def shutdown(self):
"""
The initialized notification is sent from the client to the server after the client received the result of the initialize request
but before the client is sending any other request or notification to the server. The server can use the initialized notification
for example to dynamically register capabilities. The initialized notification may only be sent once.
"""
return self.lsp_endpoint.call_method("shutdown")
def exit(self):
"""
The initialized notification is sent from the client to the server after the client received the result of the initialize request
but before the client is sending any other request or notification to the server. The server can use the initialized notification
for example to dynamically register capabilities. The initialized notification may only be sent once.
"""
self.lsp_endpoint.send_notification("exit")
@ -115,7 +114,7 @@ class LspClient(object):
The document change notification is sent from the client to the server to signal changes to a text document.
In 2.0 the shape of the params has changed to include proper version numbers and language ids.
:param VersionedTextDocumentIdentifier textDocument: The initial trace setting. If omitted trace is disabled ('off').
:param TextDocumentItem textDocument: The text document.
:param TextDocumentContentChangeEvent[] contentChanges: The actual content changes. The content changes describe single state changes
to the document. So if there are two content changes c1 and c2 for a document in state S then c1 move the document
to S' and c2 to S''.

View File

@ -39,7 +39,13 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']:
return False
event_system.emit("textDocument/completion", (self._source_view, context, self.do_populate))
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):
@ -49,7 +55,9 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context, result = None):
result = event_system.emit_and_await("textDocument/completion", (self._source_view,))
proposals = []
if result:
if not result.items is None:
for item in result.items:
@ -86,6 +94,5 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
comp_item.set_icon( self.get_icon_for_type(item.kind) )
comp_item.set_info(item.documentation)
return comp_item
return comp_item

View File

@ -6,6 +6,7 @@ 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 Gio
from gi.repository import GtkSource
@ -79,7 +80,7 @@ class FileEventsMixin:
self.update_labels(gfile)
self._loading_file = False
self._file_loader.load_async(io_priority = 80,
self._file_loader.load_async(io_priority = GLib.PRIORITY_HIGH,
cancellable = None,
progress_callback = None,
progress_callback_data = None,
@ -140,8 +141,9 @@ class FileEventsMixin:
for provider in self._completion.get_providers():
self._completion.remove_provider(provider)
uri = self._current_file.get_uri()
buffer = self.get_buffer()
uri = self._current_file.get_uri()
buffer = self.get_buffer()
buffer.uri = uri
event_system.emit("textDocument/didOpen", (self._current_filetype, uri,))
@ -152,6 +154,4 @@ class FileEventsMixin:
lsp_completion_provider = LSPCompletionProvider(self)
self._completion.add_provider(lsp_completion_provider)
self.got_to_line(buffer, line)
self.got_to_line(buffer, line)

View File

@ -70,4 +70,4 @@ class EventSystem(Singleton):
if not response in (None, ''):
break
return response
return response

View File

@ -12,13 +12,27 @@ function main() {
files=()
for f in "$@"; do
# ff=${f%:*}
# ii=${f#*:}
# target=$(readlink -f "${ff}")
target=$(readlink -f "${f}")
i="${#files[@]}"
size=$(($i + 1))
files[$size]="${target}"
# if [ -n "$ii" ]; then
# files[$size]="${target}:${ii}"
# else
# files[$size]="${target}${ii}"
# fi
done
echo "${files[@]}"
cd "/opt/"
python /opt/newton.zip "${files[@]}"
}
main "$@";
main "$@";