-
-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow spoken forms generator to use custom
- Loading branch information
Showing
19 changed files
with
924 additions
and
544 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export interface SpokenFormSuccess { | ||
type: "success"; | ||
preferred: string; | ||
alternatives: string[]; | ||
} | ||
|
||
export interface SpokenFormError { | ||
type: "error"; | ||
reason: string; | ||
requiresTalonUpdate: boolean; | ||
isSecret: boolean; | ||
} | ||
|
||
export type SpokenForm = SpokenFormSuccess | SpokenFormError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export function camelCaseToAllDown(input: string): string { | ||
return input | ||
.replace(/([A-Z])/g, " $1") | ||
.split(" ") | ||
.map((word) => word.toLowerCase()) | ||
.join(" "); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import { mapValues } from "lodash"; | ||
import { | ||
SpokenFormMap, | ||
SpokenFormMapEntry, | ||
SpokenFormMapKeyTypes, | ||
} from "./SpokenFormMap"; | ||
|
||
type DefaultSpokenFormMapDefinition = { | ||
readonly [K in keyof SpokenFormMapKeyTypes]: Readonly< | ||
Record<SpokenFormMapKeyTypes[K], string | DefaultSpokenFormMapEntry> | ||
>; | ||
}; | ||
|
||
const defaultSpokenFormMapCore: DefaultSpokenFormMapDefinition = { | ||
pairedDelimiter: { | ||
curlyBrackets: "curly", | ||
angleBrackets: "diamond", | ||
escapedDoubleQuotes: "escaped quad", | ||
escapedSingleQuotes: "escaped twin", | ||
escapedParentheses: "escaped round", | ||
escapedSquareBrackets: "escaped box", | ||
doubleQuotes: "quad", | ||
parentheses: "round", | ||
backtickQuotes: "skis", | ||
squareBrackets: "box", | ||
singleQuotes: "twin", | ||
any: "pair", | ||
string: "string", | ||
whitespace: "void", | ||
}, | ||
|
||
simpleScopeTypeType: { | ||
argumentOrParameter: "arg", | ||
attribute: "attribute", | ||
functionCall: "call", | ||
functionCallee: "callee", | ||
className: "class name", | ||
class: "class", | ||
comment: "comment", | ||
functionName: "funk name", | ||
namedFunction: "funk", | ||
ifStatement: "if state", | ||
instance: "instance", | ||
collectionItem: "item", | ||
collectionKey: "key", | ||
anonymousFunction: "lambda", | ||
list: "list", | ||
map: "map", | ||
name: "name", | ||
regularExpression: "regex", | ||
section: "section", | ||
sectionLevelOne: disabledByDefault("one section"), | ||
sectionLevelTwo: disabledByDefault("two section"), | ||
sectionLevelThree: disabledByDefault("three section"), | ||
sectionLevelFour: disabledByDefault("four section"), | ||
sectionLevelFive: disabledByDefault("five section"), | ||
sectionLevelSix: disabledByDefault("six section"), | ||
selector: "selector", | ||
statement: "state", | ||
branch: "branch", | ||
type: "type", | ||
value: "value", | ||
condition: "condition", | ||
unit: "unit", | ||
// XML, JSX | ||
xmlElement: "element", | ||
xmlBothTags: "tags", | ||
xmlStartTag: "start tag", | ||
xmlEndTag: "end tag", | ||
// LaTeX | ||
part: "part", | ||
chapter: "chapter", | ||
subSection: "subsection", | ||
subSubSection: "subsubsection", | ||
namedParagraph: "paragraph", | ||
subParagraph: "subparagraph", | ||
environment: "environment", | ||
// Talon | ||
command: "command", | ||
// Text-based scope types | ||
character: "char", | ||
word: "word", | ||
token: "token", | ||
identifier: "identifier", | ||
line: "line", | ||
sentence: "sentence", | ||
paragraph: "block", | ||
document: "file", | ||
nonWhitespaceSequence: "paint", | ||
boundedNonWhitespaceSequence: "short paint", | ||
url: "link", | ||
notebookCell: "cell", | ||
|
||
string: secret("parse tree string"), | ||
switchStatementSubject: secret("subject"), | ||
}, | ||
|
||
surroundingPairForceDirection: { | ||
left: "left", | ||
right: "right", | ||
}, | ||
|
||
simpleModifier: { | ||
excludeInterior: "bounds", | ||
toRawSelection: "just", | ||
leading: "leading", | ||
trailing: "trailing", | ||
keepContentFilter: "content", | ||
keepEmptyFilter: "empty", | ||
inferPreviousMark: "its", | ||
startOf: "start of", | ||
endOf: "end of", | ||
interiorOnly: "inside", | ||
extendThroughStartOf: "head", | ||
extendThroughEndOf: "tail", | ||
everyScope: "every", | ||
}, | ||
|
||
modifierExtra: { | ||
first: "first", | ||
last: "last", | ||
previous: "previous", | ||
next: "next", | ||
forward: "forward", | ||
backward: "backward", | ||
}, | ||
|
||
customRegex: {}, | ||
}; | ||
|
||
function disabledByDefault( | ||
...spokenForms: string[] | ||
): DefaultSpokenFormMapEntry { | ||
return { | ||
defaultSpokenForms: spokenForms, | ||
isDisabledByDefault: true, | ||
isSecret: false, | ||
}; | ||
} | ||
|
||
function secret(...spokenForms: string[]): DefaultSpokenFormMapEntry { | ||
return { | ||
defaultSpokenForms: spokenForms, | ||
isDisabledByDefault: true, | ||
isSecret: true, | ||
}; | ||
} | ||
|
||
export interface DefaultSpokenFormMapEntry { | ||
defaultSpokenForms: string[]; | ||
isDisabledByDefault: boolean; | ||
isSecret: boolean; | ||
} | ||
|
||
export type DefaultSpokenFormMap = { | ||
readonly [K in keyof SpokenFormMapKeyTypes]: Readonly< | ||
Record<SpokenFormMapKeyTypes[K], DefaultSpokenFormMapEntry> | ||
>; | ||
}; | ||
|
||
// FIXME: Don't cast here; need to make our own mapValues with stronger typing | ||
// using tricks from our object.d.ts | ||
export const defaultSpokenFormInfo = mapValues( | ||
defaultSpokenFormMapCore, | ||
(entry) => | ||
mapValues(entry, (subEntry) => | ||
typeof subEntry === "string" | ||
? { | ||
defaultSpokenForms: [subEntry], | ||
isDisabledByDefault: false, | ||
isSecret: false, | ||
} | ||
: subEntry, | ||
), | ||
) as DefaultSpokenFormMap; | ||
|
||
// FIXME: Don't cast here; need to make our own mapValues with stronger typing | ||
// using tricks from our object.d.ts | ||
export const defaultSpokenFormMap = mapValues(defaultSpokenFormInfo, (entry) => | ||
mapValues( | ||
entry, | ||
({ | ||
defaultSpokenForms, | ||
isDisabledByDefault, | ||
isSecret, | ||
}): SpokenFormMapEntry => ({ | ||
spokenForms: isDisabledByDefault ? [] : defaultSpokenForms, | ||
isCustom: false, | ||
defaultSpokenForms, | ||
requiresTalonUpdate: false, | ||
isSecret, | ||
}), | ||
), | ||
) as SpokenFormMap; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
ModifierType, | ||
SimpleScopeTypeType, | ||
SurroundingPairName, | ||
} from "@cursorless/common"; | ||
|
||
export type SpeakableSurroundingPairName = | ||
| Exclude<SurroundingPairName, "collectionBoundary"> | ||
| "whitespace"; | ||
|
||
export type SimpleModifierType = Exclude< | ||
ModifierType, | ||
| "containingScope" | ||
| "ordinalScope" | ||
| "relativeScope" | ||
| "modifyIfUntyped" | ||
| "cascading" | ||
| "range" | ||
>; | ||
|
||
export type ModifierExtra = | ||
| "first" | ||
| "last" | ||
| "previous" | ||
| "next" | ||
| "forward" | ||
| "backward"; | ||
|
||
export interface SpokenFormMapKeyTypes { | ||
pairedDelimiter: SpeakableSurroundingPairName; | ||
simpleScopeTypeType: SimpleScopeTypeType; | ||
surroundingPairForceDirection: "left" | "right"; | ||
simpleModifier: SimpleModifierType; | ||
modifierExtra: ModifierExtra; | ||
customRegex: string; | ||
} | ||
|
||
export type SpokenFormType = keyof SpokenFormMapKeyTypes; | ||
|
||
export interface SpokenFormMapEntry { | ||
spokenForms: string[]; | ||
isCustom: boolean; | ||
defaultSpokenForms: string[]; | ||
requiresTalonUpdate: boolean; | ||
isSecret: boolean; | ||
} | ||
|
||
export type SpokenFormMap = { | ||
readonly [K in keyof SpokenFormMapKeyTypes]: Readonly< | ||
Record<SpokenFormMapKeyTypes[K], SpokenFormMapEntry> | ||
>; | ||
}; |
48 changes: 48 additions & 0 deletions
48
packages/cursorless-engine/src/generateSpokenForm/GeneratorSpokenFormMap.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { | ||
SpokenFormMap, | ||
SpokenFormMapEntry, | ||
SpokenFormMapKeyTypes, | ||
SpokenFormType, | ||
} from "../SpokenFormMap"; | ||
|
||
export type GeneratorSpokenFormMap = { | ||
readonly [K in keyof SpokenFormMapKeyTypes]: Record< | ||
SpokenFormMapKeyTypes[K], | ||
SingleTermSpokenForm | ||
>; | ||
}; | ||
|
||
export interface SingleTermSpokenForm { | ||
type: "singleTerm"; | ||
spokenForms: SpokenFormMapEntry; | ||
spokenFormType: SpokenFormType; | ||
id: string; | ||
} | ||
|
||
export type SpokenFormComponent = | ||
| SingleTermSpokenForm | ||
| string | ||
| SpokenFormComponent[]; | ||
|
||
export function getGeneratorSpokenForms( | ||
spokenFormMap: SpokenFormMap, | ||
): GeneratorSpokenFormMap { | ||
// FIXME: Don't cast here; need to make our own mapValues with stronger typing | ||
// using tricks from our object.d.ts | ||
return Object.fromEntries( | ||
Object.entries(spokenFormMap).map(([spokenFormType, map]) => [ | ||
spokenFormType, | ||
Object.fromEntries( | ||
Object.entries(map).map(([id, spokenForms]) => [ | ||
id, | ||
{ | ||
type: "singleTerm", | ||
spokenForms, | ||
spokenFormType, | ||
id, | ||
}, | ||
]), | ||
), | ||
]), | ||
) as GeneratorSpokenFormMap; | ||
} |
6 changes: 5 additions & 1 deletion
6
packages/cursorless-engine/src/generateSpokenForm/NoSpokenFormError.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
export class NoSpokenFormError extends Error { | ||
constructor(public reason: string) { | ||
constructor( | ||
public reason: string, | ||
public requiresTalonUpdate: boolean = false, | ||
public isSecret: boolean = false, | ||
) { | ||
super(`No spoken form for: ${reason}`); | ||
} | ||
} |
Oops, something went wrong.