diff options
Diffstat (limited to 'src/debputy/lsp/lsp_debian_debputy_manifest.py')
-rw-r--r-- | src/debputy/lsp/lsp_debian_debputy_manifest.py | 54 |
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 |