|
1 | 1 | import logging
|
| 2 | +from pathlib import Path |
| 3 | +from typing import Any, Dict, Generator, TypedDict |
2 | 4 |
|
3 |
| -from pylsp import hookimpl, uris |
4 |
| - |
| 5 | +import isort |
| 6 | +from pylsp import hookimpl |
| 7 | +from pylsp.config.config import Config |
| 8 | +from pylsp.workspace import Document |
5 | 9 |
|
6 | 10 | logger = logging.getLogger(__name__)
|
7 | 11 |
|
8 | 12 |
|
9 |
| -@hookimpl |
10 |
| -def pylsp_settings(): |
11 |
| - logger.info("Initializing pylsp_isort") |
| 13 | +class Position(TypedDict): |
| 14 | + line: int |
| 15 | + character: int |
12 | 16 |
|
13 |
| - # Disable default plugins that conflicts with our plugin |
14 |
| - return { |
15 |
| - "plugins": { |
16 |
| - # "autopep8_format": {"enabled": False}, |
17 |
| - # "definition": {"enabled": False}, |
18 |
| - # "flake8_lint": {"enabled": False}, |
19 |
| - # "folding": {"enabled": False}, |
20 |
| - # "highlight": {"enabled": False}, |
21 |
| - # "hover": {"enabled": False}, |
22 |
| - # "jedi_completion": {"enabled": False}, |
23 |
| - # "jedi_rename": {"enabled": False}, |
24 |
| - # "mccabe_lint": {"enabled": False}, |
25 |
| - # "preload_imports": {"enabled": False}, |
26 |
| - # "pycodestyle_lint": {"enabled": False}, |
27 |
| - # "pydocstyle_lint": {"enabled": False}, |
28 |
| - # "pyflakes_lint": {"enabled": False}, |
29 |
| - # "pylint_lint": {"enabled": False}, |
30 |
| - # "references": {"enabled": False}, |
31 |
| - # "rope_completion": {"enabled": False}, |
32 |
| - # "rope_rename": {"enabled": False}, |
33 |
| - # "signature": {"enabled": False}, |
34 |
| - # "symbols": {"enabled": False}, |
35 |
| - # "yapf_format": {"enabled": False}, |
36 |
| - }, |
37 |
| - } |
| 17 | + |
| 18 | +class Range(TypedDict): |
| 19 | + start: Position |
| 20 | + end: Position |
38 | 21 |
|
39 | 22 |
|
40 | 23 | @hookimpl
|
41 |
| -def pylsp_code_actions(config, workspace, document, range, context): |
42 |
| - logger.info("textDocument/codeAction: %s %s %s", document, range, context) |
43 |
| - |
44 |
| - return [ |
45 |
| - { |
46 |
| - "title": "Extract method", |
47 |
| - "kind": "refactor.extract", |
48 |
| - "command": { |
49 |
| - "command": "example.refactor.extract", |
50 |
| - "arguments": [document.uri, range], |
| 24 | +def pylsp_settings() -> Dict[str, Any]: |
| 25 | + return { |
| 26 | + "plugins": { |
| 27 | + "isort": { |
| 28 | + "enabled": True, |
| 29 | + "profile": None, |
| 30 | + "line_length": 79, |
51 | 31 | },
|
52 | 32 | },
|
53 |
| - ] |
54 |
| - |
55 |
| - |
56 |
| -@hookimpl |
57 |
| -def pylsp_execute_command(config, workspace, command, arguments): |
58 |
| - logger.info("workspace/executeCommand: %s %s", command, arguments) |
59 |
| - |
60 |
| - if command == "example.refactor.extract": |
61 |
| - current_document, range = arguments |
62 |
| - |
63 |
| - workspace_edit = { |
64 |
| - "changes": { |
65 |
| - current_document: [ |
66 |
| - { |
67 |
| - "range": range, |
68 |
| - "newText": "replacement text", |
69 |
| - }, |
70 |
| - ] |
71 |
| - } |
72 |
| - } |
73 |
| - |
74 |
| - logger.info("applying workspace edit: %s %s", command, workspace_edit) |
75 |
| - workspace.apply_edit(workspace_edit) |
| 33 | + } |
76 | 34 |
|
77 | 35 |
|
78 |
| -@hookimpl |
79 |
| -def pylsp_definitions(config, workspace, document, position): |
80 |
| - logger.info("textDocument/definition: %s %s", document, position) |
81 |
| - |
82 |
| - filename = __file__ |
83 |
| - uri = uris.uri_with(document.uri, path=filename) |
84 |
| - with open(filename) as f: |
85 |
| - lines = f.readlines() |
86 |
| - for lineno, line in enumerate(lines): |
87 |
| - if "def pylsp_definitions" in line: |
88 |
| - break |
89 |
| - return [ |
90 |
| - { |
91 |
| - "uri": uri, |
92 |
| - "range": { |
93 |
| - "start": { |
94 |
| - "line": lineno, |
95 |
| - "character": 4, |
96 |
| - }, |
97 |
| - "end": { |
98 |
| - "line": lineno, |
99 |
| - "character": line.find(")") + 1, |
100 |
| - }, |
101 |
| - } |
102 |
| - } |
103 |
| - ] |
| 36 | +@hookimpl(hookwrapper=True) |
| 37 | +def pylsp_format_document(config: Config, document: Document) -> Generator: |
| 38 | + range = Range( |
| 39 | + start={"line": 0, "character": 0}, |
| 40 | + end={"line": len(document.lines), "character": 0}, |
| 41 | + ) |
| 42 | + outcome = yield |
| 43 | + _process(outcome, config, document, range) |
| 44 | + |
| 45 | + |
| 46 | +@hookimpl(hookwrapper=True) |
| 47 | +def pylsp_format_range(config: Config, document: Document, range: Range) -> Generator: |
| 48 | + outcome = yield |
| 49 | + _process(outcome, config, document, range) |
| 50 | + |
| 51 | + |
| 52 | +def _process(outcome, config: Config, document: Document, range: Range): |
| 53 | + result = outcome.get_result() |
| 54 | + if result: |
| 55 | + text = result[0]["newText"] |
| 56 | + range = result[0]["range"] |
| 57 | + else: |
| 58 | + start = range["start"]["line"] |
| 59 | + end = range["end"]["line"] |
| 60 | + text = "".join(document.lines[start:end]) |
| 61 | + |
| 62 | + config_kwargs = {} |
| 63 | + defined_args = set(getattr(isort.Config, "__dataclass_fields__", {}).keys()) |
| 64 | + settings = config.plugin_settings("isort", document_path=document.path) |
| 65 | + for key, value in settings.items(): |
| 66 | + if key in defined_args: |
| 67 | + config_kwargs[key] = value |
| 68 | + logger.debug("config_kwargs=%r", config_kwargs) |
| 69 | + |
| 70 | + new_text = isort.code( |
| 71 | + text, config=isort.Config(**config_kwargs), file_path=Path(document.path) |
| 72 | + ) |
| 73 | + |
| 74 | + if new_text != text: |
| 75 | + result = [{"range": range, "newText": new_text}] |
| 76 | + outcome.force_result(result) |
0 commit comments