-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathoption.ts
More file actions
145 lines (134 loc) · 3.78 KB
/
option.ts
File metadata and controls
145 lines (134 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* option.ts
*
* Copyright (C) 2022 by Posit Software, PBC
*
* Unless you have received this program directly from Posit Software pursuant
* to the terms of a commercial license agreement with Posit Software, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
import {
window,
workspace,
ExtensionContext,
Position,
TextEditor,
Range,
} from "vscode";
import { isQuartoDoc } from "../core/doc";
import { MarkdownEngine } from "../markdown/engine";
import { languageBlockAtPosition, languageNameFromBlock } from "quarto-core";
export function activateOptionEnterProvider(
context: ExtensionContext,
engine: MarkdownEngine
) {
workspace.onDidChangeTextDocument(
async (event) => {
if (window.activeTextEditor) {
// if we are in an active quarto doc with an empty selection
const doc = window.activeTextEditor.document;
if (
doc.uri === event.document.uri &&
isQuartoDoc(doc) &&
window.activeTextEditor.selection.isEmpty
) {
// check for enter key within a language block
for (const change of event.contentChanges) {
if (change.text === "\n" || change.text === "\r\n") {
const tokens = engine.parse(doc);
const line = window.activeTextEditor.selection.start.line;
const block = languageBlockAtPosition(
tokens,
new Position(line, 0)
);
if (block) {
const language = languageNameFromBlock(block);
// handle option enter for the this language if we can
const optionComment = languageOptionComment(language);
if (optionComment) {
handleOptionEnter(window.activeTextEditor, optionComment);
}
}
}
}
}
}
},
null,
context.subscriptions
);
}
function handleOptionEnter(editor: TextEditor, comment: string) {
// option comment for this language
const optionComment = comment + "| ";
// current line info
const currentLineNumber = editor.selection.active.line;
const currentLine = editor.document.lineAt(editor.selection.start).text;
// apply edits
if (currentLine.trim() === optionComment.trim()) {
editor.edit((builder) => {
builder.delete(new Range(new Position(currentLineNumber, 0), new Position(currentLineNumber, currentLine.length)));
});
} else if (currentLine.startsWith(optionComment)) {
editor.edit((builder) => {
builder.insert(editor.selection.start.translate(1, -editor.selection.active.character), optionComment);
});
}
}
export function languageOptionComment(language: string) {
// some mappings
if (language === "ojs") {
language = "js";
}
if (Object.keys(kLangCommentChars).includes(language)) {
return kLangCommentChars[language];
} else {
return undefined;
}
}
const kLangCommentChars: Record<string, string> = {
r: "#",
python: "#",
julia: "#",
scala: "//",
matlab: "%",
csharp: "//",
fsharp: "//",
powershell: "#",
bash: "#",
sql: "--",
mysql: "--",
psql: "--",
lua: "--",
cpp: "//",
cc: "//",
stan: "#",
octave: "#",
fortran: "!",
fortran95: "!",
awk: "#",
gawk: "#",
stata: "*",
java: "//",
groovy: "//",
sed: "#",
perl: "#",
ruby: "#",
tikz: "%",
js: "//",
d3: "//",
node: "//",
sass: "//",
coffee: "#",
go: "//",
asy: "//",
haskell: "--",
dot: "//",
mermaid: "%%",
prql: "#",
};