summaryrefslogtreecommitdiffstats
path: root/src/debputy/lsp/lsp_debian_debputy_manifest.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/debputy/lsp/lsp_debian_debputy_manifest.py')
-rw-r--r--src/debputy/lsp/lsp_debian_debputy_manifest.py54
1 files changed, 41 insertions, 13 deletions
diff --git a/src/debputy/lsp/lsp_debian_debputy_manifest.py b/src/debputy/lsp/lsp_debian_debputy_manifest.py
index 1dc5fb3..d24d441 100644
--- a/src/debputy/lsp/lsp_debian_debputy_manifest.py
+++ b/src/debputy/lsp/lsp_debian_debputy_manifest.py
@@ -54,6 +54,7 @@ from debputy.lsp.text_util import (
from debputy.manifest_parser.declarative_parser import (
AttributeDescription,
ParserGenerator,
+ DeclarativeNonMappingInputParser,
)
from debputy.manifest_parser.declarative_parser import DeclarativeMappingInputParser
from debputy.manifest_parser.parser_doc import (
@@ -307,7 +308,6 @@ def _trace_cursor(
break
matched = v
matched_key = k
- matched_was_key = False
elif isinstance(content, CommentedSeq):
list_lc: LineCol = content.lc
for idx, value in enumerate(content):
@@ -481,13 +481,25 @@ def _insert_snippet(lines: List[str], server_position: Position) -> bool:
if pos_rhs and not pos_rhs.isspace():
_info(f"No insertion: {_ecsape(line[server_position.character:])}")
return False
- lhs = line[: server_position.character].strip()
- if not lhs:
- _info(f"Insertion of key: {_ecsape(line[server_position.character:])}")
+ lhs_ws = line[: server_position.character]
+ lhs = lhs_ws.strip()
+ if lhs.endswith(":"):
+ _info("Insertion of value (key seen)")
+ new_line = line[: server_position.character] + _COMPLETION_HINT_VALUE
+ elif lhs.startswith("-"):
+ _info("Insertion of key or value (list item)")
+ # Respect the provided indentation
+ snippet = _COMPLETION_HINT_KEY if ":" not in lhs else _COMPLETION_HINT_VALUE
+ new_line = line[: server_position.character] + snippet
+ elif not lhs or (lhs_ws and not lhs_ws[0].isspace()):
+ _info(f"Insertion of key or value: {_ecsape(line[server_position.character:])}")
+ # Respect the provided indentation
+ snippet = _COMPLETION_HINT_KEY if ":" not in lhs else _COMPLETION_HINT_VALUE
+ new_line = line[: server_position.character] + snippet
+ elif lhs.isalpha() and ":" not in lhs:
+ _info(f"Expanding value to a key: {_ecsape(line[server_position.character:])}")
# Respect the provided indentation
new_line = line[: server_position.character] + _COMPLETION_HINT_KEY
- elif lhs.endswith(":"):
- new_line = line[: server_position.character] + _COMPLETION_HINT_VALUE
else:
c = line[server_position.character]
_info(f"Not touching line: {_ecsape(line)} -- {_ecsape(c)}")
@@ -513,6 +525,7 @@ def debputy_manifest_completer(
added_key = _insert_snippet(lines, server_position)
attempts = 1 if added_key else 2
content = None
+
while attempts > 0:
attempts -= 1
try:
@@ -531,6 +544,7 @@ def debputy_manifest_completer(
if e.problem_mark.line < len(lines)
else "N/A (OOB)"
)
+
_info(f"Parse error on line: {e.problem_mark.line}: {l_data}")
return None
@@ -540,26 +554,22 @@ def debputy_manifest_completer(
lines[server_position.line] = new_line
except YAMLError:
break
-
if content is None:
context = lines[server_position.line].replace("\n", "\\n")
_info(f"Completion failed: parse error: Line in question: {context}")
return None
-
m = _trace_cursor(content, attribute_root_path, server_position)
+
if m is None:
_info("No match")
return None
matched_key, attr_path, matched, parent = m
_info(f"Matched path: {matched} (path: {attr_path.path}) [{matched_key=}]")
-
feature_set = lsp_get_plugin_features()
root_parser = feature_set.manifest_parser_generator.dispatchable_object_parsers[
OPARSER_MANIFEST_ROOT
]
segments = list(attr_path.path_segments())
- if added_key:
- segments.pop()
km = resolve_keyword(
root_parser,
DEBPUTY_PLUGIN_METADATA,
@@ -586,18 +596,29 @@ def debputy_manifest_completer(
)
]
else:
- _info("TODO: Match value")
+ items = [
+ CompletionItem(k)
+ for k in parser.registered_keywords()
+ if k not in parent
+ and isinstance(
+ parser.parser_for(k).parser,
+ DeclarativeValuelessKeywordInputParser,
+ )
+ ]
elif isinstance(parser, InPackageContextParser):
# doc = ls.workspace.get_text_document(params.text_document.uri)
_info(f"TODO: Match package - {parent} -- {matched} -- {matched_key=}")
elif isinstance(parser, DeclarativeMappingInputParser):
- print(f"MMM: {matched} - {parent}")
if matched_key:
_info("Match attributes")
locked = set(parent)
for mx in parser.mutually_exclusive_attributes:
if not mx.isdisjoint(parent.keys()):
locked.update(mx)
+ for attr_name, attr in parser.manifest_attributes.items():
+ if not attr.conflicting_attributes.isdisjoint(parent.keys()):
+ locked.add(attr_name)
+ break
items = [
CompletionItem(f"{k}:")
for k in parser.manifest_attributes
@@ -618,6 +639,13 @@ def debputy_manifest_completer(
_info(
f"Expand value / key: {key} -- !! {list(parser.manifest_attributes)}"
)
+ elif isinstance(parser, DeclarativeNonMappingInputParser):
+ attr = parser.alt_form_parser
+ items = _completion_from_attr(
+ attr,
+ feature_set.manifest_parser_generator,
+ matched,
+ )
return items