Skip to content

Commit 471a262

Browse files
Fix some styling bugs
1 parent 651f546 commit 471a262

13 files changed

Lines changed: 152 additions & 128 deletions

out/lib.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

out/snippetFormatter.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

out/talonFormatter.js

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

out/treeSitterFormatter.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

out/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export interface SyntaxNode {
5454
type: string;
5555
startPosition: Point;
5656
endPosition: Point;
57+
parent: SyntaxNode | null;
5758
children: SyntaxNode[];
5859
}
5960
export {};

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cursorless/talon-tools",
3-
"version": "0.1.10",
3+
"version": "0.2.0",
44
"description": "Linting and formatting tools for Talon and Cursorless",
55
"author": "Cursorless Dev",
66
"license": "MIT",

src/talon/talonFormatter.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,20 @@ class TalonFormatter {
112112
return `${nl}${text}`;
113113
}
114114

115-
private pairWithChildren(node: SyntaxNode) {
115+
private pairWithChildren(
116+
node: SyntaxNode,
117+
unwrap: boolean = false,
118+
): string {
116119
const { children } = node;
117-
const pre = children[0].text;
118-
const post = children[children.length - 1].text;
119120
const middle = children
120121
.slice(1, -1)
121122
.map((n) => this.getNodeText(n))
122123
.join(" ");
124+
if (unwrap) {
125+
return middle;
126+
}
127+
const pre = children[0].text;
128+
const post = children[children.length - 1].text;
123129
return `${pre}${middle}${post}`;
124130
}
125131

@@ -133,7 +139,7 @@ class TalonFormatter {
133139

134140
case "matches": {
135141
// There are no match nodes and there is no comment before
136-
if (node.children.length < 2 && this.lastRow === 0) {
142+
if (node.children.length < 2 && isFirstChild(node)) {
137143
return "";
138144
}
139145
return node.children
@@ -205,6 +211,11 @@ class TalonFormatter {
205211
return node.text.trim();
206212

207213
case "parenthesized_rule":
214+
return this.pairWithChildren(
215+
node,
216+
node.parent != null && rangeEqual(node, node.parent),
217+
);
218+
208219
case "optional":
209220
return this.pairWithChildren(node);
210221

@@ -254,3 +265,16 @@ function isLeftRightSingleLine(
254265
): boolean {
255266
return left.endPosition.row === rights[rights.length - 1].startPosition.row;
256267
}
268+
269+
function rangeEqual(a: SyntaxNode, b: SyntaxNode): boolean {
270+
return (
271+
a.startPosition.row === b.startPosition.row &&
272+
a.startPosition.column === b.startPosition.column &&
273+
a.endPosition.row === b.endPosition.row &&
274+
a.endPosition.column === b.endPosition.column
275+
);
276+
}
277+
278+
function isFirstChild(node: SyntaxNode): boolean {
279+
return node.parent?.children.findIndex((n) => n.id === node.id) === 0;
280+
}

src/test/snippetFormatter.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as assert from "node:assert";
22
import { snippetFormatter } from "../snippet/snippetFormatter.js";
3-
4-
type Content = string | string[];
3+
import type { Content } from "./testUtils.js";
4+
import { getContentString } from "./testUtils.js";
55

66
const fixtures: {
77
title: string;
@@ -132,7 +132,3 @@ suite("Snippet formatter", () => {
132132
});
133133
}
134134
});
135-
136-
function getContentString(content: Content): string {
137-
return Array.isArray(content) ? content.join("\n") : content;
138-
}

src/test/talonFormatter.test.ts

Lines changed: 51 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,57 @@
11
import * as assert from "node:assert";
22
import { talonFormatter } from "../talon/talonFormatter.js";
3-
import type { SyntaxNode } from "../types.js";
43
import { parseText } from "../util/parseText.js";
5-
6-
type Content = string | string[];
7-
8-
const fixtures: { title: string; pre: Content; post: Content }[] = [
4+
import type { Content } from "./testUtils.js";
5+
import {
6+
captureStreamWrite,
7+
createNode,
8+
getContentString,
9+
} from "./testUtils.js";
10+
11+
const fixtures: {
12+
title: string;
13+
columnWidth?: number;
14+
pre: Content;
15+
post: Content;
16+
}[] = [
917
{
10-
title: "matchers",
18+
title: "Matchers",
1119
pre: ["app : vscode", "", "and not mode : command", "-", ""],
1220
post: ["app: vscode", "", "and not mode: command", "-", ""],
1321
},
1422

1523
{
16-
title: "command singe line",
24+
title: "Command single line",
1725
pre: "foo : edit.left( )",
18-
post: ["foo: edit.left()", ""],
26+
post: ["foo: edit.left()", ""],
27+
},
28+
29+
{
30+
title: "Empty header",
31+
pre: "\n-\na:b",
32+
post: "a: b\n",
1933
},
2034

2135
{
22-
title: "command multi line",
36+
title: "Pipe padding",
37+
pre: "a|b:c",
38+
post: "a | b: c\n",
39+
},
40+
41+
{
42+
title: "Unnecessary parentheses",
43+
pre: "(a):b",
44+
post: "a: b\n",
45+
},
46+
47+
{
48+
title: "Comment before divider",
49+
pre: "# a\n-\nb: c",
50+
post: "# a\n-\nb: c\n",
51+
},
52+
53+
{
54+
title: "Command multi line",
2355
pre: [
2456
"foo : ",
2557
" # actions",
@@ -40,7 +72,7 @@ const fixtures: { title: string; pre: Content; post: Content }[] = [
4072
},
4173

4274
{
43-
title: "settings declaration",
75+
title: "Settings declaration",
4476
pre: [
4577
"settings() : ",
4678
" speech.timeout = 0.400",
@@ -57,7 +89,7 @@ const fixtures: { title: string; pre: Content; post: Content }[] = [
5789
},
5890

5991
{
60-
title: "tag/key/gamepad/parrot/face declarations",
92+
title: "Tag/key/gamepad/parrot/face declarations",
6193
pre: [
6294
"tag() : user.some_tag",
6395
"key( enter ) : 'key'",
@@ -68,19 +100,19 @@ const fixtures: { title: string; pre: Content; post: Content }[] = [
68100
],
69101
post: [
70102
"tag(): user.some_tag",
71-
"key(enter): 'key'",
72-
"gamepad(north): 'gamepad'",
73-
"parrot(pop): 'parrot'",
74-
"noise(pop): 'noise'",
75-
"face(smile): 'face'",
103+
"key(enter): 'key'",
104+
"gamepad(north): 'gamepad'",
105+
"parrot(pop): 'parrot'",
106+
"noise(pop): 'noise'",
107+
"face(smile): 'face'",
76108
"",
77109
],
78110
},
79111

80112
{
81113
title: "CRLF comment",
82114
pre: "# Hello\r\nfoo: 'bar'",
83-
post: "# Hello\nfoo: 'bar'\n",
115+
post: "# Hello\nfoo: 'bar'\n",
84116
},
85117

86118
{
@@ -97,6 +129,7 @@ const fixtures: { title: string; pre: Content; post: Content }[] = [
97129

98130
{
99131
title: "Large file",
132+
columnWidth: 28,
100133
pre: `\
101134
not mode : command
102135
tag : stuff
@@ -180,19 +213,13 @@ suite("Talon formatter", () => {
180213
const content = getContentString(fixture.pre);
181214
const rootNode = await parseText(content, "tree-sitter-talon");
182215
const actual = talonFormatter(rootNode, {
183-
columnWidth: 28,
216+
columnWidth: fixture.columnWidth,
184217
});
185218
const expected = getContentString(fixture.post);
186219
assert.equal(actual, expected);
187220
});
188221
}
189222

190-
test("comment before divider", async () => {
191-
const rootNode = await parseText("# a\n-\nb: c", "tree-sitter-talon");
192-
const actual = talonFormatter(rootNode);
193-
assert.equal(actual, "# a\n-\nb: c\n");
194-
});
195-
196223
test("endOfLine: CRLF", async () => {
197224
const rootNode = await parseText(
198225
"foo:\n edit.left()",
@@ -276,40 +303,3 @@ suite("Talon formatter", () => {
276303
);
277304
});
278305
});
279-
280-
function getContentString(content: Content): string {
281-
return Array.isArray(content) ? content.join("\n") : content;
282-
}
283-
284-
function createNode(type: string, text: string): SyntaxNode {
285-
return {
286-
id: 1,
287-
type,
288-
text,
289-
startPosition: { row: 0, column: 0 },
290-
endPosition: { row: 0, column: text.length },
291-
children: [],
292-
};
293-
}
294-
295-
async function captureStreamWrite<T>(
296-
stream: NodeJS.WriteStream,
297-
callback: () => Promise<T> | T,
298-
): Promise<{ result: T; text: string }> {
299-
let text = "";
300-
const originalWrite = stream.write.bind(stream);
301-
302-
(stream.write as unknown as (chunk: string) => boolean) = (
303-
chunk: string | Uint8Array,
304-
) => {
305-
text += chunk.toString();
306-
return true;
307-
};
308-
309-
try {
310-
const result = await callback();
311-
return { result, text };
312-
} finally {
313-
stream.write = originalWrite;
314-
}
315-
}

0 commit comments

Comments
 (0)