add hover function
This commit is contained in:
@@ -17,10 +17,15 @@ KIND_MAP = {
|
|||||||
|
|
||||||
class StandardCompletionItems:
|
class StandardCompletionItems:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.__json_data: dict = self.__load_json()
|
||||||
self.__tcl_keyword_list = self.__load_tcl_keyword()
|
self.__tcl_keyword_list = self.__load_tcl_keyword()
|
||||||
self.__nx_procs = self.__load_nx_procs()
|
self.__nx_procs = self.__load_nx_procs()
|
||||||
self.__nx_variables = self.__load_nx_variables()
|
self.__nx_variables = self.__load_nx_variables()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json_data(self):
|
||||||
|
return self.__json_data
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tcl_keyword_list(self):
|
def tcl_keyword_list(self):
|
||||||
return self.__tcl_keyword_list
|
return self.__tcl_keyword_list
|
||||||
@@ -33,11 +38,15 @@ class StandardCompletionItems:
|
|||||||
def nx_variables(self):
|
def nx_variables(self):
|
||||||
return self.__nx_variables
|
return self.__nx_variables
|
||||||
|
|
||||||
def __load_tcl_keyword(self) -> list[lsp.CompletionItem]:
|
def __load_json(self) -> dict:
|
||||||
with open(
|
with open(
|
||||||
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
|
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
|
||||||
) as f:
|
) as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __load_tcl_keyword(self) -> list[lsp.CompletionItem]:
|
||||||
|
data = self.json_data
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
for i in data.get("tcl", []):
|
for i in data.get("tcl", []):
|
||||||
@@ -50,10 +59,7 @@ class StandardCompletionItems:
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
def __load_nx_variables(self):
|
def __load_nx_variables(self):
|
||||||
with open(
|
data = self.json_data
|
||||||
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
|
|
||||||
) as f:
|
|
||||||
data = json.load(f)
|
|
||||||
items = []
|
items = []
|
||||||
for var in data.get("mom_variables", []):
|
for var in data.get("mom_variables", []):
|
||||||
label = var.get("label", "")
|
label = var.get("label", "")
|
||||||
@@ -85,11 +91,7 @@ class StandardCompletionItems:
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
def __load_nx_procs(self) -> list[lsp.CompletionItem]:
|
def __load_nx_procs(self) -> list[lsp.CompletionItem]:
|
||||||
with open(
|
data = self.json_data
|
||||||
pathlib.Path(__file__).parent.joinpath("completion_list.json"), "r"
|
|
||||||
) as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
for proc in data.get("MOM_procs", []):
|
for proc in data.get("MOM_procs", []):
|
||||||
label = proc.get("label", "")
|
label = proc.get("label", "")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import sys
|
|||||||
import sysconfig
|
import sysconfig
|
||||||
import traceback
|
import traceback
|
||||||
from typing import Any, Optional, Sequence
|
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)
|
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
|
# Linting features end here
|
||||||
# **********************************************************
|
# **********************************************************
|
||||||
|
|||||||
@@ -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]*/
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user