Compare commits
20 Commits
99dc917de3
...
release/ne
| Author | SHA1 | Date | |
|---|---|---|---|
| cb73f6b3b0 | |||
| e6eaa1d83c | |||
| 62731ae766 | |||
| b5cec0d049 | |||
| c821f30880 | |||
| 13908d7ba7 | |||
| ec69d4db73 | |||
| 511138316a | |||
| d6e0823e21 | |||
| 54e7b58c24 | |||
| 77a3b71d31 | |||
| 21dd86ad3d | |||
| fea303c898 | |||
| e8653cd116 | |||
| 5e28fb1e5c | |||
| 609eaa8246 | |||
| 71bab687d7 | |||
| 060f68237b | |||
| ee5f66fbbb | |||
| 7ee484f0c0 |
32
README.md
32
README.md
@@ -1,25 +1,13 @@
|
||||
# Python-With-Gtk-Template
|
||||
A template project for Python with Gtk applications.
|
||||
|
||||
### Requirements
|
||||
* PyGObject (Gtk introspection library)
|
||||
* pygobject-stubs (For actually getting pylsp or python-language-server to auto complete in LSPs. Do if GTK3 --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2)
|
||||
* pyxdg (Desktop ".desktop" file parser)
|
||||
* setproctitle (Define process title to search and kill more easily)
|
||||
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
|
||||
# Newton
|
||||
A Python + Gtk 3 based quasi-IDE.
|
||||
|
||||
### Note
|
||||
* pyrightconfig.json can prompt IDEs that use pyright lsp on where imports are located- look at venvPath and venv. "venvPath" is parent path of "venv" where "venv" is just the name of the folder under the parent path that is the python created venv.
|
||||
* Move respetive sub folder content under user_config to the same places in Linux. Though, user/share/<app name> can go to ~/.config folder if prefered.
|
||||
* In additiion, place the plugins folder in the same app folder you moved to /usr/share/<app name> or ~/.config/<app name> .
|
||||
There are a "\<change_me\>" strings and files that need to be set according to your app's name located at:
|
||||
* \_\_builtins\_\_.py
|
||||
* user_config/bin/app_name
|
||||
* user_config/usr/share/app_name
|
||||
* user_config/usr/share/app_name/icons/app_name.png
|
||||
* user_config/usr/share/app_name/icons/app_name-64x64.png
|
||||
* user_config/usr/share/applications/app_name.desktop
|
||||
[TODO](TODO.md)
|
||||
|
||||
|
||||
For the user_config, after changing names and files, copy all content to their respective destinations.
|
||||
The logic follows Debian Dpkg packaging and its placement logic.
|
||||
### Images
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
19
TODO.md
Normal file
19
TODO.md
Normal file
@@ -0,0 +1,19 @@
|
||||
___
|
||||
### Add
|
||||
1. Add TreeSitter
|
||||
1. Add Collapsable code blocks
|
||||
1. Add Godot LSP Client
|
||||
1. Add Terminal plugin
|
||||
1. Add Plugin to <Shift\><Ctrl\>| and <Ctrl\>| to split views up, down, left, right
|
||||
1. Add <Ctrl\>i to **lsp_manager** to list who implements xyz
|
||||
|
||||
___
|
||||
### Change
|
||||
1. Make **telescope** plugin a generic base to allow query mode additions through plugins
|
||||
1. Make **lsp_manager** hard coded values configurable, plus add respective fields to UI
|
||||
|
||||
___
|
||||
### Fix
|
||||
- Fix on lsp client unload to close files lsp side and unload server endpoint
|
||||
|
||||
___
|
||||
BIN
images/pic1.png
Normal file
BIN
images/pic1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
images/pic2.png
Normal file
BIN
images/pic2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
images/pic3.png
Normal file
BIN
images/pic3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
images/pic4.png
Normal file
BIN
images/pic4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
images/pic5.png
Normal file
BIN
images/pic5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 951 KiB |
BIN
images/pic6.png
Normal file
BIN
images/pic6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 901 KiB |
@@ -39,6 +39,24 @@ class Plugin(PluginCode):
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event("unregister_command",
|
||||
command_name = "autopairs",
|
||||
command = Handler,
|
||||
binding_mode = "held",
|
||||
binding = [
|
||||
"'", "`", "[", "]",
|
||||
'<Shift>"',
|
||||
'<Shift>(',
|
||||
'<Shift>)',
|
||||
'<Shift>{',
|
||||
'<Shift>}'
|
||||
]
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
autopairs = None
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
|
||||
@@ -27,7 +27,19 @@ class Plugin(PluginCode):
|
||||
colorize.handle_colorize(event.buffer)
|
||||
|
||||
def load(self):
|
||||
event = Event_Factory.create_event("register_command",
|
||||
self._manage_signals("register_command")
|
||||
|
||||
def unload(self):
|
||||
self._manage_signals("unregister_command")
|
||||
event = Event_Factory.create_event("get_source_views")
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
for view in event.response:
|
||||
buffer = view.get_buffer()
|
||||
colorize.clear_color_tags(buffer)
|
||||
|
||||
def _manage_signals(self, action: str):
|
||||
event = Event_Factory.create_event(action,
|
||||
command_name = "tggle_colorize",
|
||||
command = Handler,
|
||||
binding_mode = "released",
|
||||
@@ -36,6 +48,7 @@ class Plugin(PluginCode):
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
|
||||
@@ -36,6 +36,16 @@ class Plugin(PluginCode):
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event("unregister_command",
|
||||
command_name = "keyboard_tggl_comment",
|
||||
command = Handler,
|
||||
binding_mode = "released",
|
||||
binding = "<Control>slash"
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
|
||||
3
plugins/code/commands/file_history/__init__.py
Normal file
3
plugins/code/commands/file_history/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Module
|
||||
"""
|
||||
3
plugins/code/commands/file_history/__main__.py
Normal file
3
plugins/code/commands/file_history/__main__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Package
|
||||
"""
|
||||
97
plugins/code/commands/file_history/autopairs.py
Normal file
97
plugins/code/commands/file_history/autopairs.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class Autopairs:
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
def handle_word_wrap(self, buffer, char_str: str):
|
||||
wrap_block = self.get_wrap_block(char_str)
|
||||
if not wrap_block: return
|
||||
|
||||
selection = buffer.get_selection_bounds()
|
||||
if not selection:
|
||||
self.insert_pair(buffer, char_str, wrap_block)
|
||||
return True
|
||||
|
||||
self.wrap_selection(buffer, char_str, wrap_block, selection)
|
||||
|
||||
return True
|
||||
|
||||
def insert_pair(
|
||||
self, buffer, char_str: str, wrap_block: tuple
|
||||
):
|
||||
buffer.begin_user_action()
|
||||
|
||||
left_block, right_block = wrap_block
|
||||
insert_mark = buffer.get_insert()
|
||||
|
||||
insert_itr = buffer.get_iter_at_mark(insert_mark)
|
||||
buffer.insert(insert_itr, f"{left_block}{right_block}")
|
||||
insert_itr = buffer.get_iter_at_mark( insert_mark )
|
||||
insert_itr.backward_char()
|
||||
|
||||
buffer.place_cursor(insert_itr)
|
||||
|
||||
buffer.end_user_action()
|
||||
|
||||
def wrap_selection(
|
||||
self, buffer, char_str: str, wrap_block: tuple, selection
|
||||
):
|
||||
left_block, \
|
||||
right_block = wrap_block
|
||||
start_itr, \
|
||||
end_itr = selection
|
||||
data = buffer.get_text(
|
||||
start_itr, end_itr, include_hidden_chars = False
|
||||
)
|
||||
start_mark = buffer.create_mark("startclose", start_itr, False)
|
||||
end_mark = buffer.create_mark("endclose", end_itr, True)
|
||||
|
||||
buffer.begin_user_action()
|
||||
|
||||
buffer.insert(start_itr, left_block)
|
||||
end_itr = buffer.get_iter_at_mark(end_mark)
|
||||
buffer.insert(end_itr, right_block)
|
||||
|
||||
start = buffer.get_iter_at_mark(start_mark)
|
||||
end = buffer.get_iter_at_mark(end_mark)
|
||||
|
||||
buffer.select_range(start, end)
|
||||
buffer.delete_mark_by_name("startclose")
|
||||
buffer.delete_mark_by_name("endclose")
|
||||
|
||||
buffer.end_user_action()
|
||||
|
||||
def get_wrap_block(self, char_str) -> tuple:
|
||||
left_block = ""
|
||||
right_block = ""
|
||||
|
||||
match char_str:
|
||||
case "(" | ")":
|
||||
left_block = "("
|
||||
right_block = ")"
|
||||
case "[" | "]":
|
||||
left_block = "["
|
||||
right_block = "]"
|
||||
case "{" | "}":
|
||||
left_block = "{"
|
||||
right_block = "}"
|
||||
case '"':
|
||||
left_block = '"'
|
||||
right_block = '"'
|
||||
case "'":
|
||||
left_block = "'"
|
||||
right_block = "'"
|
||||
case "`":
|
||||
left_block = "`"
|
||||
right_block = "`"
|
||||
case _:
|
||||
return ()
|
||||
|
||||
return left_block, right_block
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "LSP Manager",
|
||||
"name": "File History",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
65
plugins/code/commands/file_history/plugin.py
Normal file
65
plugins/code/commands/file_history/plugin.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
|
||||
|
||||
history: list = []
|
||||
history_size: int = 30
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
if isinstance(event, Code_Event_Types.RemovedFileEvent):
|
||||
if event.file.ftype == "buffer": return
|
||||
|
||||
if len(history) == history_size:
|
||||
history.pop(0)
|
||||
|
||||
history.append(event.file.fpath)
|
||||
|
||||
def load(self):
|
||||
self._manage_signals("register_command")
|
||||
|
||||
def unload(self):
|
||||
self._manage_signals("unregister_command")
|
||||
|
||||
def _manage_signals(self, action: str):
|
||||
event = Event_Factory.create_event(action,
|
||||
command_name = "file_history_pop",
|
||||
command = Handler,
|
||||
binding_mode = "released",
|
||||
binding = "<Shift><Control>t"
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
|
||||
class Handler:
|
||||
@staticmethod
|
||||
def execute(
|
||||
view: any,
|
||||
char_str: str,
|
||||
*args,
|
||||
**kwargs
|
||||
):
|
||||
logger.debug("Command: File History")
|
||||
if len(history) == 0: return
|
||||
|
||||
view._on_uri_data_received(
|
||||
[
|
||||
f"file://{history.pop()}"
|
||||
]
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from .helpers import clear_temp_cut_buffer_delayed, set_temp_cut_buffer_delayed
|
||||
|
||||
|
||||
|
||||
class Handler:
|
||||
@staticmethod
|
||||
def execute(
|
||||
view: GtkSource.View,
|
||||
*args,
|
||||
**kwargs
|
||||
):
|
||||
logger.debug("Command: Cut to Temp Buffer")
|
||||
|
||||
clear_temp_cut_buffer_delayed(view)
|
||||
|
||||
buffer = view.get_buffer()
|
||||
itr = buffer.get_iter_at_mark(buffer.get_insert())
|
||||
|
||||
start_itr = itr.copy()
|
||||
start_itr.set_line_offset(0)
|
||||
|
||||
end_itr = start_itr.copy()
|
||||
if not end_itr.forward_line():
|
||||
end_itr = buffer.get_end_iter()
|
||||
|
||||
if not hasattr(view, "_cut_buffer"):
|
||||
view._cut_buffer = ""
|
||||
|
||||
line_str = buffer.get_text(start_itr, end_itr, True)
|
||||
view._cut_buffer += line_str
|
||||
|
||||
buffer.delete(start_itr, end_itr)
|
||||
|
||||
set_temp_cut_buffer_delayed(view)
|
||||
24
plugins/code/commands/nanoesq_temp_buffer/helpers.py
Normal file
24
plugins/code/commands/nanoesq_temp_buffer/helpers.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def clear_temp_cut_buffer_delayed(view: any):
|
||||
if not hasattr(view, "_cut_temp_timeout_id"): return
|
||||
if not view._cut_temp_timeout_id: return
|
||||
|
||||
GLib.source_remove(view._cut_temp_timeout_id)
|
||||
|
||||
def set_temp_cut_buffer_delayed(view: any):
|
||||
def clear_temp_buffer(view: any):
|
||||
view._cut_buffer = ""
|
||||
view._cut_temp_timeout_id = None
|
||||
return False
|
||||
|
||||
view._cut_temp_timeout_id = GLib.timeout_add(15000, clear_temp_buffer, view)
|
||||
7
plugins/code/commands/nanoesq_temp_buffer/manifest.json
Normal file
7
plugins/code/commands/nanoesq_temp_buffer/manifest.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Nanoesq Temp Buffer",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"requests": {}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from .helpers import clear_temp_cut_buffer_delayed, set_temp_cut_buffer_delayed
|
||||
|
||||
|
||||
class Handler2:
|
||||
@staticmethod
|
||||
def execute(
|
||||
view: GtkSource.View,
|
||||
*args,
|
||||
**kwargs
|
||||
):
|
||||
logger.debug("Command: Paste Temp Buffer")
|
||||
if not hasattr(view, "_cut_temp_timeout_id"): return
|
||||
if not hasattr(view, "_cut_buffer"): return
|
||||
if not view._cut_buffer: return
|
||||
|
||||
clear_temp_cut_buffer_delayed(view)
|
||||
|
||||
buffer = view.get_buffer()
|
||||
itr = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
insert_itr = itr.copy()
|
||||
|
||||
buffer.insert(insert_itr, view._cut_buffer, -1)
|
||||
|
||||
set_temp_cut_buffer_delayed(view)
|
||||
49
plugins/code/commands/nanoesq_temp_buffer/plugin.py
Normal file
49
plugins/code/commands/nanoesq_temp_buffer/plugin.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
from .cut_to_temp_buffer import Handler
|
||||
from .paste_temp_buffer import Handler2
|
||||
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
...
|
||||
|
||||
def load(self):
|
||||
self._manage_signals("register_command")
|
||||
|
||||
def unload(self):
|
||||
self._manage_signals("unregister_command")
|
||||
|
||||
def _manage_signals(self, action: str):
|
||||
event = Event_Factory.create_event(action,
|
||||
command_name = "cut_to_temp_buffer",
|
||||
command = Handler,
|
||||
binding_mode = "held",
|
||||
binding = "<Control>k"
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
event = Event_Factory.create_event(action,
|
||||
command_name = "paste_temp_buffer",
|
||||
command = Handler2,
|
||||
binding_mode = "held",
|
||||
binding = "<Control>u"
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
@@ -26,6 +26,16 @@ class Plugin(PluginCode):
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event("unregister_command",
|
||||
command_name = "toggle_source_view",
|
||||
command = Handler,
|
||||
binding_mode = "released",
|
||||
binding = "<Shift><Control>h"
|
||||
)
|
||||
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
|
||||
@@ -35,5 +35,15 @@ class Plugin(PluginCode):
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event(
|
||||
"unregister_provider",
|
||||
provider_name = "Example Completer"
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
self.provider = None
|
||||
del self.provider
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -35,5 +35,15 @@ class Plugin(PluginCode):
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event(
|
||||
"register_provider",
|
||||
provider_name = "Python Completer"
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
self.provider = None
|
||||
del self.provider
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -38,7 +38,7 @@ class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
||||
iter.backward_char()
|
||||
|
||||
ch = iter.get_char()
|
||||
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||
# NOTE: Look to re-add or apply supporting 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()):
|
||||
|
||||
@@ -35,5 +35,15 @@ class Plugin(PluginCode):
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event(
|
||||
"unregister_provider",
|
||||
provider_name = "Snippets Completer"
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
self.provider = None
|
||||
del self.provider
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -35,5 +35,15 @@ class Plugin(PluginCode):
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event(
|
||||
"unregister_provider",
|
||||
provider_name = "Words Completer"
|
||||
)
|
||||
self.emit_to("completion", event)
|
||||
|
||||
self.provider = None
|
||||
del self.provider
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Module
|
||||
"""
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Package
|
||||
"""
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Extend Source View Menu",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"requests": {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
from .source_view_menu import extend_source_view_menu
|
||||
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
if isinstance(event, Code_Event_Types.PopulateSourceViewPopupEvent):
|
||||
extend_source_view_menu(event.buffer, event.menu)
|
||||
|
||||
def load(self):
|
||||
...
|
||||
|
||||
def unload(self):
|
||||
...
|
||||
|
||||
def run(self):
|
||||
...
|
||||
@@ -0,0 +1,68 @@
|
||||
# Python imports
|
||||
import json
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def on_case_handle(menuitem, buffer, action):
|
||||
start_itr, \
|
||||
end_itr = buffer.get_selection_bounds()
|
||||
data = buffer.get_text(start_itr, end_itr, False)
|
||||
text = data
|
||||
|
||||
if action == "on_all_upper":
|
||||
text = data.upper()
|
||||
elif action == "on_all_lower":
|
||||
text = data.lower()
|
||||
elif action == "on_invert":
|
||||
text = data.swapcase()
|
||||
elif action == "on_title":
|
||||
text = data.title()
|
||||
elif action == "on_title_strip":
|
||||
text = data.title().replace("-", "").replace("_", "").replace(" ", "")
|
||||
|
||||
buffer.begin_user_action()
|
||||
buffer.delete(start_itr, end_itr)
|
||||
buffer.insert(start_itr, text)
|
||||
buffer.end_user_action()
|
||||
|
||||
|
||||
|
||||
def extend_source_view_menu(buffer, menu):
|
||||
if not buffer.get_selection_bounds(): return
|
||||
|
||||
for child in menu.get_children():
|
||||
if not child.get_label() == "C_hange Case": continue
|
||||
menu.remove(child)
|
||||
|
||||
change_case_item = Gtk.MenuItem(label = "Change Case")
|
||||
|
||||
case_menu = Gtk.Menu()
|
||||
au_case_item = Gtk.MenuItem(label = "All Upper Case")
|
||||
al_case_item = Gtk.MenuItem(label = "All Lower Case")
|
||||
inver_case_item = Gtk.MenuItem(label = "Invert Case")
|
||||
title_case_item = Gtk.MenuItem(label = "Title Case")
|
||||
title_strip_case_item = Gtk.MenuItem(label = "Title Strip Case")
|
||||
|
||||
au_case_item.connect("activate", on_case_handle, buffer, "on_all_upper")
|
||||
al_case_item.connect("activate", on_case_handle, buffer, "on_all_lower")
|
||||
inver_case_item.connect("activate", on_case_handle, buffer, "on_invert")
|
||||
title_case_item.connect("activate", on_case_handle, buffer, "on_title")
|
||||
title_strip_case_item.connect("activate", on_case_handle, buffer, "on_title_strip")
|
||||
|
||||
case_menu.append(au_case_item)
|
||||
case_menu.append(al_case_item)
|
||||
case_menu.append(inver_case_item)
|
||||
case_menu.append(title_case_item)
|
||||
case_menu.append(title_strip_case_item)
|
||||
change_case_item.set_submenu(case_menu)
|
||||
|
||||
menu.append(change_case_item)
|
||||
@@ -21,12 +21,15 @@ class Plugin(PluginCode):
|
||||
event.file.check_file_on_disk()
|
||||
|
||||
if event.file.is_deleted():
|
||||
file_is_deleted(event)
|
||||
file_is_deleted(event, self.emit)
|
||||
elif event.file.is_externally_modified():
|
||||
file_is_externally_modified(event)
|
||||
file_is_externally_modified(event, self.emit)
|
||||
|
||||
def load(self):
|
||||
...
|
||||
|
||||
def unload(self):
|
||||
...
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -10,23 +10,23 @@ from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
|
||||
|
||||
def file_is_deleted(event):
|
||||
def file_is_deleted(event, emit):
|
||||
event.file.was_deleted = True
|
||||
event = Event_Factory.create_event(
|
||||
"file_externally_deleted",
|
||||
file = event.file,
|
||||
buffer = event.buffer
|
||||
)
|
||||
self.emit(event)
|
||||
emit(event)
|
||||
|
||||
|
||||
def file_is_externally_modified(event):
|
||||
def file_is_externally_modified(event, emit):
|
||||
# event = Event_Factory.create_event(
|
||||
# "file_externally_modified",
|
||||
# file = event.file,
|
||||
# buffer = event.buffer
|
||||
# )
|
||||
# self.emit(event)
|
||||
# emit(event)
|
||||
|
||||
...
|
||||
|
||||
|
||||
@@ -32,5 +32,8 @@ class Plugin(PluginCode):
|
||||
def load(self):
|
||||
...
|
||||
|
||||
def unload(self):
|
||||
...
|
||||
|
||||
def run(self):
|
||||
...
|
||||
|
||||
@@ -13,8 +13,6 @@ from gi.repository import Gtk
|
||||
|
||||
|
||||
def add_prettify_json(buffer, menu):
|
||||
menu.append( Gtk.SeparatorMenuItem() )
|
||||
|
||||
def on_prettify_json(menuitem, buffer):
|
||||
start_itr, \
|
||||
end_itr = buffer.get_start_iter(), buffer.get_end_iter()
|
||||
@@ -28,4 +26,4 @@ def add_prettify_json(buffer, menu):
|
||||
|
||||
item = Gtk.MenuItem(label = "Prettify JSON")
|
||||
item.connect("activate", on_prettify_json, buffer)
|
||||
menu.append(item)
|
||||
menu.append(item)
|
||||
3
plugins/code/event-watchers/tree_sitter/__init__.py
Normal file
3
plugins/code/event-watchers/tree_sitter/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Module
|
||||
"""
|
||||
3
plugins/code/event-watchers/tree_sitter/__main__.py
Normal file
3
plugins/code/event-watchers/tree_sitter/__main__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Package
|
||||
"""
|
||||
39
plugins/code/event-watchers/tree_sitter/compile.py
Normal file
39
plugins/code/event-watchers/tree_sitter/compile.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from .libs.tree_sitter_language_pack import \
|
||||
init, download, get_language, get_parser, available_languages, process, ProcessConfig
|
||||
|
||||
# Optional: Pre-download specific languages for offline use
|
||||
#init(["python", "javascript", "rust"])
|
||||
|
||||
# Get a language (auto-downloads if not cached)
|
||||
language = get_language("python")
|
||||
|
||||
# Get a pre-configured parser (auto-downloads if needed)
|
||||
parser = get_parser("python")
|
||||
tree = parser.parse(b"def hello(): pass")
|
||||
print(tree.root_node)
|
||||
|
||||
# List all available languages
|
||||
for lang in available_languages():
|
||||
print(lang)
|
||||
|
||||
|
||||
# Extract file intelligence (auto-downloads language if needed)
|
||||
result = process(
|
||||
"def hello(): pass",
|
||||
ProcessConfig( language = "python")
|
||||
)
|
||||
print(f"Functions: {len(result['structure'])}")
|
||||
|
||||
# Pre-download languages for offline use
|
||||
download(["python", "javascript"])
|
||||
|
||||
# With chunking
|
||||
result = process(
|
||||
source,
|
||||
ProcessConfig(
|
||||
language = "python",
|
||||
chunk_max_size = 1000,
|
||||
comments = True
|
||||
)
|
||||
)
|
||||
print(f"Chunks: {len(result['chunks'])}")
|
||||
3
plugins/code/event-watchers/tree_sitter/libs/__init__.py
Normal file
3
plugins/code/event-watchers/tree_sitter/libs/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Libs Module
|
||||
"""
|
||||
@@ -0,0 +1,71 @@
|
||||
"""Python bindings to the Tree-sitter parsing library."""
|
||||
|
||||
from typing import Protocol as _Protocol
|
||||
|
||||
from ._binding import (
|
||||
Language,
|
||||
LogType,
|
||||
LookaheadIterator,
|
||||
Node,
|
||||
Parser,
|
||||
Point,
|
||||
Query,
|
||||
QueryCursor,
|
||||
QueryError,
|
||||
Range,
|
||||
Tree,
|
||||
TreeCursor,
|
||||
LANGUAGE_VERSION,
|
||||
MIN_COMPATIBLE_LANGUAGE_VERSION,
|
||||
)
|
||||
|
||||
LogType.__doc__ = "The type of a log message."
|
||||
|
||||
Point.__doc__ = "A position in a multi-line text document, in terms of rows and columns."
|
||||
Point.row.__doc__ = "The zero-based row of the document."
|
||||
Point.column.__doc__ = "The zero-based column of the document."
|
||||
|
||||
|
||||
class QueryPredicate(_Protocol):
|
||||
"""A custom query predicate that runs on a pattern."""
|
||||
def __call__(self, predicate, args, pattern_index, captures):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
|
||||
predicate : str
|
||||
The name of the predicate.
|
||||
args : list[tuple[str, typing.Literal['capture', 'string']]]
|
||||
The arguments to the predicate.
|
||||
pattern_index : int
|
||||
The index of the pattern within the query.
|
||||
captures : dict[str, list[Node]]
|
||||
The captures contained in the pattern.
|
||||
|
||||
Returns
|
||||
-------
|
||||
``True`` if the predicate matches, ``False`` otherwise.
|
||||
|
||||
Tip
|
||||
---
|
||||
You don't need to create an actual class, just a function with this signature.
|
||||
"""
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Language",
|
||||
"LogType",
|
||||
"LookaheadIterator",
|
||||
"Node",
|
||||
"Parser",
|
||||
"Point",
|
||||
"Query",
|
||||
"QueryCursor",
|
||||
"QueryError",
|
||||
"QueryPredicate",
|
||||
"Range",
|
||||
"Tree",
|
||||
"TreeCursor",
|
||||
"LANGUAGE_VERSION",
|
||||
"MIN_COMPATIBLE_LANGUAGE_VERSION",
|
||||
]
|
||||
@@ -0,0 +1,416 @@
|
||||
from enum import IntEnum
|
||||
from collections.abc import ByteString, Callable, Iterator, Sequence
|
||||
from typing import Annotated, Any, Final, Literal, NamedTuple, Protocol, Self, final, overload
|
||||
from typing_extensions import deprecated
|
||||
|
||||
class _SupportsFileno(Protocol):
|
||||
def fileno(self) -> int: ...
|
||||
|
||||
class Point(NamedTuple):
|
||||
row: int
|
||||
column: int
|
||||
|
||||
class LogType(IntEnum):
|
||||
PARSE: int
|
||||
LEX: int
|
||||
|
||||
@final
|
||||
class Language:
|
||||
@overload
|
||||
@deprecated("int argument support is deprecated")
|
||||
def __init__(self, ptr: Annotated[int, "TSLanguage *"], /) -> None: ...
|
||||
@overload
|
||||
def __init__(self, ptr: Annotated[object, "TSLanguage *"], /) -> None: ...
|
||||
@property
|
||||
def name(self) -> str | None: ...
|
||||
@property
|
||||
def abi_version(self) -> int: ...
|
||||
@property
|
||||
def semantic_version(self) -> tuple[int, int, int] | None: ...
|
||||
@deprecated("Use abi_version instead")
|
||||
@property
|
||||
def version(self) -> int: ...
|
||||
@property
|
||||
def node_kind_count(self) -> int: ...
|
||||
@property
|
||||
def parse_state_count(self) -> int: ...
|
||||
@property
|
||||
def field_count(self) -> int: ...
|
||||
@property
|
||||
def supertypes(self) -> tuple[int, ...]: ...
|
||||
def subtypes(self, supertype: int, /) -> tuple[int, ...]: ...
|
||||
def node_kind_for_id(self, id: int, /) -> str | None: ...
|
||||
def id_for_node_kind(self, kind: str, named: bool, /) -> int | None: ...
|
||||
def node_kind_is_named(self, id: int, /) -> bool: ...
|
||||
def node_kind_is_visible(self, id: int, /) -> bool: ...
|
||||
def node_kind_is_supertype(self, id: int, /) -> bool: ...
|
||||
def field_name_for_id(self, field_id: int, /) -> str | None: ...
|
||||
def field_id_for_name(self, name: str, /) -> int | None: ...
|
||||
def next_state(self, state: int, id: int, /) -> int: ...
|
||||
def lookahead_iterator(self, state: int, /) -> LookaheadIterator | None: ...
|
||||
@deprecated("Use the Query() constructor instead")
|
||||
def query(self, source: str, /) -> Query: ...
|
||||
def copy(self) -> Language: ...
|
||||
def __repr__(self) -> str: ...
|
||||
def __eq__(self, other: Any, /) -> bool: ...
|
||||
def __ne__(self, other: Any, /) -> bool: ...
|
||||
def __hash__(self) -> int: ...
|
||||
def __copy__(self) -> Language: ...
|
||||
|
||||
@final
|
||||
class Node:
|
||||
@property
|
||||
def id(self) -> int: ...
|
||||
@property
|
||||
def kind_id(self) -> int: ...
|
||||
@property
|
||||
def grammar_id(self) -> int: ...
|
||||
@property
|
||||
def grammar_name(self) -> str: ...
|
||||
@property
|
||||
def type(self) -> str: ...
|
||||
@property
|
||||
def is_named(self) -> bool: ...
|
||||
@property
|
||||
def is_extra(self) -> bool: ...
|
||||
@property
|
||||
def has_changes(self) -> bool: ...
|
||||
@property
|
||||
def has_error(self) -> bool: ...
|
||||
@property
|
||||
def is_error(self) -> bool: ...
|
||||
@property
|
||||
def parse_state(self) -> int: ...
|
||||
@property
|
||||
def next_parse_state(self) -> int: ...
|
||||
@property
|
||||
def is_missing(self) -> bool: ...
|
||||
@property
|
||||
def start_byte(self) -> int: ...
|
||||
@property
|
||||
def end_byte(self) -> int: ...
|
||||
@property
|
||||
def byte_range(self) -> tuple[int, int]: ...
|
||||
@property
|
||||
def range(self) -> Range: ...
|
||||
@property
|
||||
def start_point(self) -> Point: ...
|
||||
@property
|
||||
def end_point(self) -> Point: ...
|
||||
@property
|
||||
def children(self) -> list[Node]: ...
|
||||
@property
|
||||
def child_count(self) -> int: ...
|
||||
@property
|
||||
def named_children(self) -> list[Node]: ...
|
||||
@property
|
||||
def named_child_count(self) -> int: ...
|
||||
@property
|
||||
def parent(self) -> Node | None: ...
|
||||
@property
|
||||
def next_sibling(self) -> Node | None: ...
|
||||
@property
|
||||
def prev_sibling(self) -> Node | None: ...
|
||||
@property
|
||||
def next_named_sibling(self) -> Node | None: ...
|
||||
@property
|
||||
def prev_named_sibling(self) -> Node | None: ...
|
||||
@property
|
||||
def descendant_count(self) -> int: ...
|
||||
@property
|
||||
def text(self) -> bytes | None: ...
|
||||
def walk(self) -> TreeCursor: ...
|
||||
def edit(
|
||||
self,
|
||||
start_byte: int,
|
||||
old_end_byte: int,
|
||||
new_end_byte: int,
|
||||
start_point: Point | tuple[int, int],
|
||||
old_end_point: Point | tuple[int, int],
|
||||
new_end_point: Point | tuple[int, int],
|
||||
) -> None: ...
|
||||
def child(self, index: int, /) -> Node | None: ...
|
||||
def named_child(self, index: int, /) -> Node | None: ...
|
||||
def first_child_for_byte(self, byte: int, /) -> Node | None: ...
|
||||
def first_named_child_for_byte(self, byte: int, /) -> Node | None: ...
|
||||
def child_by_field_id(self, id: int, /) -> Node | None: ...
|
||||
def child_by_field_name(self, name: str, /) -> Node | None: ...
|
||||
def child_with_descendant(self, descendant: Node, /) -> Node | None: ...
|
||||
def children_by_field_id(self, id: int, /) -> list[Node]: ...
|
||||
def children_by_field_name(self, name: str, /) -> list[Node]: ...
|
||||
def field_name_for_child(self, child_index: int, /) -> str | None: ...
|
||||
def field_name_for_named_child(self, child_index: int, /) -> str | None: ...
|
||||
def descendant_for_byte_range(
|
||||
self,
|
||||
start_byte: int,
|
||||
end_byte: int,
|
||||
/,
|
||||
) -> Node | None: ...
|
||||
def named_descendant_for_byte_range(
|
||||
self,
|
||||
start_byte: int,
|
||||
end_byte: int,
|
||||
/,
|
||||
) -> Node | None: ...
|
||||
def descendant_for_point_range(
|
||||
self,
|
||||
start_point: Point | tuple[int, int],
|
||||
end_point: Point | tuple[int, int],
|
||||
/,
|
||||
) -> Node | None: ...
|
||||
def named_descendant_for_point_range(
|
||||
self,
|
||||
start_point: Point | tuple[int, int],
|
||||
end_point: Point | tuple[int, int],
|
||||
/,
|
||||
) -> Node | None: ...
|
||||
def __repr__(self) -> str: ...
|
||||
def __str__(self) -> str: ...
|
||||
def __eq__(self, other: Any, /) -> bool: ...
|
||||
def __ne__(self, other: Any, /) -> bool: ...
|
||||
def __hash__(self) -> int: ...
|
||||
|
||||
@final
|
||||
class Tree:
|
||||
@property
|
||||
def root_node(self) -> Node: ...
|
||||
@property
|
||||
def included_ranges(self) -> list[Range]: ...
|
||||
@property
|
||||
def language(self) -> Language: ...
|
||||
def root_node_with_offset(
|
||||
self,
|
||||
offset_bytes: int,
|
||||
offset_extent: Point | tuple[int, int],
|
||||
/,
|
||||
) -> Node | None: ...
|
||||
def copy(self) -> Tree: ...
|
||||
def edit(
|
||||
self,
|
||||
start_byte: int,
|
||||
old_end_byte: int,
|
||||
new_end_byte: int,
|
||||
start_point: Point | tuple[int, int],
|
||||
old_end_point: Point | tuple[int, int],
|
||||
new_end_point: Point | tuple[int, int],
|
||||
) -> None: ...
|
||||
def walk(self) -> TreeCursor: ...
|
||||
def changed_ranges(self, new_tree: Tree, /) -> list[Range]: ...
|
||||
def print_dot_graph(self, file: _SupportsFileno, /) -> None: ...
|
||||
def __copy__(self) -> Tree: ...
|
||||
|
||||
@final
|
||||
class TreeCursor:
|
||||
@property
|
||||
def node(self) -> Node | None: ...
|
||||
@property
|
||||
def field_id(self) -> int | None: ...
|
||||
@property
|
||||
def field_name(self) -> str | None: ...
|
||||
@property
|
||||
def depth(self) -> int: ...
|
||||
@property
|
||||
def descendant_index(self) -> int: ...
|
||||
def copy(self) -> TreeCursor: ...
|
||||
def reset(self, node: Node, /) -> None: ...
|
||||
def reset_to(self, cursor: TreeCursor, /) -> None: ...
|
||||
def goto_first_child(self) -> bool: ...
|
||||
def goto_last_child(self) -> bool: ...
|
||||
def goto_parent(self) -> bool: ...
|
||||
def goto_next_sibling(self) -> bool: ...
|
||||
def goto_previous_sibling(self) -> bool: ...
|
||||
def goto_descendant(self, index: int, /) -> None: ...
|
||||
def goto_first_child_for_byte(self, byte: int, /) -> int | None: ...
|
||||
def goto_first_child_for_point(self, point: Point | tuple[int, int], /) -> int | None: ...
|
||||
def __copy__(self) -> TreeCursor: ...
|
||||
|
||||
@final
|
||||
class Parser:
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
language: Language | None = None,
|
||||
*,
|
||||
included_ranges: Sequence[Range] | None = None,
|
||||
logger: Callable[[LogType, str], None] | None = None,
|
||||
) -> None: ...
|
||||
@deprecated("timeout_micros is deprecated")
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
language: Language | None = None,
|
||||
*,
|
||||
included_ranges: Sequence[Range] | None = None,
|
||||
timeout_micros: int | None = None,
|
||||
logger: Callable[[LogType, str], None] | None = None,
|
||||
) -> None: ...
|
||||
@property
|
||||
def language(self) -> Language | None: ...
|
||||
@language.setter
|
||||
def language(self, language: Language) -> None: ...
|
||||
@language.deleter
|
||||
def language(self) -> None: ...
|
||||
@property
|
||||
def included_ranges(self) -> list[Range]: ...
|
||||
@included_ranges.setter
|
||||
def included_ranges(self, ranges: Sequence[Range]) -> None: ...
|
||||
@included_ranges.deleter
|
||||
def included_ranges(self) -> None: ...
|
||||
@deprecated("Use the progress_callback in parse()")
|
||||
@property
|
||||
def timeout_micros(self) -> int: ...
|
||||
@deprecated("Use the progress_callback in parse()")
|
||||
@timeout_micros.setter
|
||||
def timeout_micros(self, timeout: int) -> None: ...
|
||||
@deprecated("Use the progress_callback in parse()")
|
||||
@timeout_micros.deleter
|
||||
def timeout_micros(self) -> None: ...
|
||||
@property
|
||||
def logger(self) -> Callable[[LogType, str], None] | None: ...
|
||||
@logger.setter
|
||||
def logger(self, logger: Callable[[LogType, str], None]) -> None: ...
|
||||
@logger.deleter
|
||||
def logger(self) -> None: ...
|
||||
@overload
|
||||
def parse(
|
||||
self,
|
||||
source: ByteString,
|
||||
/,
|
||||
old_tree: Tree | None = None,
|
||||
encoding: Literal["utf8", "utf16", "utf16le", "utf16be"] = "utf8",
|
||||
) -> Tree: ...
|
||||
@overload
|
||||
def parse(
|
||||
self,
|
||||
read_callback: Callable[[int, Point], ByteString | None],
|
||||
/,
|
||||
old_tree: Tree | None = None,
|
||||
encoding: Literal["utf8", "utf16", "utf16le", "utf16be"] = "utf8",
|
||||
progress_callback: Callable[[int, bool], bool] | None = None,
|
||||
) -> Tree: ...
|
||||
def reset(self) -> None: ...
|
||||
def print_dot_graphs(self, file: _SupportsFileno | None, /) -> None: ...
|
||||
|
||||
class QueryError(ValueError): ...
|
||||
|
||||
class QueryPredicate(Protocol):
|
||||
def __call__(
|
||||
self,
|
||||
predicate: str,
|
||||
args: list[tuple[str, Literal["capture", "string"]]],
|
||||
pattern_index: int,
|
||||
captures: dict[str, list[Node]],
|
||||
) -> bool: ...
|
||||
|
||||
@final
|
||||
class Query:
|
||||
def __new__(cls, language: Language, source: str, /) -> Self: ...
|
||||
def pattern_count(self) -> int: ...
|
||||
def capture_count(self) -> int: ...
|
||||
def string_count(self) -> int: ...
|
||||
def start_byte_for_pattern(self, index: int, /) -> int: ...
|
||||
def end_byte_for_pattern(self, index: int, /) -> int: ...
|
||||
def is_pattern_rooted(self, index: int, /) -> bool: ...
|
||||
def is_pattern_non_local(self, index: int, /) -> bool: ...
|
||||
def is_pattern_guaranteed_at_step(self, index: int, /) -> bool: ...
|
||||
def capture_name(self, index: int, /) -> str: ...
|
||||
def capture_quantifier(
|
||||
self,
|
||||
pattern_index: int,
|
||||
capture_index: int,
|
||||
/
|
||||
) -> Literal["", "?", "*", "+"]: ...
|
||||
def string_value(self, index: int, /) -> str: ...
|
||||
def disable_capture(self, name: str, /) -> None: ...
|
||||
def disable_pattern(self, index: int, /) -> None: ...
|
||||
def pattern_settings(self, index: int, /) -> dict[str, str | None]: ...
|
||||
def pattern_assertions(self, index: int, /) -> dict[str, tuple[str | None, bool]]: ...
|
||||
|
||||
@final
|
||||
class QueryCursor:
|
||||
@overload
|
||||
def __init__(self, query: Query, *, match_limit: int = 0xFFFFFFFF) -> None: ...
|
||||
@deprecated("timeout_micros is deprecated")
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
query: Query,
|
||||
*,
|
||||
match_limit: int = 0xFFFFFFFF,
|
||||
timeout_micros: int = 0
|
||||
) -> None: ...
|
||||
@property
|
||||
def match_limit(self) -> int: ...
|
||||
@match_limit.setter
|
||||
def match_limit(self, limit: int) -> None: ...
|
||||
@match_limit.deleter
|
||||
def match_limit(self) -> None: ...
|
||||
@deprecated("Use the progress_callback in matches() or captures()")
|
||||
@property
|
||||
def timeout_micros(self) -> int: ...
|
||||
@deprecated("Use the progress_callback in matches() or captures()")
|
||||
@timeout_micros.setter
|
||||
def timeout_micros(self, timeout: int) -> None: ...
|
||||
@property
|
||||
def did_exceed_match_limit(self) -> bool: ...
|
||||
def set_max_start_depth(self, depth: int, /) -> None: ...
|
||||
def set_byte_range(self, start: int, end: int, /) -> None: ...
|
||||
def set_point_range(
|
||||
self,
|
||||
start: Point | tuple[int, int],
|
||||
end: Point | tuple[int, int],
|
||||
/,
|
||||
) -> None: ...
|
||||
def captures(
|
||||
self,
|
||||
node: Node,
|
||||
predicate: QueryPredicate | None = None,
|
||||
progress_callback: Callable[[int], bool] | None = None,
|
||||
/,
|
||||
) -> dict[str, list[Node]]: ...
|
||||
def matches(
|
||||
self,
|
||||
node: Node,
|
||||
predicate: QueryPredicate | None = None,
|
||||
progress_callback: Callable[[int], bool] | None = None,
|
||||
/,
|
||||
) -> list[tuple[int, dict[str, list[Node]]]]: ...
|
||||
|
||||
@final
|
||||
class LookaheadIterator(Iterator[tuple[int, str]]):
|
||||
@property
|
||||
def language(self) -> Language: ...
|
||||
@property
|
||||
def current_symbol(self) -> int: ...
|
||||
@property
|
||||
def current_symbol_name(self) -> str: ...
|
||||
def reset(self, state: int, /, language: Language | None = None) -> bool: ...
|
||||
def names(self) -> list[str]: ...
|
||||
def symbols(self) -> list[int]: ...
|
||||
def __next__(self) -> tuple[int, str]: ...
|
||||
|
||||
@final
|
||||
class Range:
|
||||
def __init__(
|
||||
self,
|
||||
start_point: Point | tuple[int, int],
|
||||
end_point: Point | tuple[int, int],
|
||||
start_byte: int,
|
||||
end_byte: int,
|
||||
) -> None: ...
|
||||
@property
|
||||
def start_point(self) -> Point: ...
|
||||
@property
|
||||
def end_point(self) -> Point: ...
|
||||
@property
|
||||
def start_byte(self) -> int: ...
|
||||
@property
|
||||
def end_byte(self) -> int: ...
|
||||
def __eq__(self, other: Any, /) -> bool: ...
|
||||
def __ne__(self, other: Any, /) -> bool: ...
|
||||
def __repr__(self) -> str: ...
|
||||
def __hash__(self) -> int: ...
|
||||
|
||||
LANGUAGE_VERSION: Final[int]
|
||||
|
||||
MIN_COMPATIBLE_LANGUAGE_VERSION: Final[int]
|
||||
@@ -0,0 +1,54 @@
|
||||
from typing import TypeAlias
|
||||
|
||||
from tree_sitter_language_pack._native import (
|
||||
DownloadError,
|
||||
LanguageNotFoundError,
|
||||
ParseError,
|
||||
ProcessConfig,
|
||||
QueryError,
|
||||
TreeHandle,
|
||||
available_languages,
|
||||
cache_dir,
|
||||
clean_cache,
|
||||
configure,
|
||||
download,
|
||||
download_all,
|
||||
downloaded_languages,
|
||||
get_binding,
|
||||
get_language,
|
||||
get_parser,
|
||||
has_language,
|
||||
init,
|
||||
language_count,
|
||||
manifest_languages,
|
||||
parse_string,
|
||||
process,
|
||||
)
|
||||
|
||||
SupportedLanguage: TypeAlias = str
|
||||
|
||||
__all__ = [
|
||||
"DownloadError",
|
||||
"LanguageNotFoundError",
|
||||
"ParseError",
|
||||
"ProcessConfig",
|
||||
"QueryError",
|
||||
"SupportedLanguage",
|
||||
"TreeHandle",
|
||||
"available_languages",
|
||||
"cache_dir",
|
||||
"clean_cache",
|
||||
"configure",
|
||||
"download",
|
||||
"download_all",
|
||||
"downloaded_languages",
|
||||
"get_binding",
|
||||
"get_language",
|
||||
"get_parser",
|
||||
"has_language",
|
||||
"init",
|
||||
"language_count",
|
||||
"manifest_languages",
|
||||
"parse_string",
|
||||
"process",
|
||||
]
|
||||
@@ -0,0 +1,276 @@
|
||||
from typing import Literal, TypeAlias
|
||||
|
||||
from tree_sitter import Language, Parser
|
||||
|
||||
class LanguageNotFoundError(ValueError): ...
|
||||
class DownloadError(RuntimeError): ...
|
||||
|
||||
SupportedLanguage: TypeAlias = Literal[
|
||||
"actionscript",
|
||||
"ada",
|
||||
"agda",
|
||||
"apex",
|
||||
"arduino",
|
||||
"asm",
|
||||
"astro",
|
||||
"bash",
|
||||
"batch",
|
||||
"bazel",
|
||||
"beancount",
|
||||
"bibtex",
|
||||
"bicep",
|
||||
"bitbake",
|
||||
"bsl",
|
||||
"c",
|
||||
"cairo",
|
||||
"capnp",
|
||||
"chatito",
|
||||
"clarity",
|
||||
"clojure",
|
||||
"cmake",
|
||||
"cobol",
|
||||
"comment",
|
||||
"commonlisp",
|
||||
"cpon",
|
||||
"cpp",
|
||||
"css",
|
||||
"csv",
|
||||
"cuda",
|
||||
"d",
|
||||
"dart",
|
||||
"diff",
|
||||
"dockerfile",
|
||||
"doxygen",
|
||||
"dtd",
|
||||
"elisp",
|
||||
"elixir",
|
||||
"elm",
|
||||
"erlang",
|
||||
"fennel",
|
||||
"firrtl",
|
||||
"fish",
|
||||
"fortran",
|
||||
"fsharp",
|
||||
"fsharp_signature",
|
||||
"func",
|
||||
"gdscript",
|
||||
"gitattributes",
|
||||
"gitcommit",
|
||||
"gitignore",
|
||||
"gleam",
|
||||
"glsl",
|
||||
"gn",
|
||||
"go",
|
||||
"gomod",
|
||||
"gosum",
|
||||
"gradle",
|
||||
"graphql",
|
||||
"groovy",
|
||||
"gstlaunch",
|
||||
"hack",
|
||||
"hare",
|
||||
"haskell",
|
||||
"haxe",
|
||||
"hcl",
|
||||
"heex",
|
||||
"hlsl",
|
||||
"html",
|
||||
"hyprlang",
|
||||
"ignorefile",
|
||||
"ini",
|
||||
"ispc",
|
||||
"janet",
|
||||
"java",
|
||||
"javascript",
|
||||
"jsdoc",
|
||||
"json",
|
||||
"jsonnet",
|
||||
"julia",
|
||||
"kconfig",
|
||||
"kdl",
|
||||
"kotlin",
|
||||
"latex",
|
||||
"linkerscript",
|
||||
"lisp",
|
||||
"llvm",
|
||||
"lua",
|
||||
"luadoc",
|
||||
"luap",
|
||||
"luau",
|
||||
"magik",
|
||||
"make",
|
||||
"makefile",
|
||||
"markdown",
|
||||
"markdown_inline",
|
||||
"matlab",
|
||||
"mermaid",
|
||||
"meson",
|
||||
"netlinx",
|
||||
"nim",
|
||||
"ninja",
|
||||
"nix",
|
||||
"nqc",
|
||||
"objc",
|
||||
"ocaml",
|
||||
"ocaml_interface",
|
||||
"odin",
|
||||
"org",
|
||||
"pascal",
|
||||
"pem",
|
||||
"perl",
|
||||
"pgn",
|
||||
"php",
|
||||
"pkl",
|
||||
"po",
|
||||
"pony",
|
||||
"powershell",
|
||||
"printf",
|
||||
"prisma",
|
||||
"properties",
|
||||
"proto",
|
||||
"psv",
|
||||
"puppet",
|
||||
"purescript",
|
||||
"pymanifest",
|
||||
"python",
|
||||
"qmldir",
|
||||
"qmljs",
|
||||
"query",
|
||||
"r",
|
||||
"racket",
|
||||
"re2c",
|
||||
"readline",
|
||||
"rego",
|
||||
"requirements",
|
||||
"ron",
|
||||
"rst",
|
||||
"ruby",
|
||||
"rust",
|
||||
"scala",
|
||||
"scheme",
|
||||
"scss",
|
||||
"shell",
|
||||
"smali",
|
||||
"smithy",
|
||||
"solidity",
|
||||
"sparql",
|
||||
"sql",
|
||||
"squirrel",
|
||||
"starlark",
|
||||
"svelte",
|
||||
"swift",
|
||||
"tablegen",
|
||||
"tcl",
|
||||
"terraform",
|
||||
"test",
|
||||
"thrift",
|
||||
"toml",
|
||||
"tsv",
|
||||
"tsx",
|
||||
"twig",
|
||||
"typescript",
|
||||
"typst",
|
||||
"udev",
|
||||
"ungrammar",
|
||||
"uxntal",
|
||||
"v",
|
||||
"verilog",
|
||||
"vhdl",
|
||||
"vim",
|
||||
"vue",
|
||||
"wast",
|
||||
"wat",
|
||||
"wgsl",
|
||||
"xcompose",
|
||||
"xml",
|
||||
"yuck",
|
||||
"zig",
|
||||
]
|
||||
|
||||
class ParseError(RuntimeError): ...
|
||||
class QueryError(ValueError): ...
|
||||
|
||||
class ProcessConfig:
|
||||
language: str
|
||||
structure: bool
|
||||
imports: bool
|
||||
exports: bool
|
||||
comments: bool
|
||||
docstrings: bool
|
||||
symbols: bool
|
||||
diagnostics: bool
|
||||
chunk_max_size: int | None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
language: str,
|
||||
*,
|
||||
structure: bool = True,
|
||||
imports: bool = True,
|
||||
exports: bool = True,
|
||||
comments: bool = True,
|
||||
docstrings: bool = True,
|
||||
symbols: bool = True,
|
||||
diagnostics: bool = True,
|
||||
chunk_max_size: int | None = None,
|
||||
) -> None: ...
|
||||
@staticmethod
|
||||
def all(language: str) -> ProcessConfig: ...
|
||||
@staticmethod
|
||||
def minimal(language: str) -> ProcessConfig: ...
|
||||
|
||||
class TreeHandle:
|
||||
def root_node_type(self) -> str: ...
|
||||
def root_child_count(self) -> int: ...
|
||||
def contains_node_type(self, node_type: str) -> bool: ...
|
||||
def has_error_nodes(self) -> bool: ...
|
||||
def to_sexp(self) -> str: ...
|
||||
def error_count(self) -> int: ...
|
||||
def root_node_info(self) -> dict[str, object]: ...
|
||||
def find_nodes_by_type(self, node_type: str) -> list[dict[str, object]]: ...
|
||||
def named_children_info(self) -> list[dict[str, object]]: ...
|
||||
def extract_text(self, start_byte: int, end_byte: int) -> str: ...
|
||||
def run_query(self, language: str, query_source: str) -> list[dict[str, object]]: ...
|
||||
|
||||
__all__ = [
|
||||
"DownloadError",
|
||||
"LanguageNotFoundError",
|
||||
"ParseError",
|
||||
"ProcessConfig",
|
||||
"QueryError",
|
||||
"SupportedLanguage",
|
||||
"TreeHandle",
|
||||
"available_languages",
|
||||
"cache_dir",
|
||||
"clean_cache",
|
||||
"configure",
|
||||
"download",
|
||||
"download_all",
|
||||
"downloaded_languages",
|
||||
"get_binding",
|
||||
"get_language",
|
||||
"get_parser",
|
||||
"has_language",
|
||||
"init",
|
||||
"language_count",
|
||||
"manifest_languages",
|
||||
"parse_string",
|
||||
"process",
|
||||
]
|
||||
|
||||
def get_binding(name: SupportedLanguage) -> object: ...
|
||||
def get_language(name: SupportedLanguage) -> Language: ...
|
||||
def get_parser(name: SupportedLanguage) -> Parser: ...
|
||||
def available_languages() -> list[str]: ...
|
||||
def has_language(name: str) -> bool: ...
|
||||
def language_count() -> int: ...
|
||||
def parse_string(language: str, source: str) -> TreeHandle: ...
|
||||
def process(source: str, config: ProcessConfig) -> dict[str, object]: ...
|
||||
def init(config: dict[str, object]) -> None: ...
|
||||
def configure(*, cache_dir: str | None = None) -> None: ...
|
||||
def download(names: list[str]) -> int: ...
|
||||
def download_all() -> int: ...
|
||||
def manifest_languages() -> list[str]: ...
|
||||
def downloaded_languages() -> list[str]: ...
|
||||
def clean_cache() -> None: ...
|
||||
def cache_dir() -> str: ...
|
||||
9
plugins/code/event-watchers/tree_sitter/manifest.json
Normal file
9
plugins/code/event-watchers/tree_sitter/manifest.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Tree-sitter",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"pre_launch": true,
|
||||
"autoload": false,
|
||||
"requests": {}
|
||||
}
|
||||
17
plugins/code/event-watchers/tree_sitter/notes/compile.py
Normal file
17
plugins/code/event-watchers/tree_sitter/notes/compile.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from .tree_sitter import Language
|
||||
|
||||
Language.build_library(
|
||||
"my-languages.so",
|
||||
[
|
||||
"tree-sitter-python",
|
||||
"tree-sitter-javascript",
|
||||
"tree-sitter-html",
|
||||
"tree-sitter-css",
|
||||
"tree-sitter-json",
|
||||
"tree-sitter-java",
|
||||
"tree-sitter-c",
|
||||
"tree-sitter-cpp",
|
||||
"tree-sitter-go",
|
||||
"tree-sitter-gdscript",
|
||||
],
|
||||
)
|
||||
121
plugins/code/event-watchers/tree_sitter/notes/setup-tree-sitter.sh
Executable file
121
plugins/code/event-watchers/tree_sitter/notes/setup-tree-sitter.sh
Executable file
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
|
||||
# . CONFIG.sh
|
||||
|
||||
# set -o xtrace ## To debug scripts
|
||||
# set -o errexit ## To exit on error
|
||||
# set -o errunset ## To exit if a variable is referenced but not set
|
||||
|
||||
|
||||
|
||||
|
||||
function old_build() {
|
||||
touch __init__.py
|
||||
|
||||
cat <<'EOF' > compile.py
|
||||
from tree_sitter import Language
|
||||
|
||||
Language.build_library(
|
||||
"my-languages.so",
|
||||
[
|
||||
"tree-sitter-python",
|
||||
"tree-sitter-javascript",
|
||||
"tree-sitter-html",
|
||||
"tree-sitter-css",
|
||||
"tree-sitter-json",
|
||||
"tree-sitter-java",
|
||||
"tree-sitter-c",
|
||||
"tree-sitter-cpp",
|
||||
"tree-sitter-go"
|
||||
"tree-sitter-gdscript",
|
||||
],
|
||||
)
|
||||
EOF
|
||||
|
||||
python compile.py
|
||||
cd ..
|
||||
}
|
||||
|
||||
function build() {
|
||||
touch __init__.py
|
||||
|
||||
cat <<'EOF' > compile.py
|
||||
from tree_sitter_language_pack import init, download, get_language, get_parser, available_languages
|
||||
from tree_sitter_language_pack import process, ProcessConfig
|
||||
|
||||
# Optional: Pre-download specific languages for offline use
|
||||
# init(["python", "javascript", "rust"])
|
||||
|
||||
# Get a language (auto-downloads if not cached)
|
||||
language = get_language("python")
|
||||
|
||||
# Get a pre-configured parser (auto-downloads if needed)
|
||||
parser = get_parser("python")
|
||||
tree = parser.parse(b"def hello(): pass")
|
||||
print(tree.root_node)
|
||||
|
||||
# List all available languages
|
||||
for lang in available_languages():
|
||||
print(lang)
|
||||
|
||||
|
||||
# Extract file intelligence (auto-downloads language if needed)
|
||||
result = process(
|
||||
"def hello(): pass",
|
||||
ProcessConfig(
|
||||
language = "python"
|
||||
)
|
||||
)
|
||||
print(f"Functions: {len(result['structure'])}")
|
||||
|
||||
# Pre-download languages for offline use
|
||||
download(["python", "javascript"])
|
||||
|
||||
# With chunking
|
||||
result = process(
|
||||
source,
|
||||
ProcessConfig(
|
||||
language = "python",
|
||||
chunk_max_size = 1000,
|
||||
comments = True
|
||||
)
|
||||
)
|
||||
print(f"Chunks: {len(result['chunks'])}")
|
||||
|
||||
EOF
|
||||
|
||||
python compile.py
|
||||
cd ..
|
||||
}
|
||||
|
||||
function clone() {
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-python
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-javascript
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-html
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-css
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-json
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-java
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-c
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-cpp
|
||||
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-go
|
||||
# git clone --depth 1 https://github.com/godotengine/tree-sitter-gdscript
|
||||
}
|
||||
|
||||
function setup() {
|
||||
# pip install tree-sitter -t .
|
||||
pip install tree-sitter-language-pack -t .
|
||||
# pip install tree_sitter_languages -t . # Old unmaintained library
|
||||
}
|
||||
|
||||
function main() {
|
||||
cd "$(dirname "$0")"
|
||||
echo "Working Dir: " $(pwd)
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# clone "$@"
|
||||
setup "$@"
|
||||
build "$@"
|
||||
}
|
||||
main "$@";
|
||||
77
plugins/code/event-watchers/tree_sitter/plugin.py
Normal file
77
plugins/code/event-watchers/tree_sitter/plugin.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Python imports
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
BASE_DIR = os.path.dirname( os.path.realpath(__file__) )
|
||||
LIBS_DIR = f"{BASE_DIR}/libs"
|
||||
|
||||
if str(LIBS_DIR) not in sys.path:
|
||||
sys.path.insert(0, LIBS_DIR)
|
||||
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
import tree_sitter_language_pack as tslp
|
||||
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
if isinstance(event, Code_Event_Types.TextChangedEvent):
|
||||
if not tslp.has_language( event.file.ftype ):
|
||||
try:
|
||||
tslp.download( [event.file.ftype] )
|
||||
except Exception:
|
||||
logger.info(
|
||||
f"Tree Sitter Language Pack:\nCouldn't download -> '{event.file.ftype}' language type..."
|
||||
)
|
||||
return
|
||||
|
||||
buffer = event.file.buffer
|
||||
start_itr, \
|
||||
end_itr = buffer.get_bounds()
|
||||
text = buffer.get_text(start_itr, end_itr, True)
|
||||
result = tslp.process(
|
||||
text,
|
||||
tslp.ProcessConfig(
|
||||
language = event.file.ftype
|
||||
)
|
||||
)
|
||||
|
||||
event.file.tree_sitter_meta = result
|
||||
|
||||
def load(self):
|
||||
tslp.configure(
|
||||
cache_dir = f"{BASE_DIR}/cache/tree-sitter-language-pack/v1.0.0/libs"
|
||||
)
|
||||
|
||||
def unload(self):
|
||||
...
|
||||
|
||||
def run(self):
|
||||
# tslp.download(
|
||||
# [
|
||||
# "python",
|
||||
# "java",
|
||||
# "go",
|
||||
# "c",
|
||||
# "cpp",
|
||||
# "javascript",
|
||||
# "html",
|
||||
# "css",
|
||||
# "json"
|
||||
# ]
|
||||
# )
|
||||
# "gdscript"
|
||||
|
||||
...
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Module
|
||||
"""
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Package
|
||||
"""
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"info": "https://github.com/godotengine/godot/blob/4a280218fcfdd69408cceb74577c9e69086be23a/editor/settings/editor_settings.cpp#L1132",
|
||||
"command": "lsp-ws-proxy -- godot",
|
||||
"alt-command": "godot",
|
||||
"alt-command2": "lsp-ws-proxy --listen 4114 -- godot --headless",
|
||||
"alt-command3": "godot --headless --lsp-port 7766",
|
||||
"socket": "ws://127.0.0.1:9999/gdscript",
|
||||
"socket-two": "ws://127.0.0.1:9999/?name=gdscript",
|
||||
"initialization-options": {
|
||||
"processId": ,
|
||||
"clientInfo": {
|
||||
"name": "Godot",
|
||||
"version": "4.4"
|
||||
},
|
||||
"rootUri": "file://{workspace.folder}",
|
||||
"capabilities": {
|
||||
"workspace": {
|
||||
"applyEdit": true,
|
||||
"workspaceEdit": {
|
||||
"documentChanges": true
|
||||
}
|
||||
},
|
||||
"textDocument": {
|
||||
"synchronization": {
|
||||
"dynamicRegistration": true,
|
||||
"willSave": false,
|
||||
"didSave": true,
|
||||
"willSaveWaitUntil": false
|
||||
},
|
||||
"completion": {
|
||||
"dynamicRegistration": true,
|
||||
"completionItem": {
|
||||
"snippetSupport": true
|
||||
}
|
||||
},
|
||||
"hover": {
|
||||
"dynamicRegistration": true
|
||||
},
|
||||
"definition": {
|
||||
"dynamicRegistration": true
|
||||
},
|
||||
"references": {
|
||||
"dynamicRegistration": true
|
||||
},
|
||||
"documentSymbol": {
|
||||
"dynamicRegistration": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"trace": "off"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Godot LSP Client",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"autoload": false,
|
||||
"requests": {}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Python imports
|
||||
from os import path
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
from .response_handler import GDScriptHandler
|
||||
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
...
|
||||
|
||||
def load(self):
|
||||
dirPth = path.dirname( path.realpath(__file__) )
|
||||
with open(f"{dirPth}/config/lsp-server-config.json", "r") as f:
|
||||
config = f.read()
|
||||
event = Event_Factory.create_event("register_lsp_client",
|
||||
lang_id = "gdscript",
|
||||
lang_config = config,
|
||||
handler = GDScriptHandler
|
||||
)
|
||||
self.emit_to("lsp_manager", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event("unregister_lsp_client",
|
||||
lang_id = "gdscript"
|
||||
)
|
||||
self.emit_to("lsp_manager", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
@@ -0,0 +1 @@
|
||||
from .gdscript import GDScriptHandler
|
||||
@@ -0,0 +1,12 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from lsp_manager.response_handlers.default import DefaultHandler
|
||||
|
||||
|
||||
|
||||
class GDScriptHandler(DefaultHandler):
|
||||
"""Uses default handling, can override if Godot needs special logic."""
|
||||
...
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Module
|
||||
"""
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Package
|
||||
"""
|
||||
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"info": "https://download.eclipse.org/jdtls/",
|
||||
"info-init-options": "https://github.com/eclipse-jdtls/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line",
|
||||
"info-import-build": "https://www.javahotchocolate.com/tutorials/build-path.html",
|
||||
"info-external-class-paths": "https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3291",
|
||||
"link": "https://download.eclipse.org/jdtls/milestones/?d",
|
||||
"command": "lsp-ws-proxy --listen 4114 -- jdtls",
|
||||
"alt-command": "lsp-ws-proxy -- jdtls",
|
||||
"alt-command2": "java-language-server",
|
||||
"socket": "ws://127.0.0.1:9999/java",
|
||||
"socket-two": "ws://127.0.0.1:9999/?name=jdtls",
|
||||
"alt-socket": "ws://127.0.0.1:9999/?name=java-language-server",
|
||||
"initialization-options": {
|
||||
"bundles": [
|
||||
"intellicode-core.jar"
|
||||
],
|
||||
"workspaceFolders": [
|
||||
"file://{workspace.folder}"
|
||||
],
|
||||
"extendedClientCapabilities": {
|
||||
"classFileContentsSupport": true,
|
||||
"executeClientCommandSupport": false
|
||||
},
|
||||
"settings": {
|
||||
"java": {
|
||||
"autobuild": {
|
||||
"enabled": true
|
||||
},
|
||||
"jdt": {
|
||||
"ls": {
|
||||
"javac": {
|
||||
"enabled": true
|
||||
},
|
||||
"java": {
|
||||
"home": "{user.home}/Portable_Apps/sdks/javasdk/jdk-22.0.2"
|
||||
},
|
||||
"lombokSupport": {
|
||||
"enabled": true
|
||||
},
|
||||
"protobufSupport":{
|
||||
"enabled": true
|
||||
},
|
||||
"androidSupport": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"configuration": {
|
||||
"updateBuildConfiguration": "automatic",
|
||||
"maven": {
|
||||
"userSettings": "{user.home}/.config/jdtls/settings.xml",
|
||||
"globalSettings": "{user.home}/.config/jdtls/settings.xml"
|
||||
},
|
||||
"runtimes": [
|
||||
{
|
||||
"name": "JavaSE-17",
|
||||
"path": "/usr/lib/jvm/java-17-openjdk",
|
||||
"javadoc": "https://docs.oracle.com/en/java/javase/17/docs/api/",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"name": "JavaSE-22",
|
||||
"path": "{user.home}/Portable_Apps/sdks/javasdk/jdk-22.0.2",
|
||||
"javadoc": "https://docs.oracle.com/en/java/javase/22/docs/api/",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"classPath": [
|
||||
"{user.home}/.config/jdtls/m2/repository/**/*-sources.jar",
|
||||
"lib/**/*-sources.jar"
|
||||
],
|
||||
"docPath": [
|
||||
"{user.home}/.config/jdtls/m2/repository/**/*-javadoc.jar",
|
||||
"lib/**/*-javadoc.jar"
|
||||
],
|
||||
"project": {
|
||||
"encoding": "ignore",
|
||||
"outputPath": "bin",
|
||||
"referencedLibraries": [
|
||||
"{user.home}/.config/jdtls/m2/repository/**/*.jar",
|
||||
"lib/**/*.jar"
|
||||
],
|
||||
"importOnFirstTimeStartup": "automatic",
|
||||
"importHint": true,
|
||||
"resourceFilters": [
|
||||
"node_modules",
|
||||
"\\.git"
|
||||
],
|
||||
"sourcePaths": [
|
||||
"src",
|
||||
"{user.home}/.config/jdtls/m2/repository/**/*.jar"
|
||||
]
|
||||
},
|
||||
"sources": {
|
||||
"organizeImports": {
|
||||
"starThreshold": 99,
|
||||
"staticStarThreshold": 99
|
||||
}
|
||||
},
|
||||
"imports": {
|
||||
"gradle": {
|
||||
"wrapper": {
|
||||
"checksums": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"import": {
|
||||
"maven": {
|
||||
"enabled": true,
|
||||
"offline": {
|
||||
"enabled": false
|
||||
},
|
||||
"disableTestClasspathFlag": false
|
||||
},
|
||||
"gradle": {
|
||||
"enabled": false,
|
||||
"wrapper": {
|
||||
"enabled": true
|
||||
},
|
||||
"version": "",
|
||||
"home": "abs(static/gradle-7.3.3)",
|
||||
"java": {
|
||||
"home": "abs(static/launch_jres/17.0.6-linux-x86_64)"
|
||||
},
|
||||
"offline": {
|
||||
"enabled": false
|
||||
},
|
||||
"arguments": [],
|
||||
"jvmArguments": [],
|
||||
"user": {
|
||||
"home": ""
|
||||
},
|
||||
"annotationProcessing": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"exclusions": [
|
||||
"**/node_modules/**",
|
||||
"**/.metadata/**",
|
||||
"**/archetype-resources/**",
|
||||
"**/META-INF/maven/**"
|
||||
],
|
||||
"generatesMetadataFilesAtProjectRoot": false
|
||||
},
|
||||
"maven": {
|
||||
"downloadSources": true,
|
||||
"updateSnapshots": true
|
||||
},
|
||||
"silentNotification": true,
|
||||
"contentProvider": {
|
||||
"preferred": "fernflower"
|
||||
},
|
||||
"signatureHelp": {
|
||||
"enabled": true,
|
||||
"description": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"completion": {
|
||||
"enabled": true,
|
||||
"engine": "ecj",
|
||||
"matchCase": "firstletter",
|
||||
"maxResults": 25,
|
||||
"guessMethodArguments": true,
|
||||
"lazyResolveTextEdit": {
|
||||
"enabled": true
|
||||
},
|
||||
"postfix": {
|
||||
"enabled": true
|
||||
},
|
||||
"favoriteStaticMembers": [
|
||||
"org.junit.Assert.*",
|
||||
"org.junit.Assume.*",
|
||||
"org.junit.jupiter.api.Assertions.*",
|
||||
"org.junit.jupiter.api.Assumptions.*",
|
||||
"org.junit.jupiter.api.DynamicContainer.*",
|
||||
"org.junit.jupiter.api.DynamicTest.*"
|
||||
],
|
||||
"importOrder": [
|
||||
"#",
|
||||
"java",
|
||||
"javax",
|
||||
"org",
|
||||
"com"
|
||||
]
|
||||
},
|
||||
"references": {
|
||||
"includeAccessors": true,
|
||||
"includeDecompiledSources": true
|
||||
},
|
||||
"codeGeneration": {
|
||||
"toString": {
|
||||
"template": "${object.className}{${member.name()}=${member.value}, ${otherMembers}}"
|
||||
},
|
||||
"insertionLocation": "afterCursor",
|
||||
"useBlocks": true
|
||||
},
|
||||
"implementationsCodeLens": {
|
||||
"enabled": true
|
||||
},
|
||||
"referencesCodeLens": {
|
||||
"enabled": true
|
||||
},
|
||||
"progressReports": {
|
||||
"enabled": false
|
||||
},
|
||||
"saveActions": {
|
||||
"organizeImports": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Java LSP Client",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"autoload": false,
|
||||
"requests": {}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Python imports
|
||||
from os import path
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from plugins.plugin_types import PluginCode
|
||||
|
||||
from .response_handler import JavaHandler
|
||||
|
||||
|
||||
class Plugin(PluginCode):
|
||||
def __init__(self):
|
||||
super(Plugin, self).__init__()
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
...
|
||||
|
||||
def load(self):
|
||||
dirPth = path.dirname( path.realpath(__file__) )
|
||||
with open(f"{dirPth}/config/lsp-server-config.json", "r") as f:
|
||||
config = f.read()
|
||||
event = Event_Factory.create_event("register_lsp_client",
|
||||
lang_id = "java",
|
||||
lang_config = config,
|
||||
handler = JavaHandler
|
||||
)
|
||||
self.emit_to("lsp_manager", event)
|
||||
|
||||
def unload(self):
|
||||
event = Event_Factory.create_event("unregister_lsp_client",
|
||||
lang_id = "java"
|
||||
)
|
||||
self.emit_to("lsp_manager", event)
|
||||
|
||||
def run(self):
|
||||
...
|
||||
@@ -0,0 +1 @@
|
||||
from .java import JavaHandler
|
||||
@@ -0,0 +1,51 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('GtkSource', '4')
|
||||
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from lsp_manager.response_handlers.default import DefaultHandler
|
||||
|
||||
|
||||
|
||||
class JavaHandler(DefaultHandler):
|
||||
"""Java-specific: overrides definition, handles classFileContents."""
|
||||
|
||||
def handle(self, method: str, response, controller):
|
||||
match method:
|
||||
case "textDocument/definition":
|
||||
self._handle_definition(response, controller)
|
||||
case "java/classFileContents":
|
||||
self._handle_class_file_contents(response)
|
||||
case _:
|
||||
super().handle(method, response, controller)
|
||||
|
||||
def _handle_definition(self, response, controller):
|
||||
if not response: return
|
||||
|
||||
uri = response[0]["uri"]
|
||||
if "jdt://" in uri:
|
||||
controller._lsp_java_class_file_contents(uri)
|
||||
return
|
||||
|
||||
self._prompt_goto_request(uri, response[0]["range"])
|
||||
|
||||
def _handle_class_file_contents(self, text: str):
|
||||
event = Event_Factory.create_event("get_active_view")
|
||||
self.emit_to("source_views", event)
|
||||
|
||||
view = event.response
|
||||
file = view.command.exec("new_file")
|
||||
buffer = view.get_buffer()
|
||||
itr = buffer.get_iter_at_mark(buffer.get_insert())
|
||||
lm = GtkSource.LanguageManager.get_default()
|
||||
language = lm.get_language("java")
|
||||
file.ftype = "java"
|
||||
|
||||
buffer.set_language(language)
|
||||
buffer.insert(itr, text, -1)
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Module
|
||||
"""
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Package
|
||||
"""
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
LSP Clients Module
|
||||
"""
|
||||
@@ -1,36 +1,37 @@
|
||||
# Python imports
|
||||
import threading
|
||||
from os import path
|
||||
import json
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from libs.dto.code.lsp.lsp_messages import get_message_str
|
||||
from libs.dto.code.lsp.lsp_message_structs import LSPResponseTypes, ClientRequest, ClientNotification
|
||||
from .lsp_controller_websocket import LSPControllerWebsocket
|
||||
from ..dto.code.lsp.lsp_messages import get_message_str
|
||||
from ..dto.code.lsp.lsp_message_structs import \
|
||||
LSPResponseTypes, ClientRequest, ClientNotification
|
||||
from .lsp_client_websocket import LSPClientWebsocket
|
||||
|
||||
|
||||
|
||||
class LSPController(LSPControllerWebsocket):
|
||||
class LSPClient(LSPClientWebsocket):
|
||||
def __init__(self):
|
||||
super(LSPController, self).__init__()
|
||||
super(LSPClient, self).__init__()
|
||||
|
||||
# https://github.com/microsoft/multilspy/tree/main/src/multilspy/language_servers
|
||||
# initialize-params-slim.json was created off of jedi_language_server one
|
||||
# self._init_params = settings_manager.get_lsp_init_data()
|
||||
|
||||
self._language: str = ""
|
||||
self._init_params: dict = {}
|
||||
self._event_history: dict[str] = {}
|
||||
self._language: str = ""
|
||||
self._init_params: dict = {}
|
||||
self._event_history: dict[int, str] = {}
|
||||
|
||||
try:
|
||||
from os import path
|
||||
import json
|
||||
|
||||
_USER_HOME = path.expanduser('~')
|
||||
_SCRIPT_PTH = path.dirname( path.realpath(__file__) )
|
||||
_LSP_INIT_CONFIG = f"{_SCRIPT_PTH}/../configs/initialize-params-slim.json"
|
||||
|
||||
with open(_LSP_INIT_CONFIG) as file:
|
||||
data = file.read().replace("{user.home}", _USER_HOME)
|
||||
self._init_params = json.loads(data)
|
||||
@@ -42,7 +43,7 @@ class LSPController(LSPControllerWebsocket):
|
||||
self.read_lock = threading.Lock()
|
||||
self.write_lock = threading.Lock()
|
||||
|
||||
def set_language(self, language):
|
||||
def set_language(self, language: str):
|
||||
self._language = language
|
||||
|
||||
def set_socket(self, socket: str):
|
||||
@@ -51,15 +52,15 @@ class LSPController(LSPControllerWebsocket):
|
||||
def unset_socket(self):
|
||||
self._socket = None
|
||||
|
||||
def send_notification(self, method: str, params: {} = {}):
|
||||
def send_notification(self, method: str, params: dict = {}):
|
||||
self._send_message( ClientNotification(method, params) )
|
||||
|
||||
def send_request(self, method: str, params: {} = {}):
|
||||
def send_request(self, method: str, params: dict = {}):
|
||||
self._message_id += 1
|
||||
self._event_history[self._message_id] = method
|
||||
self._send_message( ClientRequest(self._message_id, method, params) )
|
||||
|
||||
def get_event_by_id(self, message_id: int):
|
||||
def get_event_by_id(self, message_id: int) -> str:
|
||||
if not message_id in self._event_history: return
|
||||
return self._event_history[message_id]
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .lsp_controller_events import LSPControllerEvents
|
||||
from libs.dto.code.lsp.lsp_message_structs import ClientRequest, ClientNotification
|
||||
from ..dto.code.lsp.lsp_message_structs import ClientRequest, ClientNotification
|
||||
|
||||
from .lsp_client_events import LSPClientEvents
|
||||
|
||||
|
||||
|
||||
class LSPControllerBase(LSPControllerEvents):
|
||||
class LSPClientBase(LSPClientEvents):
|
||||
def _send_message(self, data: ClientRequest or ClientNotification):
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -2,22 +2,21 @@
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from libs.dto.code.lsp.lsp_messages import get_message_obj
|
||||
from libs.dto.code.lsp.lsp_messages import didopen_notification
|
||||
from libs.dto.code.lsp.lsp_messages import didsave_notification
|
||||
from libs.dto.code.lsp.lsp_messages import didclose_notification
|
||||
from libs.dto.code.lsp.lsp_messages import didchange_notification
|
||||
from libs.dto.code.lsp.lsp_messages import completion_request
|
||||
from libs.dto.code.lsp.lsp_messages import definition_request
|
||||
from libs.dto.code.lsp.lsp_messages import references_request
|
||||
from libs.dto.code.lsp.lsp_messages import symbols_request
|
||||
from ..dto.code.lsp.lsp_messages import get_message_obj
|
||||
from ..dto.code.lsp.lsp_messages import didopen_notification
|
||||
from ..dto.code.lsp.lsp_messages import didsave_notification
|
||||
from ..dto.code.lsp.lsp_messages import didclose_notification
|
||||
from ..dto.code.lsp.lsp_messages import didchange_notification
|
||||
from ..dto.code.lsp.lsp_messages import completion_request
|
||||
from ..dto.code.lsp.lsp_messages import definition_request
|
||||
from ..dto.code.lsp.lsp_messages import references_request
|
||||
from ..dto.code.lsp.lsp_messages import symbols_request
|
||||
|
||||
|
||||
|
||||
class LSPControllerEvents:
|
||||
class LSPClientEvents:
|
||||
def send_initialize_message(self, init_ops: dict, workspace_file: str, workspace_uri: str):
|
||||
folder_name = os.path.basename(workspace_file)
|
||||
|
||||
@@ -45,7 +44,7 @@ class LSPControllerEvents:
|
||||
params["textDocument"]["languageId"] = data["language_id"]
|
||||
params["textDocument"]["text"] = data["text"]
|
||||
|
||||
GLib.idle_add( self.send_notification, method, params )
|
||||
self.send_notification( method, params )
|
||||
|
||||
def _lsp_did_save(self, data: dict):
|
||||
method = "textDocument/didSave"
|
||||
@@ -54,7 +53,7 @@ class LSPControllerEvents:
|
||||
params["textDocument"]["uri"] = data["uri"]
|
||||
params["text"] = data["text"]
|
||||
|
||||
GLib.idle_add( self.send_notification, method, params )
|
||||
self.send_notification( method, params )
|
||||
|
||||
def _lsp_did_close(self, data: dict):
|
||||
method = "textDocument/didClose"
|
||||
@@ -62,7 +61,7 @@ class LSPControllerEvents:
|
||||
|
||||
params["textDocument"]["uri"] = data["uri"]
|
||||
|
||||
GLib.idle_add( self.send_notification, method, params )
|
||||
self.send_notification( method, params )
|
||||
|
||||
def _lsp_did_change(self, data: dict):
|
||||
method = "textDocument/didChange"
|
||||
@@ -75,7 +74,7 @@ class LSPControllerEvents:
|
||||
contentChanges = params["contentChanges"][0]
|
||||
contentChanges["text"] = data["text"]
|
||||
|
||||
GLib.idle_add( self.send_notification, method, params )
|
||||
self.send_notification( method, params )
|
||||
|
||||
# def _lsp_did_change(self, data: dict):
|
||||
# method = "textDocument/didChange"
|
||||
@@ -94,7 +93,7 @@ class LSPControllerEvents:
|
||||
# end["line"] = data["line"]
|
||||
# end["character"] = data["column"]
|
||||
|
||||
# GLib.idle_add( self.send_notification, method, params )
|
||||
# self.send_notification( method, params )
|
||||
|
||||
def _lsp_definition(self, data: dict):
|
||||
method = "textDocument/definition"
|
||||
@@ -106,7 +105,7 @@ class LSPControllerEvents:
|
||||
params["position"]["line"] = data["line"]
|
||||
params["position"]["character"] = data["column"]
|
||||
|
||||
GLib.idle_add( self.send_request, method, params )
|
||||
self.send_request( method, params )
|
||||
|
||||
def _lsp_completion(self, data: dict):
|
||||
method = "textDocument/completion"
|
||||
@@ -118,4 +117,12 @@ class LSPControllerEvents:
|
||||
params["position"]["line"] = data["line"]
|
||||
params["position"]["character"] = data["column"]
|
||||
|
||||
GLib.idle_add( self.send_request, method, params )
|
||||
self.send_request( method, params )
|
||||
|
||||
def _lsp_java_class_file_contents(self, uri: str):
|
||||
method = "java/classFileContents"
|
||||
params = {
|
||||
"uri": uri
|
||||
}
|
||||
|
||||
self.send_request( method, params )
|
||||
@@ -1,23 +1,22 @@
|
||||
# Python imports
|
||||
import traceback
|
||||
import subprocess
|
||||
|
||||
# Lib imports
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
# from libs import websockets
|
||||
from libs.dto.code.lsp.lsp_messages import LEN_HEADER, TYPE_HEADER, get_message_str, get_message_obj
|
||||
from libs.dto.code.lsp.lsp_message_structs import \
|
||||
LSPResponseTypes, ClientRequest, ClientNotification, LSPResponseRequest, LSPResponseNotification, LSPIDResponseNotification
|
||||
from ..dto.code.lsp.lsp_messages import get_message_str, get_message_obj
|
||||
from ..dto.code.lsp.lsp_message_structs import \
|
||||
LSPResponseTypes, ClientRequest, ClientNotification, \
|
||||
LSPResponseRequest, LSPResponseNotification, LSPIDResponseNotification
|
||||
|
||||
from .lsp_controller_base import LSPControllerBase
|
||||
from .lsp_client_base import LSPClientBase
|
||||
from .websocket_client import WebsocketClient
|
||||
|
||||
|
||||
|
||||
class LSPControllerWebsocket(LSPControllerBase):
|
||||
def _send_message(self, data: ClientRequest or ClientNotification):
|
||||
class LSPClientWebsocket(LSPClientBase):
|
||||
def _send_message(self, data: ClientRequest | ClientNotification):
|
||||
if not data: return
|
||||
|
||||
message_str = get_message_str(data)
|
||||
@@ -39,7 +38,7 @@ class LSPControllerWebsocket(LSPControllerBase):
|
||||
if not hasattr(self, "ws_client"): return
|
||||
self.ws_client.close_client()
|
||||
|
||||
def _monitor_lsp_response(self, data: None or {}):
|
||||
def _monitor_lsp_response(self, data: dict | None):
|
||||
if not data: return
|
||||
|
||||
message = get_message_obj(data)
|
||||
@@ -0,0 +1,8 @@
|
||||
"""
|
||||
Libs Code DTO(s) Events Package
|
||||
"""
|
||||
|
||||
from .lsp_event import LspEvent
|
||||
|
||||
from .register_lsp_client_event import RegisterLspClientEvent
|
||||
from .unregister_lsp_client_event import UnregisterLspClientEvent
|
||||
@@ -0,0 +1,13 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.dto.code.events import CodeEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class LspEvent(CodeEvent):
|
||||
...
|
||||
@@ -0,0 +1,17 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from ....response_handlers.base_handler import BaseHandler
|
||||
|
||||
from .lsp_event import LspEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class RegisterLspClientEvent(LspEvent):
|
||||
lang_id: str = ""
|
||||
lang_config: str = "{}"
|
||||
handler: BaseHandler = None
|
||||
@@ -0,0 +1,13 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .lsp_event import LspEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnregisterLspClientEvent(LspEvent):
|
||||
lang_id: str = ""
|
||||
128
plugins/code/language_server_clients/lsp_manager/lsp_manager.py
Normal file
128
plugins/code/language_server_clients/lsp_manager/lsp_manager.py
Normal file
@@ -0,0 +1,128 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from libs.controllers.controller_base import ControllerBase
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from .dto.code.events import \
|
||||
RegisterLspClientEvent, UnregisterLspClientEvent
|
||||
from .dto.code.lsp.lsp_message_structs import \
|
||||
LSPResponseTypes, LSPResponseRequest, LSPResponseNotification
|
||||
|
||||
from .provider import Provider
|
||||
from .provider_response_cache import ProviderResponseCache
|
||||
from .lsp_manager_ui import LSPManagerUI
|
||||
from .lsp_manager_client import LSPManagerClient
|
||||
from .response_handlers.response_registry import ResponseRegistry
|
||||
|
||||
|
||||
|
||||
class LSPManager(ControllerBase):
|
||||
def __init__(self):
|
||||
super(LSPManager, self).__init__()
|
||||
|
||||
self._init()
|
||||
self._load_widgets()
|
||||
self._do_bind_mapping()
|
||||
|
||||
|
||||
def _init(self):
|
||||
self.provider: Provider = Provider()
|
||||
self.response_cache: ProviderResponseCache = ProviderResponseCache()
|
||||
self.lsp_manager_client: LSPManagerClient = LSPManagerClient()
|
||||
self.response_registry: ResponseRegistry = ResponseRegistry()
|
||||
|
||||
def _load_widgets(self):
|
||||
self.lsp_manager_ui: LSPManagerUI = LSPManagerUI()
|
||||
self.lsp_manager_ui.connect('create-client', self._on_create_client)
|
||||
self.lsp_manager_ui.connect('close-client', self._on_close_client)
|
||||
|
||||
def _do_bind_mapping(self):
|
||||
self.response_cache.set_lsp_manager_client(self.lsp_manager_client)
|
||||
self.provider.response_cache = self.response_cache
|
||||
self.response_registry.set_event_hub(
|
||||
self.emit, self.emit_to, self.provider
|
||||
)
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
if isinstance(event, Code_Event_Types.RegisterLspClientEvent):
|
||||
self.response_registry.register_handler(event.lang_id, event.handler)
|
||||
self.lsp_manager_ui.add_client_listing(event.lang_id, event.lang_config)
|
||||
elif isinstance(event, Code_Event_Types.UnregisterLspClientEvent):
|
||||
self.response_registry.unregister_handler(event.lang_id)
|
||||
self.lsp_manager_ui.remove_client_listing(event.lang_id)
|
||||
|
||||
def _on_create_client(self, ui, lang_id: str, workspace_uri: str) -> bool:
|
||||
init_opts = ui.get_init_opts(lang_id)
|
||||
result = self.create_client(lang_id, workspace_uri, init_opts)
|
||||
if result:
|
||||
ui.toggle_client_buttons(show_close=True)
|
||||
return result
|
||||
|
||||
def _on_close_client(self, ui, lang_id: str) -> bool:
|
||||
result = self.close_client(lang_id)
|
||||
if result:
|
||||
ui.toggle_client_buttons(show_close=False)
|
||||
return result
|
||||
|
||||
def handle_destroy(self):
|
||||
self.lsp_manager_ui.disconnect_by_func(self._on_create_client)
|
||||
self.lsp_manager_ui.disconnect_by_func(self._on_close_client)
|
||||
|
||||
def create_client(
|
||||
self,
|
||||
lang_id: str = "python",
|
||||
workspace_uri: str = "",
|
||||
init_opts: dict = {}
|
||||
) -> bool:
|
||||
client = self.lsp_manager_client.create_client(
|
||||
lang_id, workspace_uri, init_opts
|
||||
)
|
||||
handler = self.response_registry.get_handler(lang_id)
|
||||
self.lsp_manager_client.active_language_id = lang_id
|
||||
|
||||
if not client or not handler:
|
||||
logger.error(f"LSP Manager: Either 'client' or 'handler' didn't get created...'")
|
||||
self.close_client(lang_id)
|
||||
return False
|
||||
|
||||
handler.set_context(self.response_registry)
|
||||
handler.set_response_cache(self.response_cache)
|
||||
|
||||
client.handle_lsp_response = self.server_response
|
||||
client.send_initialize_message(init_opts, "", f"file://{workspace_uri}")
|
||||
|
||||
return True
|
||||
|
||||
def close_client(self, lang_id: str) -> bool:
|
||||
self.lsp_manager_client.close_client(lang_id)
|
||||
self.response_registry.close_handler(lang_id)
|
||||
|
||||
return True
|
||||
|
||||
def server_response(self, lsp_response: LSPResponseTypes):
|
||||
logger.debug(f"LSP Response: { lsp_response }")
|
||||
|
||||
if isinstance(lsp_response, LSPResponseRequest):
|
||||
if not self.lsp_manager_client.active_language_id in self.lsp_manager_client.clients:
|
||||
logger.debug(f"No LSP client for '{self.lsp_manager_client.active_language_id}', skipping 'server_response'")
|
||||
return
|
||||
|
||||
controller = self.lsp_manager_client.get_active_client()
|
||||
event = controller.get_event_by_id(lsp_response.id)
|
||||
handler = self.response_registry.get_handler(
|
||||
self.lsp_manager_client.active_language_id, event
|
||||
)
|
||||
|
||||
if not handler: return
|
||||
handler.handle(event, lsp_response.result, controller)
|
||||
elif isinstance(lsp_response, LSPResponseNotification):
|
||||
handler = self.response_registry.get_handler("default", lsp_response.method)
|
||||
|
||||
if not handler: return
|
||||
|
||||
handler.set_context(self.response_registry)
|
||||
handler.set_response_cache(self.response_cache)
|
||||
handler.handle(lsp_response.method, lsp_response.params, None)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user