1
- import { CursorlessCommandId } from "@cursorless/common" ;
1
+ import { CursorlessCommandId , Disposer } from "@cursorless/common" ;
2
2
import {
3
3
ScopeProvider ,
4
4
ScopeSupport ,
5
5
ScopeSupportLevels ,
6
6
ScopeTypeInfo ,
7
7
} from "@cursorless/cursorless-engine" ;
8
8
import * as vscode from "vscode" ;
9
- import { VisualizationType } from "./ScopeVisualizerCommandApi" ;
9
+ import {
10
+ ScopeVisualizer ,
11
+ VisualizationType ,
12
+ } from "./ScopeVisualizerCommandApi" ;
13
+ import { isEqual } from "lodash" ;
10
14
11
15
export class ScopeSupportTreeProvider
12
16
implements vscode . TreeDataProvider < MyTreeItem >
13
17
{
14
- private onDidChangeScopeSupportDisposable : vscode . Disposable | undefined ;
18
+ private visibleDisposable : Disposer | undefined ;
15
19
private treeView : vscode . TreeView < MyTreeItem > ;
16
20
private supportLevels : ScopeSupportLevels = [ ] ;
17
21
@@ -25,6 +29,7 @@ export class ScopeSupportTreeProvider
25
29
constructor (
26
30
private context : vscode . ExtensionContext ,
27
31
private scopeProvider : ScopeProvider ,
32
+ private scopeVisualizer : ScopeVisualizer ,
28
33
) {
29
34
this . treeView = vscode . window . createTreeView ( "cursorless.scopeSupport" , {
30
35
treeDataProvider : this ,
@@ -40,8 +45,13 @@ export class ScopeSupportTreeProvider
40
45
static create (
41
46
context : vscode . ExtensionContext ,
42
47
scopeProvider : ScopeProvider ,
48
+ scopeVisualizer : ScopeVisualizer ,
43
49
) : ScopeSupportTreeProvider {
44
- const treeProvider = new ScopeSupportTreeProvider ( context , scopeProvider ) ;
50
+ const treeProvider = new ScopeSupportTreeProvider (
51
+ context ,
52
+ scopeProvider ,
53
+ scopeVisualizer ,
54
+ ) ;
45
55
treeProvider . init ( ) ;
46
56
return treeProvider ;
47
57
}
@@ -54,27 +64,32 @@ export class ScopeSupportTreeProvider
54
64
55
65
onDidChangeVisible ( e : vscode . TreeViewVisibilityChangeEvent ) {
56
66
if ( e . visible ) {
57
- if ( this . onDidChangeScopeSupportDisposable != null ) {
67
+ if ( this . visibleDisposable != null ) {
58
68
return ;
59
69
}
60
70
61
71
this . registerScopeSupportListener ( ) ;
62
72
} else {
63
- if ( this . onDidChangeScopeSupportDisposable == null ) {
73
+ if ( this . visibleDisposable == null ) {
64
74
return ;
65
75
}
66
76
67
- this . onDidChangeScopeSupportDisposable . dispose ( ) ;
68
- this . onDidChangeScopeSupportDisposable = undefined ;
77
+ this . visibleDisposable . dispose ( ) ;
78
+ this . visibleDisposable = undefined ;
69
79
}
70
80
}
71
81
72
82
private registerScopeSupportListener ( ) {
73
- this . onDidChangeScopeSupportDisposable =
83
+ this . visibleDisposable = new Disposer ( ) ;
84
+ this . visibleDisposable . push (
74
85
this . scopeProvider . onDidChangeScopeSupport ( ( supportLevels ) => {
75
86
this . supportLevels = supportLevels ;
76
87
this . _onDidChangeTreeData . fire ( ) ;
77
- } ) ;
88
+ } ) ,
89
+ this . scopeVisualizer . onDidChangeScopeType ( ( ) => {
90
+ this . _onDidChangeTreeData . fire ( ) ;
91
+ } ) ,
92
+ ) ;
78
93
}
79
94
80
95
getTreeItem ( element : MyTreeItem ) : MyTreeItem {
@@ -96,7 +111,13 @@ export class ScopeSupportTreeProvider
96
111
getScopeTypesWithSupport ( scopeSupport : ScopeSupport ) : ScopeSupportTreeItem [ ] {
97
112
return this . supportLevels
98
113
. filter ( ( supportLevel ) => supportLevel . support === scopeSupport )
99
- . map ( ( supportLevel ) => new ScopeSupportTreeItem ( supportLevel ) )
114
+ . map (
115
+ ( supportLevel ) =>
116
+ new ScopeSupportTreeItem (
117
+ supportLevel ,
118
+ isEqual ( supportLevel . scopeType , this . scopeVisualizer . scopeType ) ,
119
+ ) ,
120
+ )
100
121
. sort ( ( a , b ) => {
101
122
if (
102
123
a . scopeTypeInfo . spokenForm . type !== b . scopeTypeInfo . spokenForm . type
@@ -111,12 +132,12 @@ export class ScopeSupportTreeProvider
111
132
return a . scopeTypeInfo . isLanguageSpecific ? - 1 : 1 ;
112
133
}
113
134
114
- return a . label . localeCompare ( b . label ) ;
135
+ return a . label . label . localeCompare ( b . label . label ) ;
115
136
} ) ;
116
137
}
117
138
118
139
dispose ( ) {
119
- this . onDidChangeScopeSupportDisposable ?. dispose ( ) ;
140
+ this . visibleDisposable ?. dispose ( ) ;
120
141
}
121
142
}
122
143
@@ -146,9 +167,12 @@ function getSupportCategories(): SupportCategoryTreeItem[] {
146
167
}
147
168
148
169
class ScopeSupportTreeItem extends vscode . TreeItem {
149
- public label : string ;
170
+ public label : vscode . TreeItemLabel ;
150
171
151
- constructor ( public scopeTypeInfo : ScopeTypeInfo ) {
172
+ constructor (
173
+ public scopeTypeInfo : ScopeTypeInfo ,
174
+ isVisualized : boolean ,
175
+ ) {
152
176
const label =
153
177
scopeTypeInfo . spokenForm . type === "error"
154
178
? "-"
@@ -157,7 +181,10 @@ class ScopeSupportTreeItem extends vscode.TreeItem {
157
181
158
182
super ( label , vscode . TreeItemCollapsibleState . None ) ;
159
183
160
- this . label = label ;
184
+ this . label = {
185
+ label,
186
+ highlights : isVisualized ? [ [ 0 , label . length ] ] : [ ] ,
187
+ } ;
161
188
162
189
this . description = description ;
163
190
@@ -170,14 +197,21 @@ class ScopeSupportTreeItem extends vscode.TreeItem {
170
197
. join ( "\n" ) ;
171
198
}
172
199
173
- this . command = {
174
- command : "cursorless.showScopeVisualizer" satisfies CursorlessCommandId ,
175
- arguments : [
176
- scopeTypeInfo . scopeType ,
177
- "content" satisfies VisualizationType ,
178
- ] ,
179
- title : `Visualize ${ scopeTypeInfo . humanReadableName } ` ,
180
- } ;
200
+ this . command = isVisualized
201
+ ? {
202
+ command :
203
+ "cursorless.hideScopeVisualizer" satisfies CursorlessCommandId ,
204
+ title : "Hide the scope visualizer" ,
205
+ }
206
+ : {
207
+ command :
208
+ "cursorless.showScopeVisualizer" satisfies CursorlessCommandId ,
209
+ arguments : [
210
+ scopeTypeInfo . scopeType ,
211
+ "content" satisfies VisualizationType ,
212
+ ] ,
213
+ title : `Visualize ${ scopeTypeInfo . humanReadableName } ` ,
214
+ } ;
181
215
182
216
if ( scopeTypeInfo . isLanguageSpecific ) {
183
217
this . iconPath = new vscode . ThemeIcon ( "code" ) ;
0 commit comments