-
Notifications
You must be signed in to change notification settings - Fork 10
/
plugin_commands.py
108 lines (94 loc) · 4.45 KB
/
plugin_commands.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from .plugin import RustAnalyzerCommand
from LSP.plugin import apply_text_edits
from LSP.plugin import Request
from LSP.plugin.core.protocol import Error
from LSP.plugin.core.protocol import Range
from LSP.plugin.core.protocol import TextDocumentIdentifier
from LSP.plugin.core.protocol import TextEdit
from LSP.plugin.core.typing import List, Literal, Optional, TypedDict, Union
from LSP.plugin.core.views import first_selection_region
from LSP.plugin.core.views import region_to_range
from LSP.plugin.core.views import text_document_identifier
import sublime
class JoinLinesRequest:
Type = 'experimental/joinLines'
ParamsType = TypedDict('ParamsType', {
'textDocument': TextDocumentIdentifier,
'ranges': List[Range],
})
ReturnType = List[TextEdit]
class MoveItemRequest:
Type = 'experimental/moveItem'
Direction = Literal['Up', 'Down']
ParamsType = TypedDict('ParamsType', {
'textDocument': TextDocumentIdentifier,
'range': Range,
'direction': Direction,
})
ReturnType = List[TextEdit]
class RustAnalyzerJoinLinesCommand(RustAnalyzerCommand):
def run(self, edit: sublime.Edit) -> None:
sublime.set_timeout_async(self.make_request_async)
def make_request_async(self) -> None:
session = self.session_by_name(self.session_name)
if session is None:
return
session_view = session.session_view_for_view_async(self.view)
if not session_view:
return
view_listener = session_view.listener()
if not view_listener:
return
params = {
'textDocument': text_document_identifier(self.view),
'ranges': [region_to_range(self.view, region) for region in self.view.sel()],
} # type: JoinLinesRequest.ParamsType
request = Request(JoinLinesRequest.Type, params) # type: Request[JoinLinesRequest.ReturnType]
document_version = self.view.change_count()
view_listener.purge_changes_async()
session.send_request_task(request).then(lambda result: self.on_result_async(result, document_version))
def on_result_async(self, edits: Union[JoinLinesRequest.ReturnType, Error], document_version: int) -> None:
if isinstance(edits, Error):
sublime.status_message('Error handling the "{}" request. Falling back to native join.'.format(
JoinLinesRequest.Type))
self.view.run_command('join_lines')
return
apply_text_edits(self.view, edits, required_view_version=document_version)
class RustAnalyzerMoveItemCommand(RustAnalyzerCommand):
def run(self, edit: sublime.Edit, direction: Optional[MoveItemRequest.Direction] = None) -> None:
if direction not in ('Up', 'Down'):
sublime.status_message('Error running command: direction must be either "Up" or "Down".')
return
sublime.set_timeout_async(lambda: self.make_request_async(direction))
def make_request_async(self, direction: MoveItemRequest.Direction) -> None:
session = self.session_by_name(self.session_name)
if session is None:
return
session_view = session.session_view_for_view_async(self.view)
if not session_view:
return
view_listener = session_view.listener()
if not view_listener:
return
first_selection = first_selection_region(self.view)
if first_selection is None:
return
params = {
'textDocument': text_document_identifier(self.view),
'range': region_to_range(self.view, first_selection),
'direction': direction,
} # type: MoveItemRequest.ParamsType
request = Request(MoveItemRequest.Type, params) # type: Request[MoveItemRequest.ReturnType]
document_version = self.view.change_count()
view_listener.purge_changes_async()
session.send_request_task(request).then(lambda result: self.on_result_async(result, document_version))
def on_result_async(self, edits: Union[MoveItemRequest.ReturnType, Error], document_version: int) -> None:
if document_version != self.view.change_count():
return
if isinstance(edits, Error):
sublime.status_message('Error handling the "{}" request.'.format(MoveItemRequest.Type))
return
if not edits:
sublime.status_message('Did not find anything to move.')
return
apply_text_edits(self.view, edits, process_placeholders=True)