1
1
import { CursorlessCommandId , Disposer } from "@cursorless/common" ;
2
2
import {
3
+ CustomSpokenFormGenerator ,
3
4
ScopeProvider ,
4
5
ScopeSupport ,
5
6
ScopeSupportLevels ,
6
7
ScopeTypeInfo ,
7
8
} from "@cursorless/cursorless-engine" ;
9
+ import { VscodeApi } from "@cursorless/vscode-common" ;
10
+ import { isEqual } from "lodash" ;
8
11
import * as vscode from "vscode" ;
12
+ import { URI } from "vscode-uri" ;
9
13
import {
10
14
ScopeVisualizer ,
11
15
VisualizationType ,
12
16
} from "./ScopeVisualizerCommandApi" ;
13
- import { isEqual } from "lodash" ;
17
+
18
+ export const DONT_SHOW_TALON_UPDATE_MESSAGE_KEY = "dontShowUpdateTalonMessage" ;
14
19
15
20
export class ScopeSupportTreeProvider
16
21
implements vscode . TreeDataProvider < MyTreeItem >
17
22
{
18
23
private visibleDisposable : Disposer | undefined ;
19
24
private treeView : vscode . TreeView < MyTreeItem > ;
20
25
private supportLevels : ScopeSupportLevels = [ ] ;
26
+ private shownUpdateTalonMessage = false ;
21
27
22
28
private _onDidChangeTreeData : vscode . EventEmitter <
23
29
MyTreeItem | undefined | null | void
@@ -27,11 +33,14 @@ export class ScopeSupportTreeProvider
27
33
> = this . _onDidChangeTreeData . event ;
28
34
29
35
constructor (
36
+ private vscodeApi : VscodeApi ,
30
37
private context : vscode . ExtensionContext ,
31
38
private scopeProvider : ScopeProvider ,
32
39
private scopeVisualizer : ScopeVisualizer ,
40
+ private customSpokenFormGenerator : CustomSpokenFormGenerator ,
41
+ private hasCommandServer : boolean ,
33
42
) {
34
- this . treeView = vscode . window . createTreeView ( "cursorless.scopeSupport" , {
43
+ this . treeView = vscodeApi . window . createTreeView ( "cursorless.scopeSupport" , {
35
44
treeDataProvider : this ,
36
45
} ) ;
37
46
@@ -43,14 +52,20 @@ export class ScopeSupportTreeProvider
43
52
}
44
53
45
54
static create (
55
+ vscodeApi : VscodeApi ,
46
56
context : vscode . ExtensionContext ,
47
57
scopeProvider : ScopeProvider ,
48
58
scopeVisualizer : ScopeVisualizer ,
59
+ customSpokenFormGenerator : CustomSpokenFormGenerator ,
60
+ hasCommandServer : boolean ,
49
61
) : ScopeSupportTreeProvider {
50
62
const treeProvider = new ScopeSupportTreeProvider (
63
+ vscodeApi ,
51
64
context ,
52
65
scopeProvider ,
53
66
scopeVisualizer ,
67
+ customSpokenFormGenerator ,
68
+ hasCommandServer ,
54
69
) ;
55
70
treeProvider . init ( ) ;
56
71
return treeProvider ;
@@ -98,6 +113,7 @@ export class ScopeSupportTreeProvider
98
113
99
114
getChildren ( element ?: MyTreeItem ) : MyTreeItem [ ] {
100
115
if ( element == null ) {
116
+ this . possiblyShowUpdateTalonMessage ( ) ;
101
117
return getSupportCategories ( ) ;
102
118
}
103
119
@@ -108,9 +124,46 @@ export class ScopeSupportTreeProvider
108
124
throw new Error ( "Unexpected element" ) ;
109
125
}
110
126
127
+ private async possiblyShowUpdateTalonMessage ( ) {
128
+ if (
129
+ ! this . customSpokenFormGenerator . needsInitialTalonUpdate ||
130
+ this . shownUpdateTalonMessage ||
131
+ ! this . hasCommandServer ||
132
+ ( await this . context . globalState . get ( DONT_SHOW_TALON_UPDATE_MESSAGE_KEY ) )
133
+ ) {
134
+ return ;
135
+ }
136
+
137
+ this . shownUpdateTalonMessage = true ;
138
+
139
+ const result = await this . vscodeApi . window . showInformationMessage (
140
+ "In order to see your custom spoken forms in the sidebar, you'll need to update your Cursorless Talon files." ,
141
+ "How?" ,
142
+ "Don't show again" ,
143
+ ) ;
144
+
145
+ if ( result === "How?" ) {
146
+ await this . vscodeApi . env . openExternal (
147
+ URI . parse (
148
+ "https://www.cursorless.org/docs/user/updating/#updating-the-talon-side" ,
149
+ ) ,
150
+ ) ;
151
+ } else if ( result === "Don't show again" ) {
152
+ await this . context . globalState . update (
153
+ DONT_SHOW_TALON_UPDATE_MESSAGE_KEY ,
154
+ true ,
155
+ ) ;
156
+ }
157
+ }
158
+
111
159
getScopeTypesWithSupport ( scopeSupport : ScopeSupport ) : ScopeSupportTreeItem [ ] {
112
160
return this . supportLevels
113
- . filter ( ( supportLevel ) => supportLevel . support === scopeSupport )
161
+ . filter (
162
+ ( supportLevel ) =>
163
+ supportLevel . support === scopeSupport &&
164
+ ( supportLevel . spokenForm . type !== "error" ||
165
+ ! supportLevel . spokenForm . isSecret ) ,
166
+ )
114
167
. map (
115
168
( supportLevel ) =>
116
169
new ScopeSupportTreeItem (
@@ -169,6 +222,11 @@ function getSupportCategories(): SupportCategoryTreeItem[] {
169
222
class ScopeSupportTreeItem extends vscode . TreeItem {
170
223
public label : vscode . TreeItemLabel ;
171
224
225
+ /**
226
+ * @param scopeTypeInfo The scope type info
227
+ * @param isVisualized Whether the scope type is currently being visualized
228
+ with the scope visualizer
229
+ */
172
230
constructor (
173
231
public scopeTypeInfo : ScopeTypeInfo ,
174
232
isVisualized : boolean ,
@@ -181,20 +239,27 @@ class ScopeSupportTreeItem extends vscode.TreeItem {
181
239
182
240
super ( label , vscode . TreeItemCollapsibleState . None ) ;
183
241
242
+ const requiresTalonUpdate =
243
+ scopeTypeInfo . spokenForm . type === "error" &&
244
+ scopeTypeInfo . spokenForm . requiresTalonUpdate ;
245
+
184
246
this . label = {
185
247
label,
186
248
highlights : isVisualized ? [ [ 0 , label . length ] ] : [ ] ,
187
249
} ;
188
250
189
251
this . description = description ;
190
252
191
- if (
192
- scopeTypeInfo . spokenForm . type === "success" &&
193
- scopeTypeInfo . spokenForm . alternatives . length > 0
194
- ) {
195
- this . tooltip = scopeTypeInfo . spokenForm . alternatives
196
- . map ( ( spokenForm ) => `"${ spokenForm } "` )
197
- . join ( "\n" ) ;
253
+ if ( scopeTypeInfo . spokenForm . type === "success" ) {
254
+ if ( scopeTypeInfo . spokenForm . alternatives . length > 0 ) {
255
+ this . tooltip = scopeTypeInfo . spokenForm . alternatives
256
+ . map ( ( spokenForm ) => `"${ spokenForm } "` )
257
+ . join ( "\n" ) ;
258
+ }
259
+ } else if ( requiresTalonUpdate ) {
260
+ this . tooltip = "Requires Talon update" ;
261
+ } else {
262
+ this . tooltip = "Spoken form disabled; see customization docs" ;
198
263
}
199
264
200
265
this . command = isVisualized
0 commit comments