1- import { CursorlessCommandId } from "@cursorless/common" ;
1+ import { CursorlessCommandId , Disposer } from "@cursorless/common" ;
22import {
33 ScopeProvider ,
44 ScopeSupport ,
55 ScopeSupportLevels ,
66 ScopeTypeInfo ,
77} from "@cursorless/cursorless-engine" ;
88import * as vscode from "vscode" ;
9- import { VisualizationType } from "./ScopeVisualizerCommandApi" ;
9+ import {
10+ ScopeVisualizer ,
11+ VisualizationType ,
12+ } from "./ScopeVisualizerCommandApi" ;
13+ import { isEqual } from "lodash" ;
1014
1115export class ScopeSupportTreeProvider
1216 implements vscode . TreeDataProvider < MyTreeItem >
1317{
14- private onDidChangeScopeSupportDisposable : vscode . Disposable | undefined ;
18+ private visibleDisposable : Disposer | undefined ;
1519 private treeView : vscode . TreeView < MyTreeItem > ;
1620 private supportLevels : ScopeSupportLevels = [ ] ;
1721
@@ -25,6 +29,7 @@ export class ScopeSupportTreeProvider
2529 constructor (
2630 private context : vscode . ExtensionContext ,
2731 private scopeProvider : ScopeProvider ,
32+ private scopeVisualizer : ScopeVisualizer ,
2833 ) {
2934 this . treeView = vscode . window . createTreeView ( "cursorless.scopeSupport" , {
3035 treeDataProvider : this ,
@@ -40,8 +45,13 @@ export class ScopeSupportTreeProvider
4045 static create (
4146 context : vscode . ExtensionContext ,
4247 scopeProvider : ScopeProvider ,
48+ scopeVisualizer : ScopeVisualizer ,
4349 ) : ScopeSupportTreeProvider {
44- const treeProvider = new ScopeSupportTreeProvider ( context , scopeProvider ) ;
50+ const treeProvider = new ScopeSupportTreeProvider (
51+ context ,
52+ scopeProvider ,
53+ scopeVisualizer ,
54+ ) ;
4555 treeProvider . init ( ) ;
4656 return treeProvider ;
4757 }
@@ -54,27 +64,32 @@ export class ScopeSupportTreeProvider
5464
5565 onDidChangeVisible ( e : vscode . TreeViewVisibilityChangeEvent ) {
5666 if ( e . visible ) {
57- if ( this . onDidChangeScopeSupportDisposable != null ) {
67+ if ( this . visibleDisposable != null ) {
5868 return ;
5969 }
6070
6171 this . registerScopeSupportListener ( ) ;
6272 } else {
63- if ( this . onDidChangeScopeSupportDisposable == null ) {
73+ if ( this . visibleDisposable == null ) {
6474 return ;
6575 }
6676
67- this . onDidChangeScopeSupportDisposable . dispose ( ) ;
68- this . onDidChangeScopeSupportDisposable = undefined ;
77+ this . visibleDisposable . dispose ( ) ;
78+ this . visibleDisposable = undefined ;
6979 }
7080 }
7181
7282 private registerScopeSupportListener ( ) {
73- this . onDidChangeScopeSupportDisposable =
83+ this . visibleDisposable = new Disposer ( ) ;
84+ this . visibleDisposable . push (
7485 this . scopeProvider . onDidChangeScopeSupport ( ( supportLevels ) => {
7586 this . supportLevels = supportLevels ;
7687 this . _onDidChangeTreeData . fire ( ) ;
77- } ) ;
88+ } ) ,
89+ this . scopeVisualizer . onDidChangeScopeType ( ( ) => {
90+ this . _onDidChangeTreeData . fire ( ) ;
91+ } ) ,
92+ ) ;
7893 }
7994
8095 getTreeItem ( element : MyTreeItem ) : MyTreeItem {
@@ -96,7 +111,13 @@ export class ScopeSupportTreeProvider
96111 getScopeTypesWithSupport ( scopeSupport : ScopeSupport ) : ScopeSupportTreeItem [ ] {
97112 return this . supportLevels
98113 . 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+ )
100121 . sort ( ( a , b ) => {
101122 if (
102123 a . scopeTypeInfo . spokenForm . type !== b . scopeTypeInfo . spokenForm . type
@@ -111,12 +132,12 @@ export class ScopeSupportTreeProvider
111132 return a . scopeTypeInfo . isLanguageSpecific ? - 1 : 1 ;
112133 }
113134
114- return a . label . localeCompare ( b . label ) ;
135+ return a . label . label . localeCompare ( b . label . label ) ;
115136 } ) ;
116137 }
117138
118139 dispose ( ) {
119- this . onDidChangeScopeSupportDisposable ?. dispose ( ) ;
140+ this . visibleDisposable ?. dispose ( ) ;
120141 }
121142}
122143
@@ -146,9 +167,12 @@ function getSupportCategories(): SupportCategoryTreeItem[] {
146167}
147168
148169class ScopeSupportTreeItem extends vscode . TreeItem {
149- public label : string ;
170+ public label : vscode . TreeItemLabel ;
150171
151- constructor ( public scopeTypeInfo : ScopeTypeInfo ) {
172+ constructor (
173+ public scopeTypeInfo : ScopeTypeInfo ,
174+ isVisualized : boolean ,
175+ ) {
152176 const label =
153177 scopeTypeInfo . spokenForm . type === "error"
154178 ? "-"
@@ -157,7 +181,10 @@ class ScopeSupportTreeItem extends vscode.TreeItem {
157181
158182 super ( label , vscode . TreeItemCollapsibleState . None ) ;
159183
160- this . label = label ;
184+ this . label = {
185+ label,
186+ highlights : isVisualized ? [ [ 0 , label . length ] ] : [ ] ,
187+ } ;
161188
162189 this . description = description ;
163190
@@ -170,14 +197,21 @@ class ScopeSupportTreeItem extends vscode.TreeItem {
170197 . join ( "\n" ) ;
171198 }
172199
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+ } ;
181215
182216 if ( scopeTypeInfo . isLanguageSpecific ) {
183217 this . iconPath = new vscode . ThemeIcon ( "code" ) ;
0 commit comments