Skip to content

Commit 1abf38d

Browse files
fidgetingbitsfidgetingbitspokey
authored
Add language overrides for delimiter maps (#2012)
This is me breaking out some functionality that was part of PR #1911 since that PR has lots of work to be done and it may still benefit other languages that get in sooner. I've applied the suggested changes from pokey in that PR's code review. I've also added a placeholder map for lua which uses `[[ ]]` for multiline support as noted in PR #1962, however I realized as I went to add it that it's not as simple as the way I did it for nix because I can't just reuse the existing `singleQuote` entry since lua actually uses single quotes. So this may actually be a bit harder, and reminds me of [this discussion](#1992 (comment)). So before I go randomly hacking stuff I'm curious what you think the best approach here is. These are the comments I had left in the Nix PR about these changes: * I called returning delimiterToText as getSimpleDelimiterMap to kind of mirror complexDelimiterMap. * I'm not sure is if you still want a delimiterMap.ts standalone file, and then a getSimpleDelimiterMap.ts only for that function. Now delimiterToText isn't referenced anywhere else, so seemed maybe okay to keep them together. * I also thought about adding getComplexDelimiterMap(), but atm because complexDelimiterMap only ever uses the keys from the delimiterToText it won't change even if the language has different values, so seemed unnecessary. These are all things I could guess at your preferences, but may as well ask instead. * I also noticed leftToRightMap in that file isn't actually used anywhere so can be deleted I think, but also not sure about doing that as part of a totally unrelated code change, to keep commits clean. ## Checklist - [x] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [-] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [x] I have not broken the cheatsheet --------- Co-authored-by: fidgetingbits <[email protected]> Co-authored-by: Pokey Rule <[email protected]>
1 parent 2d07d11 commit 1abf38d

File tree

5 files changed

+88
-6
lines changed

5 files changed

+88
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
languageId: lua
2+
command:
3+
version: 7
4+
spokenForm: change string
5+
action:
6+
name: clearAndSetSelection
7+
target:
8+
type: primitive
9+
modifiers:
10+
- type: containingScope
11+
scopeType: {type: surroundingPair, delimiter: string}
12+
usePrePhraseSnapshot: true
13+
initialState:
14+
documentContents: "[[aaa]]"
15+
selections:
16+
- anchor: {line: 0, character: 2}
17+
active: {line: 0, character: 2}
18+
marks: {}
19+
finalState:
20+
documentContents: ""
21+
selections:
22+
- anchor: {line: 0, character: 0}
23+
active: {line: 0, character: 0}

packages/cursorless-engine/src/processTargets/modifiers/surroundingPair/delimiterMaps.ts

+54-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import { unsafeKeys } from "../../../util/object";
66

77
type IndividualDelimiterText = string | string[];
88

9-
export const delimiterToText: Record<
9+
type DelimiterMap = Record<
1010
SimpleSurroundingPairName,
1111
[IndividualDelimiterText, IndividualDelimiterText]
12-
> = Object.freeze({
12+
>;
13+
14+
const delimiterToText: DelimiterMap = Object.freeze({
1315
angleBrackets: [
1416
["</", "<"],
1517
[">", "/>"],
@@ -26,6 +28,24 @@ export const delimiterToText: Record<
2628
squareBrackets: ["[", "]"],
2729
});
2830

31+
// FIXME: Probably remove these as part of
32+
// https://github.com/cursorless-dev/cursorless/issues/1812#issuecomment-1691493746
33+
const delimiterToTextOverrides: Record<string, Partial<DelimiterMap>> = {
34+
nix: {
35+
singleQuotes: ["''", "''"],
36+
},
37+
38+
lua: {
39+
// FIXME: Add special double square brackets
40+
// see https://github.com/cursorless-dev/cursorless/pull/2012#issuecomment-1808214409
41+
// see also https://github.com/cursorless-dev/cursorless/issues/1812#issuecomment-1691493746
42+
doubleQuotes: [
43+
['"', "[["],
44+
['"', "]]"],
45+
],
46+
},
47+
};
48+
2949
export const leftToRightMap: Record<string, string> = Object.fromEntries(
3050
Object.values(delimiterToText),
3151
);
@@ -47,3 +67,35 @@ export const complexDelimiterMap: Record<
4767
"angleBrackets",
4868
],
4969
};
70+
71+
/**
72+
* Given a language id, returns a list of all possible delimiters for that
73+
* language.
74+
*
75+
* Allows us to support languages where the parse tree gives type names to nodes
76+
* that don't correspond to the actual delimiter.
77+
*
78+
* Note that we pass in `undefined` if we are in a text fragment, because then
79+
* we won't be using a parse tree.
80+
*
81+
* FIXME: Probably remove these as part of
82+
* https://github.com/cursorless-dev/cursorless/issues/1812#issuecomment-1691493746
83+
*
84+
* @param languageId The language id, or `undefined` if in a text fragment
85+
* @returns A list of all possible delimiters for that language
86+
*/
87+
export function getSimpleDelimiterMap(
88+
languageId: string | undefined,
89+
): Record<
90+
SimpleSurroundingPairName,
91+
[IndividualDelimiterText, IndividualDelimiterText]
92+
> {
93+
if (languageId != null && languageId in delimiterToTextOverrides) {
94+
return {
95+
...delimiterToText,
96+
...delimiterToTextOverrides[languageId],
97+
};
98+
}
99+
100+
return delimiterToText;
101+
}

packages/cursorless-engine/src/processTargets/modifiers/surroundingPair/findSurroundingPairParseTreeBased.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ export function findSurroundingPairParseTreeBased(
6666
) {
6767
const document: TextDocument = editor.document;
6868

69-
const individualDelimiters = getIndividualDelimiters(delimiters);
69+
const individualDelimiters = getIndividualDelimiters(
70+
document.languageId,
71+
delimiters,
72+
);
7073

7174
const delimiterTextToDelimiterInfoMap = Object.fromEntries(
7275
individualDelimiters.map((individualDelimiter) => [

packages/cursorless-engine/src/processTargets/modifiers/surroundingPair/findSurroundingPairTextBased.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export function findSurroundingPairTextBased(
7474
const document: TextDocument = editor.document;
7575
const fullRange = allowableRange ?? document.range;
7676

77-
const individualDelimiters = getIndividualDelimiters(delimiters);
77+
const individualDelimiters = getIndividualDelimiters(undefined, delimiters);
7878

7979
const delimiterTextToDelimiterInfoMap = Object.fromEntries(
8080
individualDelimiters.map((individualDelimiter) => [

packages/cursorless-engine/src/processTargets/modifiers/surroundingPair/getIndividualDelimiters.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { SimpleSurroundingPairName, isString } from "@cursorless/common";
22
import { IndividualDelimiter } from "./types";
3-
import { delimiterToText } from "./delimiterMaps";
3+
import { getSimpleDelimiterMap } from "./delimiterMaps";
44
import { concat, uniq } from "lodash";
55

66
/**
77
* Given a list of delimiters, returns a list where each element corresponds to
88
* a single right or left delimiter. Each item contains information such as a
99
* reference to delimiter name, the text to expect, etc.
1010
*
11+
* @param languageId The language id, or `undefined` if in a text fragment
1112
* @param delimiters The delimiter names
12-
* @returns A list of information about all possible left / right delimiter instances
13+
* @returns A list of information about all possible left / right delimiter
14+
* instances
1315
*/
1416
export function getIndividualDelimiters(
17+
languageId: string | undefined,
1518
delimiters: SimpleSurroundingPairName[],
1619
): IndividualDelimiter[] {
20+
const delimiterToText = getSimpleDelimiterMap(languageId);
1721
return delimiters.flatMap((delimiter) => {
1822
const [leftDelimiter, rightDelimiter] = delimiterToText[delimiter];
1923

0 commit comments

Comments
 (0)