From 18603126c7e5f571c12368e63331b67a03f1e477 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 16 Jan 2023 19:29:09 -0500 Subject: [PATCH 1/3] Improve Jedi file completions for directories --- pylsp/plugins/jedi_completion.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pylsp/plugins/jedi_completion.py b/pylsp/plugins/jedi_completion.py index 4c4bc94e..bf32ed70 100644 --- a/pylsp/plugins/jedi_completion.py +++ b/pylsp/plugins/jedi_completion.py @@ -2,6 +2,7 @@ # Copyright 2021- Python Language Server Contributors. import logging +import os import os.path as osp import parso @@ -219,11 +220,21 @@ def _format_completion(d, markup_kind: str, include_params=True, resolve=False, if resolve: completion = _resolve_completion(completion, d, markup_kind) + # Adjustments for file completions if d.type == 'path': path = osp.normpath(d.name) path = path.replace('\\', '\\\\') path = path.replace('/', '\\/') - completion['insertText'] = path + + # If the completion ends with os.sep, it means it's a directory. So we add an escaped os.sep + # at the end to ease additional file completions. + if d.name.endswith(os.sep): + if os.name == 'nt': + completion['insertText'] = path + '\\\\' + else: + completion['insertText'] = path + '\\/' + else: + completion['insertText'] = path if include_params and not is_exception_class(d.name): snippet = _snippet(d, resolve_label_or_snippet) From 97a0f86ec36f88efd10ba942df40e79137f01e33 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 16 Jan 2023 19:30:35 -0500 Subject: [PATCH 2/3] Add a test to check file completions --- test/plugins/test_completion.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/plugins/test_completion.py b/test/plugins/test_completion.py index 16e278e0..fc22c34f 100644 --- a/test/plugins/test_completion.py +++ b/test/plugins/test_completion.py @@ -528,3 +528,26 @@ def foo(): com_position = {'line': 1, 'character': 10} completions = pylsp_jedi_completions(doc._config, doc, com_position) assert completions[0]['label'] == 'foo()' + + +def test_file_completions(workspace, tmpdir): + # Create directory and a file to get completions for them. + # Note: `tmpdir`` is the root dir of the `workspace` fixture. That's why we use + # it here. + tmpdir.mkdir('bar') + file = tmpdir.join('foo.txt') + file.write('baz') + + # Content of doc to test completion + doc_content = '"' + doc = Document(DOC_URI, workspace, doc_content) + + # Request for completions + com_position = {'line': 0, 'character': 1} + completions = pylsp_jedi_completions(doc._config, doc, com_position) + + # Check completions + assert len(completions) == 2 + assert [c['kind'] == lsp.CompletionItemKind.File for c in completions] + assert completions[0]['insertText'] == ('bar' + '\\\\') if os.name == 'nt' else ('bar' + '\\/') + assert completions[1]['insertText'] == 'foo.txt"' From dbf75cf19084ab6dbe5e86aa2770b5ca23555c52 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 17 Jan 2023 11:58:29 -0500 Subject: [PATCH 3/3] Simplify adding an escaped os.sep at the end of directories for file completions --- pylsp/plugins/jedi_completion.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pylsp/plugins/jedi_completion.py b/pylsp/plugins/jedi_completion.py index bf32ed70..90b4c191 100644 --- a/pylsp/plugins/jedi_completion.py +++ b/pylsp/plugins/jedi_completion.py @@ -3,7 +3,6 @@ import logging import os -import os.path as osp import parso @@ -222,7 +221,7 @@ def _format_completion(d, markup_kind: str, include_params=True, resolve=False, # Adjustments for file completions if d.type == 'path': - path = osp.normpath(d.name) + path = os.path.normpath(d.name) path = path.replace('\\', '\\\\') path = path.replace('/', '\\/') @@ -230,11 +229,11 @@ def _format_completion(d, markup_kind: str, include_params=True, resolve=False, # at the end to ease additional file completions. if d.name.endswith(os.sep): if os.name == 'nt': - completion['insertText'] = path + '\\\\' + path = path + '\\\\' else: - completion['insertText'] = path + '\\/' - else: - completion['insertText'] = path + path = path + '\\/' + + completion['insertText'] = path if include_params and not is_exception_class(d.name): snippet = _snippet(d, resolve_label_or_snippet)