@@ -6,29 +6,20 @@ import {
66} from "@cursorless/common" ;
77import { isEqual } from "lodash" ;
88import {
9+ SUPPORTED_ENTRY_TYPES ,
910 NeedsInitialTalonUpdateError ,
1011 SpokenFormEntry ,
1112 TalonSpokenForms ,
1213} from "../scopeProviders/SpokenFormEntry" ;
1314import { ide } from "../singletons/ide.singleton" ;
1415import { SpokenFormMap , SpokenFormMapEntry } from "./SpokenFormMap" ;
15- import { SpokenFormType } from "./SpokenFormType" ;
16+ import { SpokenFormMapKeyTypes , SpokenFormType } from "./SpokenFormType" ;
1617import {
1718 defaultSpokenFormInfoMap ,
1819 defaultSpokenFormMap ,
1920} from "./defaultSpokenFormMap" ;
2021import { DefaultSpokenFormMapEntry } from "./defaultSpokenFormMap.types" ;
2122
22- /**
23- * The types of entries for which we currently support getting custom spoken
24- * forms from Talon.
25- */
26- const ENTRY_TYPES = [
27- "simpleScopeTypeType" ,
28- "customRegex" ,
29- "pairedDelimiter" ,
30- ] as const ;
31-
3223type Writable < T > = {
3324 - readonly [ K in keyof T ] : T [ K ] ;
3425} ;
@@ -110,61 +101,17 @@ export class CustomSpokenForms {
110101 return ;
111102 }
112103
113- for ( const entryType of ENTRY_TYPES ) {
114- const customEntries = Object . fromEntries (
115- allCustomEntries
116- . filter ( ( entry ) => entry . type === entryType )
117- . map ( ( { id, spokenForms } ) => [ id , spokenForms ] ) ,
104+ for ( const entryType of SUPPORTED_ENTRY_TYPES ) {
105+ updateEntriesForType (
106+ this . spokenFormMap_ ,
107+ entryType ,
108+ defaultSpokenFormInfoMap [ entryType ] ,
109+ Object . fromEntries (
110+ allCustomEntries
111+ . filter ( ( entry ) => entry . type === entryType )
112+ . map ( ( { id, spokenForms } ) => [ id , spokenForms ] ) ,
113+ ) ,
118114 ) ;
119-
120- const defaultEntries : Partial < Record < string , DefaultSpokenFormMapEntry > > =
121- defaultSpokenFormInfoMap [ entryType ] ;
122-
123- /**
124- * The ids of the entries to include in the spoken form map. We need a
125- * union of the ids from the default entry and the custom entry. The custom
126- * entry could be missing private entries, or it could be missing entries
127- * because the Talon side is old. The default entry could be missing entries
128- * like custom regexes, where the user can create arbitrary ids.
129- */
130- const ids = Array . from (
131- new Set ( [
132- ...Object . keys ( defaultEntries ) ,
133- ...Object . keys ( customEntries ) ,
134- ] ) ,
135- ) ;
136- // FIXME: How to avoid the type assertions here?
137- this . spokenFormMap_ [ entryType ] = Object . fromEntries (
138- ids . map ( ( id ) : [ SpokenFormType , SpokenFormMapEntry ] => {
139- const { defaultSpokenForms = [ ] , isPrivate = false } =
140- defaultEntries [ id ] ?? { } ;
141- const customSpokenForms = customEntries [ id ] ;
142- if ( customSpokenForms != null ) {
143- return [
144- id as SpokenFormType ,
145- {
146- defaultSpokenForms,
147- spokenForms : customSpokenForms ,
148- requiresTalonUpdate : false ,
149- isCustom : isEqual ( defaultSpokenForms , customSpokenForms ) ,
150- isPrivate,
151- } ,
152- ] ;
153- } else {
154- return [
155- id as SpokenFormType ,
156- {
157- defaultSpokenForms,
158- spokenForms : [ ] ,
159- // If it's not a private spoken form, then it's a new scope type
160- requiresTalonUpdate : ! isPrivate ,
161- isCustom : false ,
162- isPrivate,
163- } ,
164- ] ;
165- }
166- } ) ,
167- ) as any ;
168115 }
169116
170117 this . customSpokenFormsInitialized_ = true ;
@@ -180,3 +127,53 @@ export class CustomSpokenForms {
180127
181128 dispose = this . disposer . dispose ;
182129}
130+
131+ function updateEntriesForType < T extends SpokenFormType > (
132+ spokenFormMapToUpdate : Writable < SpokenFormMap > ,
133+ key : T ,
134+ defaultEntries : Partial <
135+ Record < SpokenFormMapKeyTypes [ T ] , DefaultSpokenFormMapEntry >
136+ > ,
137+ customEntries : Partial < Record < SpokenFormMapKeyTypes [ T ] , string [ ] > > ,
138+ ) {
139+ /**
140+ * The ids of the entries to include in the spoken form map. We need a
141+ * union of the ids from the default entry and the custom entry. The custom
142+ * entry could be missing private entries, or it could be missing entries
143+ * because the Talon side is old. The default entry could be missing entries
144+ * like custom regexes, where the user can create arbitrary ids.
145+ */
146+ const ids = Array . from (
147+ new Set ( [ ...Object . keys ( defaultEntries ) , ...Object . keys ( customEntries ) ] ) ,
148+ ) as SpokenFormMapKeyTypes [ T ] [ ] ;
149+
150+ const obj : Partial < Record < SpokenFormMapKeyTypes [ T ] , SpokenFormMapEntry > > = { } ;
151+ for ( const id of ids ) {
152+ const { defaultSpokenForms = [ ] , isPrivate = false } =
153+ defaultEntries [ id ] ?? { } ;
154+ const customSpokenForms = customEntries [ id ] ;
155+
156+ obj [ id ] =
157+ customSpokenForms == null
158+ ? // No entry for the given id. This either means that the user needs to
159+ // update Talon, or it's a private spoken form.
160+ {
161+ defaultSpokenForms,
162+ spokenForms : [ ] ,
163+ // If it's not a private spoken form, then it's a new scope type
164+ requiresTalonUpdate : ! isPrivate ,
165+ isCustom : false ,
166+ isPrivate,
167+ }
168+ : // We have an entry for the given id
169+ {
170+ defaultSpokenForms,
171+ spokenForms : customSpokenForms ,
172+ requiresTalonUpdate : false ,
173+ isCustom : isEqual ( defaultSpokenForms , customSpokenForms ) ,
174+ isPrivate,
175+ } ;
176+ }
177+
178+ spokenFormMapToUpdate [ key ] = obj as SpokenFormMap [ T ] ;
179+ }
0 commit comments