Skip to content

Commit e7ff14e

Browse files
committed
WIP: add Triggerkey to snippets
implements [#439](https://github.com/superle3/obsidian-latex-suite/issues/439)
1 parent a57199b commit e7ff14e

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

src/features/run_snippets.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,17 @@ const runSnippetCursor = (view: EditorView, ctx: Context, key: string, range: Se
4343
continue;
4444
}
4545

46-
if (snippet.options.automatic || snippet.type === "visual") {
46+
if (
47+
snippet.options.automatic ||
48+
(snippet.type === "visual" && !snippet.triggerKey)
49+
) {
4750
// If the key pressed wasn't a text character, continue
4851
if (!(key.length === 1)) continue;
4952
effectiveLine = updatedLine;
50-
}
51-
else if (!(key === settings.snippetsTrigger)) {
53+
} else if (
54+
!(key === settings.snippetsTrigger && !snippet.triggerKey) &&
55+
snippet.triggerKey !== key
56+
) {
5257
// The snippet must be triggered by a key
5358
continue;
5459
}
@@ -82,7 +87,8 @@ const runSnippetCursor = (view: EditorView, ctx: Context, key: string, range: Se
8287

8388
// Expand the snippet
8489
const start = triggerPos;
85-
queueSnippet(view, start, to, replacement, key);
90+
const triggerKey = (snippet.options.automatic && snippet.type !== "visual") ? key : undefined;
91+
queueSnippet(view, start, to, replacement, triggerKey);
8692

8793
const containsTrigger = settings.autoEnlargeBracketsTriggers.some(word => replacement.contains("\\" + word));
8894
return {success: true, shouldAutoEnlargeBrackets: containsTrigger};
@@ -148,4 +154,4 @@ const trimWhitespace = (replacement: string, ctx: Context) => {
148154
}
149155

150156
return replacement;
151-
}
157+
}

src/latex_suite.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { handleUndoRedo } from "./snippets/codemirror/history";
1616
import { handleMathTooltip } from "./editor_extensions/math_tooltip";
1717
import { isComposing } from "./utils/editor_utils";
1818
import { LatexSuiteCMSettings } from "./settings/settings";
19+
import { Snippet } from "./snippets/snippets";
1920

2021
export const handleUpdate = (update: ViewUpdate) => {
2122
const settings = getLatexSuiteConfig(update.state);
@@ -123,8 +124,9 @@ export const handleKeydown = (key: string, shiftKey: boolean, ctrlKey: boolean,
123124

124125

125126
export function getKeymaps(settings: LatexSuiteCMSettings): readonly KeyBinding[] {
126-
const keybindings: KeyBinding[] = [];
127-
if (settings.autoDelete$){
127+
// order matters, keybindings should be added in the order they should be triggered
128+
const keybindings: KeyBinding[] = [];
129+
if (settings.autoDelete$) {
128130
/*
129131
* When backspace is pressed, if the cursor is inside an empty inline math,
130132
* delete both $ symbols, not just the first one.
@@ -148,20 +150,40 @@ export function getKeymaps(settings: LatexSuiteCMSettings): readonly KeyBinding[
148150
}
149151

150152
if (settings.snippetsEnabled) {
151-
keybindings.push(
152-
{key: settings.snippetsTrigger, run: (view: EditorView) => {
153-
console.debug("Snippets extension", view.composing, view.compositionStarted);
154-
if (settings.suppressSnippetTriggerOnIME && view.composing) return;
153+
const snippet_triggers = new Set(
154+
settings.snippets.map((s) => s.triggerKey).filter((s) => s)
155+
);
156+
snippet_triggers.add(settings.snippetsTrigger);
157+
const runMaker = (key: string) => {
158+
console.debug("triggerkeys:", key)
159+
return (view: EditorView) => {
160+
console.debug(
161+
"Snippets extension",
162+
view.composing,
163+
view.compositionStarted
164+
);
165+
if (settings.suppressSnippetTriggerOnIME && view.composing)
166+
return;
155167
try {
156-
const ctx = Context.fromView(view)
157-
return runSnippets(view, ctx, settings.snippetsTrigger)
168+
const ctx = Context.fromView(view);
169+
return runSnippets(view, ctx, key);
158170
} catch (e) {
159-
clearSnippetQueue(view)
160-
console.error(e)
161-
return false
171+
clearSnippetQueue(view);
172+
console.error(e);
173+
return false;
162174
}
163-
}}
164-
)
175+
};
176+
};
177+
178+
179+
keybindings.push(
180+
...Array.from(snippet_triggers, (key) => {
181+
return {
182+
key,
183+
run: runMaker(key),
184+
};
185+
})
186+
);
165187
}
166188

167189
keybindings.push(
@@ -221,6 +243,7 @@ export function getKeymaps(settings: LatexSuiteCMSettings): readonly KeyBinding[
221243
})
222244
)
223245
}
246+
224247
keybindings.map((keybinding) => {
225248
keybinding.scope = "latex-suite"
226249
})

src/snippets/parse.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const RawSnippetSchema = object({
108108
flags: optional(string_()),
109109
priority: optional(number()),
110110
description: optional(string_()),
111+
triggerKey: optional(string_()),
111112
});
112113

113114
type RawSnippet = Output<typeof RawSnippetSchema>;
@@ -135,7 +136,7 @@ function validateRawSnippets(snippets: unknown): RawSnippet[] {
135136
* - if it is a regex snippet, the trigger is represented as a RegExp instance with flags set
136137
*/
137138
function parseSnippet(raw: RawSnippet, snippetVariables: SnippetVariables): Snippet {
138-
const { replacement, priority, description } = raw;
139+
const { replacement, priority, description, triggerKey } = raw;
139140
const options = Options.fromSource(raw.options);
140141
let trigger;
141142
let excludedEnvironments;
@@ -172,7 +173,7 @@ function parseSnippet(raw: RawSnippet, snippetVariables: SnippetVariables): Snip
172173

173174
options.regex = true;
174175

175-
const normalised = { trigger, replacement, options, priority, description, excludedEnvironments };
176+
const normalised = { trigger, replacement, options, priority, description, excludedEnvironments, triggerKey };
176177

177178
return new RegexSnippet(normalised);
178179
}
@@ -189,7 +190,7 @@ function parseSnippet(raw: RawSnippet, snippetVariables: SnippetVariables): Snip
189190
options.visual = true;
190191
}
191192

192-
const normalised = { trigger, replacement, options, priority, description, excludedEnvironments };
193+
const normalised = { trigger, replacement, options, priority, description, excludedEnvironments, triggerKey };
193194

194195
if (options.visual) {
195196
return new VisualSnippet(normalised);

src/snippets/snippets.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export abstract class Snippet<T extends SnippetType = SnippetType> {
5454
options: Options;
5555
priority?: number;
5656
description?: string;
57+
triggerKey: string | null;
5758

5859
excludedEnvironments: Environment[];
5960

@@ -65,6 +66,7 @@ export abstract class Snippet<T extends SnippetType = SnippetType> {
6566
priority?: number | undefined,
6667
description?: string | undefined,
6768
excludedEnvironments?: Environment[],
69+
triggerKey?: string,
6870
) {
6971
this.type = type;
7072
// @ts-ignore
@@ -73,6 +75,7 @@ export abstract class Snippet<T extends SnippetType = SnippetType> {
7375
this.priority = priority;
7476
this.description = description;
7577
this.excludedEnvironments = excludedEnvironments ?? [];
78+
this.triggerKey = triggerKey ?? null;
7679
}
7780

7881
// we need to explicitly type the return value here so the derived classes,
@@ -96,8 +99,8 @@ export abstract class Snippet<T extends SnippetType = SnippetType> {
9699
}
97100

98101
export class VisualSnippet extends Snippet<"visual"> {
99-
constructor({ trigger, replacement, options, priority, description, excludedEnvironments }: CreateSnippet<"visual">) {
100-
super("visual", trigger, replacement, options, priority, description, excludedEnvironments);
102+
constructor({ trigger, replacement, options, priority, description, excludedEnvironments, triggerKey }: CreateSnippet<"visual">) {
103+
super("visual", trigger, replacement, options, priority, description, excludedEnvironments, triggerKey);
101104
}
102105

103106
process(effectiveLine: string, range: SelectionRange, sel: string): ProcessSnippetResult {
@@ -126,8 +129,8 @@ export class VisualSnippet extends Snippet<"visual"> {
126129

127130
export class RegexSnippet extends Snippet<"regex"> {
128131

129-
constructor({ trigger, replacement, options, priority, description, excludedEnvironments }: CreateSnippet<"regex">) {
130-
super("regex", trigger, replacement, options, priority, description, excludedEnvironments);
132+
constructor({ trigger, replacement, options, priority, description, excludedEnvironments , triggerKey}: CreateSnippet<"regex">) {
133+
super("regex", trigger, replacement, options, priority, description, excludedEnvironments, triggerKey);
131134
}
132135

133136
process(effectiveLine: string, range: SelectionRange, sel: string): ProcessSnippetResult {
@@ -167,8 +170,8 @@ export class RegexSnippet extends Snippet<"regex"> {
167170
export class StringSnippet extends Snippet<"string"> {
168171
data: SnippetData<"string">;
169172

170-
constructor({ trigger, replacement, options, priority, description, excludedEnvironments: excludeIn }: CreateSnippet<"string">) {
171-
super("string", trigger, replacement, options, priority, description, excludeIn);
173+
constructor({ trigger, replacement, options, priority, description, excludedEnvironments: excludeIn, triggerKey }: CreateSnippet<"string">) {
174+
super("string", trigger, replacement, options, priority, description, excludeIn, triggerKey);
172175
}
173176

174177
process(effectiveLine: string, range: SelectionRange, sel: string): ProcessSnippetResult {
@@ -209,6 +212,7 @@ type CreateSnippet<T extends SnippetType> = {
209212
priority?: number;
210213
description?: string;
211214
excludedEnvironments?: Environment[];
215+
triggerKey?: string;
212216
} & SnippetData<T>
213217

214218

@@ -217,4 +221,4 @@ type CreateSnippet<T extends SnippetType> = {
217221
*/
218222
export function serializeSnippetLike(snippetLike: unknown) {
219223
return JSON.stringify(snippetLike, replacer, 2);
220-
}
224+
}

0 commit comments

Comments
 (0)