add hover function

This commit is contained in:
2025-07-21 21:31:04 +02:00
parent ff3059421f
commit cf6a39b51d
3 changed files with 79 additions and 71 deletions
+12 -10
View File
@@ -17,10 +17,15 @@ KIND_MAP = {
class StandardCompletionItems:
def __init__(self):
self.__json_data: dict = self.__load_json()
self.__tcl_keyword_list = self.__load_tcl_keyword()
self.__nx_procs = self.__load_nx_procs()
self.__nx_variables = self.__load_nx_variables()
@property
def json_data(self):
return self.__json_data
@property
def tcl_keyword_list(self):
return self.__tcl_keyword_list
@@ -33,11 +38,15 @@ class StandardCompletionItems:
def nx_variables(self):
return self.__nx_variables
def __load_tcl_keyword(self) -> list[lsp.CompletionItem]:
def __load_json(self) -> dict:
with open(
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
) as f:
data = json.load(f)
return data
def __load_tcl_keyword(self) -> list[lsp.CompletionItem]:
data = self.json_data
items = []
for i in data.get("tcl", []):
@@ -50,10 +59,7 @@ class StandardCompletionItems:
return items
def __load_nx_variables(self):
with open(
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
) as f:
data = json.load(f)
data = self.json_data
items = []
for var in data.get("mom_variables", []):
label = var.get("label", "")
@@ -85,11 +91,7 @@ class StandardCompletionItems:
return items
def __load_nx_procs(self) -> list[lsp.CompletionItem]:
with open(
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
) as f:
data = json.load(f)
data = self.json_data
items = []
for proc in data.get("MOM_procs", []):
label = proc.get("label", "")
+67
View File
@@ -13,6 +13,7 @@ import sys
import sysconfig
import traceback
from typing import Any, Optional, Sequence
import re
# **********************************************************
@@ -106,6 +107,72 @@ def on_completion(params: lsp.CompletionParams) -> list[lsp.CompletionItem]:
return lsp.CompletionList(is_incomplete=False, items=items)
@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_HOVER)
def hover(params: lsp.HoverParams) -> lsp.Hover:
pos = params.position
document_uri = params.text_document.uri
document = LSP_SERVER.workspace.get_text_document(document_uri)
col = params.position.character
try:
line = document.lines[pos.line]
except IndexError:
return None
for m in re.finditer(r"\b\w+\b", line):
if m.start() <= col <= m.end():
token = m.group(0)
break
else:
return None
command = token
data = standard_items.json_data
all_items = data.get("MOM_procs", []) + data.get("mom_variables", [])
match = next((item for item in all_items if item["label"] == command), None)
if not match:
return None
if not match.get("kind") == "function":
return None
label = match.get("label", "")
parameters = match.get("parameters", [])
param_lines = (
"\n".join(f"- `{p['name']}`: {p['desc']}" for p in parameters) or "_None_"
)
example_data = match.get("example", [])
example_md = "\n".join(f"{line}" for line in example_data)
returns_data = match.get("returns", ["None"])
returns_md = "\n".join(f"- {line}" for line in returns_data)
doc_md = f"""\
### 📘 {label}
**Purpose**
{match.get("description", "No description available.")}
**Format**
`{match.get("format", label)}`
**Parameters**
{param_lines}
**Return value**
{returns_md}
**Example**
```tcl
{example_md}"""
return lsp.Hover(lsp.MarkupContent(kind=lsp.MarkupKind.Markdown, value=doc_md))
# **********************************************************
# Linting features end here
# **********************************************************
-61
View File
@@ -1,61 +0,0 @@
// Lark grammar for Tcl scripts with proc definitions and optional args
%import common.CNAME -> IDENTIFIER
%import common.INT -> INT
%import common.FLOAT -> FLOAT
%import common.ESCAPED_STRING -> STRING_LITERAL
%import common.WS_INLINE -> WS_INLINE
%import common.NEWLINE -> NEWLINE
// Ignore only spaces, tabs; treat newlines as separators
%ignore WS_INLINE
// Tcl comments
%ignore COMMENT
start: script
script: statement*
statement: command (";" | NEWLINE)?
command: set_command
| proc_command
| r_break
| r_continue
proc_command: "proc" IDENTIFIER "{" argument_list "}" body_block
argument_list: [argument (argument)*]
argument: IDENTIFIER -> required_arg
| "{" IDENTIFIER (value)? "}" -> optional_arg
value: STRING_LITERAL
| FLOAT
| INT
| IDENTIFIER
| list
list: LBRACE [value (WS_INLINE value)*] RBRACE
body_block: LBRACE body_content RBRACE -> body
body_content: ( /[^{}]+/ | body_block )* // allow nested braces
set_command: "set" IDENTIFIER index? value
// Index: parentheses with comma-separated items
index: "(" index_item ("," index_item)* ")"
index_item: INT -> index_int
| STRING_VAR -> index_string
| "$" IDENTIFIER index? -> nested_index
r_break: "break"
r_continue: "continue"
LBRACE: "{"
RBRACE: "}"
STRING_VAR: /(?:[^"\\]|\\.)+/
COMMENT: /#[^\r\n]*/