2023-03-15 07:04:06 +00:00
|
|
|
import {
|
|
|
|
|
App,
|
|
|
|
|
Editor,
|
|
|
|
|
EditorPosition,
|
|
|
|
|
MarkdownView,
|
|
|
|
|
Plugin,
|
|
|
|
|
PluginSettingTab,
|
|
|
|
|
Setting,
|
|
|
|
|
} from "obsidian";
|
|
|
|
|
|
2023-10-08 23:54:15 +00:00
|
|
|
import { EditorView } from "@codemirror/view";
|
|
|
|
|
|
2023-10-08 23:55:01 +00:00
|
|
|
import { Symbol } from "src/symbol";
|
2023-10-09 00:26:36 +00:00
|
|
|
import { LHS, RHS, Snippet, SnippetType } from "src/snippet";
|
2023-09-22 07:21:57 +00:00
|
|
|
|
2023-04-14 22:03:44 +00:00
|
|
|
enum AutoTriggerOptions {
|
|
|
|
|
Disabled = "disabled",
|
|
|
|
|
EnabledNoWS = "n-ws",
|
|
|
|
|
EnabledYesWS = "y-ws",
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 09:24:34 +00:00
|
|
|
interface JellySnippetsSettings {
|
2023-08-20 18:12:38 +00:00
|
|
|
snippetsFile: string;
|
2023-04-14 22:03:44 +00:00
|
|
|
triggerOnSpace: AutoTriggerOptions;
|
2023-04-20 09:55:19 +00:00
|
|
|
triggerOnEnter: AutoTriggerOptions;
|
2023-04-14 22:03:44 +00:00
|
|
|
triggerOnTab: AutoTriggerOptions;
|
2023-03-15 07:04:06 +00:00
|
|
|
snippetPartDivider: string;
|
2023-03-15 11:08:03 +00:00
|
|
|
snippetDivider: string;
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-15 09:24:34 +00:00
|
|
|
const DEFAULT_SETTINGS: JellySnippetsSettings = {
|
2023-08-20 18:12:38 +00:00
|
|
|
snippetsFile: String.raw`Snip me! |+| Snippet successfully replaced.
|
2023-03-15 08:50:57 +00:00
|
|
|
-==-
|
|
|
|
|
- |+| #####
|
|
|
|
|
-==-
|
|
|
|
|
: |+| -
|
|
|
|
|
-==-
|
|
|
|
|
:: |+| hi`,
|
2023-04-14 22:03:44 +00:00
|
|
|
triggerOnSpace: AutoTriggerOptions.Disabled,
|
2023-04-20 09:55:19 +00:00
|
|
|
triggerOnEnter: AutoTriggerOptions.Disabled,
|
2023-04-14 22:11:38 +00:00
|
|
|
triggerOnTab: AutoTriggerOptions.Disabled,
|
2023-03-15 07:04:06 +00:00
|
|
|
snippetPartDivider: " |+| ",
|
|
|
|
|
snippetDivider: "-==-",
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-15 11:08:03 +00:00
|
|
|
export default class JellySnippets extends Plugin {
|
2023-03-15 09:24:34 +00:00
|
|
|
settings: JellySnippetsSettings;
|
2023-09-22 07:21:57 +00:00
|
|
|
private multilineSnippets: { [key: LHS]: RHS } = {};
|
2023-03-15 07:04:06 +00:00
|
|
|
|
|
|
|
|
async onload() {
|
|
|
|
|
await this.loadSettings();
|
|
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
// Check settings and load snippets in.
|
|
|
|
|
this.reloadSnippets();
|
2023-04-20 09:55:19 +00:00
|
|
|
|
2023-03-15 21:17:42 +00:00
|
|
|
// If keydown events are set...
|
2023-04-14 22:03:44 +00:00
|
|
|
if (
|
|
|
|
|
this.settings.triggerOnSpace !== AutoTriggerOptions.Disabled ||
|
|
|
|
|
this.settings.triggerOnTab !== AutoTriggerOptions.Disabled ||
|
|
|
|
|
this.settings.triggerOnEnter !== AutoTriggerOptions.Disabled
|
|
|
|
|
) {
|
2023-03-15 21:17:42 +00:00
|
|
|
const onKeyEvent = (evt: KeyboardEvent) => {
|
|
|
|
|
if (
|
2023-04-20 09:55:19 +00:00
|
|
|
!evt.shiftKey // TODO: add function to determine when not to trigger. don't trigger if shift is pressed down as well e.g.
|
2023-03-15 21:17:42 +00:00
|
|
|
) {
|
2023-04-14 20:11:29 +00:00
|
|
|
const mdFile = this.app.workspace.activeEditor;
|
|
|
|
|
if (mdFile?.editor) {
|
2023-08-20 18:12:38 +00:00
|
|
|
this.triggerSnippetAutomatically(mdFile.editor, evt);
|
2023-03-15 21:17:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Register for main window.
|
|
|
|
|
this.registerDomEvent(document, "keydown", onKeyEvent);
|
|
|
|
|
|
|
|
|
|
// If window changes, registerDomEvent for new window if so.
|
2023-04-20 09:55:19 +00:00
|
|
|
this.registerEvent(
|
|
|
|
|
this.app.workspace.on("window-open", (event) => {
|
|
|
|
|
this.registerDomEvent(activeWindow, "keydown", onKeyEvent);
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-04-20 09:55:19 +00:00
|
|
|
);
|
2023-03-15 21:17:42 +00:00
|
|
|
}
|
2023-03-15 07:04:06 +00:00
|
|
|
|
|
|
|
|
this.addCommand({
|
2023-08-20 18:12:38 +00:00
|
|
|
id: "trigger-snippet",
|
|
|
|
|
name: "Trigger snippet",
|
2023-03-15 07:04:06 +00:00
|
|
|
editorCallback: (editor: Editor) => {
|
2023-08-20 18:12:38 +00:00
|
|
|
this.triggerSnippet(editor);
|
2023-03-15 07:04:06 +00:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-15 08:50:57 +00:00
|
|
|
this.addCommand({
|
|
|
|
|
id: "reload-snippets",
|
|
|
|
|
name: "Reload snippets",
|
|
|
|
|
callback: () => {
|
2023-08-20 18:12:38 +00:00
|
|
|
this.reloadSnippets();
|
2023-03-15 08:50:57 +00:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-15 09:24:34 +00:00
|
|
|
this.addSettingTab(new JellySnippetsSettingTab(this.app, this));
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onunload() {}
|
|
|
|
|
|
|
|
|
|
async loadSettings() {
|
2023-06-22 12:21:01 +00:00
|
|
|
this.settings = Object.assign(
|
|
|
|
|
{},
|
|
|
|
|
DEFAULT_SETTINGS,
|
|
|
|
|
await this.loadData()
|
|
|
|
|
);
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async saveSettings() {
|
|
|
|
|
await this.saveData(this.settings);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
reloadSnippets(): void {
|
2023-09-18 06:21:57 +00:00
|
|
|
console.log("Jelly Snippets: Reloading snippets.");
|
2023-08-20 18:12:38 +00:00
|
|
|
this.multilineSnippets = {};
|
|
|
|
|
this.parseSnippets();
|
2023-03-15 08:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
parseSnippets(): void {
|
|
|
|
|
// If they specified newline control character, split snippets by newline.
|
2023-10-08 08:59:25 +00:00
|
|
|
// TODO: Can we make it so that leaving the setting blank is newline separation?
|
2023-06-22 12:26:15 +00:00
|
|
|
let snippetDivider =
|
|
|
|
|
this.settings.snippetDivider == "\\n"
|
|
|
|
|
? "\n"
|
2023-10-08 08:59:25 +00:00
|
|
|
: this.settings.snippetDivider + "\n";
|
2023-06-22 12:26:15 +00:00
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
// go through the snippets file, split by the snippet divider, split by the part divider, put in map
|
|
|
|
|
let snippetLines = this.settings.snippetsFile.split(snippetDivider);
|
2023-09-22 07:21:57 +00:00
|
|
|
for (let snippet of snippetLines) {
|
2023-09-22 02:36:04 +00:00
|
|
|
// Trim newlines. Instead, use symbols to let people insert whitespace.
|
2023-09-22 07:43:17 +00:00
|
|
|
// This split means only the first division of the part divider is the LHS.
|
2023-09-22 02:36:04 +00:00
|
|
|
let snippetParts = snippet
|
2023-10-08 08:59:25 +00:00
|
|
|
.trimEnd()
|
2023-09-22 02:36:04 +00:00
|
|
|
.split(this.settings.snippetPartDivider);
|
2023-09-22 07:21:57 +00:00
|
|
|
if (snippetParts.length !== 2) {
|
2023-09-22 07:43:17 +00:00
|
|
|
// probably an incomplete snippet
|
|
|
|
|
continue;
|
2023-09-22 07:21:57 +00:00
|
|
|
}
|
|
|
|
|
// Produce lhs. Continue if undefined.
|
2023-04-20 09:55:19 +00:00
|
|
|
let lhs = snippetParts.shift();
|
2023-04-13 10:56:07 +00:00
|
|
|
if (lhs === undefined) {
|
2023-08-20 18:12:38 +00:00
|
|
|
console.log("Failed to register snippet: ", snippet);
|
2023-09-22 07:21:57 +00:00
|
|
|
continue;
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
2023-09-22 07:21:57 +00:00
|
|
|
// Produce rhs (raw data).
|
2023-09-22 07:43:17 +00:00
|
|
|
// * This is a join in case they used their snippetPartDivider too many times.
|
|
|
|
|
let rhsData = snippetParts.join(this.settings.snippetPartDivider);
|
2023-09-22 07:21:57 +00:00
|
|
|
// Scan rhs for symbols and perform the replacements; acquire RHS.
|
|
|
|
|
let rhs = Symbol.replaceSymbolsOnParse(rhsData);
|
|
|
|
|
this.multilineSnippets[lhs] = rhs;
|
|
|
|
|
}
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-22 07:21:57 +00:00
|
|
|
triggerSnippet(editor: Editor, pos?: EditorPosition): Snippet | undefined {
|
2023-08-20 18:12:38 +00:00
|
|
|
let curpos = pos ? pos : editor.getCursor();
|
|
|
|
|
return this.triggerMultilineSnippet(editor, curpos);
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
triggerSnippetAutomatically(editor: Editor, evt: KeyboardEvent) {
|
2023-04-20 09:55:19 +00:00
|
|
|
// remember the order: enter and tab come out before code triggers, space comes out after.
|
2023-04-13 21:07:13 +00:00
|
|
|
switch (evt.key) {
|
|
|
|
|
case " ": {
|
2023-06-22 12:21:01 +00:00
|
|
|
if (
|
|
|
|
|
this.settings.triggerOnSpace !== AutoTriggerOptions.Disabled
|
|
|
|
|
) {
|
2023-08-20 18:12:38 +00:00
|
|
|
if (this.triggerSnippet(editor)) {
|
2023-04-20 09:55:19 +00:00
|
|
|
// Currently impossible to undo the space because the entire snippet
|
|
|
|
|
// and all this code triggers before the space actually happens.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-13 21:07:13 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "Tab": {
|
2023-06-22 12:21:01 +00:00
|
|
|
if (
|
2023-08-20 18:12:38 +00:00
|
|
|
this.settings.triggerOnTab === AutoTriggerOptions.Disabled
|
2023-06-22 12:21:01 +00:00
|
|
|
) {
|
2023-08-20 18:12:38 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
editor.exec("indentLess");
|
|
|
|
|
let maybeSnippet = this.triggerSnippet(editor);
|
|
|
|
|
if (maybeSnippet) {
|
|
|
|
|
if (
|
|
|
|
|
this.settings.triggerOnTab ===
|
|
|
|
|
AutoTriggerOptions.EnabledYesWS
|
|
|
|
|
) {
|
2023-06-22 12:21:01 +00:00
|
|
|
if (
|
2023-08-20 18:12:38 +00:00
|
|
|
this.getSnippetType(maybeSnippet) ===
|
|
|
|
|
SnippetType.SLSR
|
2023-06-22 12:21:01 +00:00
|
|
|
) {
|
2023-08-20 18:12:38 +00:00
|
|
|
editor.exec("indentMore");
|
2023-04-14 22:03:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-20 18:12:38 +00:00
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// If no snippet was triggered, restore the user's indent!
|
|
|
|
|
editor.exec("indentMore");
|
2023-04-14 22:03:44 +00:00
|
|
|
}
|
2023-04-13 21:07:13 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "Enter": {
|
2023-06-22 12:21:01 +00:00
|
|
|
if (
|
2023-08-20 18:12:38 +00:00
|
|
|
this.settings.triggerOnEnter === AutoTriggerOptions.Disabled
|
2023-06-22 12:21:01 +00:00
|
|
|
) {
|
2023-08-20 18:12:38 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2023-09-23 21:47:52 +00:00
|
|
|
// Since the newline comes out first, we need to find our old position before newline (peekPos).
|
2023-08-20 18:12:38 +00:00
|
|
|
let curpos = editor.getCursor();
|
|
|
|
|
let aboveline = curpos.line - 1;
|
|
|
|
|
let abovelineEnd = editor.getLine(aboveline).length;
|
|
|
|
|
let peekPos: EditorPosition = {
|
|
|
|
|
line: aboveline,
|
|
|
|
|
ch: abovelineEnd,
|
|
|
|
|
};
|
2023-09-23 21:47:52 +00:00
|
|
|
// Try to trigger the snippet at the old position.
|
2023-08-20 18:12:38 +00:00
|
|
|
let maybeSnippet = this.triggerSnippet(editor, peekPos);
|
2023-09-23 21:47:52 +00:00
|
|
|
|
|
|
|
|
// If the snippet triggered, clean up the newline.
|
2023-08-20 18:12:38 +00:00
|
|
|
if (maybeSnippet) {
|
2023-09-23 21:47:52 +00:00
|
|
|
// delete newline at the end of snippet
|
|
|
|
|
let curpos = editor.getCursor();
|
|
|
|
|
let curoffset = editor.posToOffset(curpos);
|
|
|
|
|
// get end of replacement part
|
|
|
|
|
let rhsEndOffset =
|
|
|
|
|
curoffset + maybeSnippet.rhs.info.cursorEnd;
|
|
|
|
|
let rhsEndPos = editor.offsetToPos(rhsEndOffset);
|
|
|
|
|
// the line after that (works at document end)
|
|
|
|
|
let afterSnippetLinePos = {
|
|
|
|
|
line: rhsEndPos.line + 1,
|
|
|
|
|
ch: 0,
|
|
|
|
|
};
|
|
|
|
|
editor.replaceRange("", rhsEndPos, afterSnippetLinePos);
|
|
|
|
|
|
|
|
|
|
// If they want the newline added where the cursor is at (works weird for cursorEnd snippets but eh)
|
|
|
|
|
// TODO: maybe make another setting where add newline on enter is disabled if snippet has a cursorEnd?
|
2023-08-20 18:12:38 +00:00
|
|
|
if (
|
|
|
|
|
this.settings.triggerOnEnter ===
|
2023-09-23 21:47:52 +00:00
|
|
|
AutoTriggerOptions.EnabledYesWS
|
2023-08-20 18:12:38 +00:00
|
|
|
) {
|
2023-09-23 21:47:52 +00:00
|
|
|
// Insert newline where we are at.
|
|
|
|
|
editor.exec("newlineAndIndent");
|
|
|
|
|
curpos = editor.getCursor();
|
|
|
|
|
// To "de-indent", delete until start of line.
|
|
|
|
|
editor.replaceRange(
|
|
|
|
|
"",
|
|
|
|
|
{
|
2023-09-23 03:38:05 +00:00
|
|
|
line: curpos.line,
|
2023-08-20 18:12:38 +00:00
|
|
|
ch: 0,
|
2023-09-23 21:47:52 +00:00
|
|
|
},
|
|
|
|
|
curpos
|
|
|
|
|
);
|
2023-04-14 21:57:38 +00:00
|
|
|
}
|
2023-08-20 18:12:38 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// Didn't trigger; move the cursor back down
|
|
|
|
|
editor.setCursor(curpos);
|
2023-04-20 09:55:19 +00:00
|
|
|
}
|
2023-08-20 18:12:38 +00:00
|
|
|
break;
|
2023-04-13 21:07:13 +00:00
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-20 09:55:19 +00:00
|
|
|
return false;
|
2023-04-13 21:07:13 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
triggerMultilineSnippet(
|
2023-04-20 09:55:19 +00:00
|
|
|
editor: Editor,
|
2023-08-20 18:12:38 +00:00
|
|
|
pos?: EditorPosition
|
2023-09-22 07:21:57 +00:00
|
|
|
): Snippet | undefined {
|
2023-08-20 18:12:38 +00:00
|
|
|
const curpos = pos ? pos : editor.getCursor();
|
2023-10-08 23:54:15 +00:00
|
|
|
const curoffset = editor.posToOffset(curpos);
|
|
|
|
|
|
|
|
|
|
// @ts-expect-error
|
|
|
|
|
const view = editor.cm as EditorView;
|
2023-08-20 18:12:38 +00:00
|
|
|
|
|
|
|
|
for (let [lhs, rhs] of Object.entries(this.multilineSnippets)) {
|
2023-10-08 23:54:15 +00:00
|
|
|
const from = curoffset - lhs.length;
|
|
|
|
|
const to = curoffset;
|
|
|
|
|
|
|
|
|
|
// Get the text just before the cursor
|
|
|
|
|
let selected = view.state.sliceDoc(from, to);
|
2023-08-19 13:16:32 +00:00
|
|
|
|
2023-08-20 18:12:38 +00:00
|
|
|
if (lhs === selected) {
|
2023-10-08 23:54:15 +00:00
|
|
|
// Dispatch the replacement and move the cursor to where it should be.
|
|
|
|
|
view.dispatch({
|
|
|
|
|
changes: [
|
|
|
|
|
{
|
|
|
|
|
from,
|
|
|
|
|
to,
|
|
|
|
|
insert: rhs.data,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
selection: {
|
|
|
|
|
anchor: from + rhs.data.length - rhs.info.cursorEnd,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Return what you replaced.
|
2023-09-22 07:21:57 +00:00
|
|
|
return { lhs, rhs };
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
2023-08-20 18:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-23 21:46:42 +00:00
|
|
|
// No replace - return undefined
|
2023-08-20 18:12:38 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Motivation:
|
|
|
|
|
// Single snippets (no newlines) and multi snippets (newlines)
|
|
|
|
|
// have different, weird interaction with Obsidian. Sometimes the whitespace goes through, sometimes not.
|
|
|
|
|
// There needs to be a way of determining what type (mlhs->srhs? mlhs->mrhs? slhs? srhs? etc.) a snippet is.
|
2023-09-22 07:21:57 +00:00
|
|
|
getSnippetType(snippet: Snippet): SnippetType {
|
|
|
|
|
let { lhs, rhs } = snippet;
|
2023-08-20 18:12:38 +00:00
|
|
|
let type = SnippetType.SLSR;
|
|
|
|
|
// Compiler doesn't complain if we convert boolean to number with unary '+'.
|
2023-09-23 18:10:58 +00:00
|
|
|
type |= +lhs.includes("\n") ? SnippetType.MLSR : 0;
|
|
|
|
|
type |= +rhs.info.hasNewline ? SnippetType.SLMR : 0;
|
2023-08-20 18:12:38 +00:00
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selectBackN(editor: Editor, N: number, pos?: EditorPosition): boolean {
|
|
|
|
|
const curpos = pos ? pos : editor.getCursor();
|
|
|
|
|
|
|
|
|
|
// pos -> offset; offset - N; offsetToPos; select offsets
|
|
|
|
|
let endOffset = editor.posToOffset(curpos);
|
|
|
|
|
let startOffset = endOffset - N;
|
|
|
|
|
|
|
|
|
|
// If we can't select back N because we are too close to the start:
|
|
|
|
|
if (startOffset < 0) {
|
2023-08-19 13:16:32 +00:00
|
|
|
return false;
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
2023-08-20 18:12:38 +00:00
|
|
|
|
|
|
|
|
// * In selection terms, anchor is where you first click and head is where you drag to.
|
|
|
|
|
// Try to keep head at the end position and anchor at the start.
|
|
|
|
|
let startPos = editor.offsetToPos(startOffset);
|
|
|
|
|
let endPos = editor.offsetToPos(endOffset);
|
|
|
|
|
editor.setSelection(startPos, endPos);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unselect(editor: Editor, pos?: EditorPosition) {
|
|
|
|
|
if (pos) editor.setSelection(pos, pos);
|
|
|
|
|
else editor.setSelection(editor.getCursor(), editor.getCursor());
|
2023-03-15 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 09:24:34 +00:00
|
|
|
class JellySnippetsSettingTab extends PluginSettingTab {
|
2023-03-15 11:08:03 +00:00
|
|
|
plugin: JellySnippets;
|
2023-03-15 07:04:06 +00:00
|
|
|
|
2023-03-15 11:08:03 +00:00
|
|
|
constructor(app: App, plugin: JellySnippets) {
|
2023-03-15 07:04:06 +00:00
|
|
|
super(app, plugin);
|
|
|
|
|
this.plugin = plugin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
display(): void {
|
|
|
|
|
const { containerEl } = this;
|
|
|
|
|
|
|
|
|
|
containerEl.empty();
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
let childEl = containerEl.createDiv({ cls: "jelly_snippets" });
|
2023-06-22 12:21:01 +00:00
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
childEl.createEl("h2", { text: "Jelly Snippets - Settings" });
|
2023-03-15 07:04:06 +00:00
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-08-20 18:12:38 +00:00
|
|
|
.setName("Snippets")
|
2023-03-15 08:50:57 +00:00
|
|
|
.setDesc(
|
2023-08-20 18:12:38 +00:00
|
|
|
"Specify your snippets here! Format: 'before<divider>after'. Surrounding your divider with a space is recommended for readability."
|
2023-03-15 08:50:57 +00:00
|
|
|
)
|
|
|
|
|
.addTextArea((textarea) =>
|
|
|
|
|
textarea
|
|
|
|
|
.setPlaceholder(
|
2023-06-22 12:21:01 +00:00
|
|
|
`before${this.plugin.settings.snippetPartDivider}after`
|
2023-03-15 08:50:57 +00:00
|
|
|
)
|
2023-08-20 18:12:38 +00:00
|
|
|
.setValue(this.plugin.settings.snippetsFile)
|
2023-03-15 08:50:57 +00:00
|
|
|
.onChange(async (value) => {
|
2023-08-20 18:12:38 +00:00
|
|
|
this.plugin.settings.snippetsFile = value;
|
2023-03-15 08:50:57 +00:00
|
|
|
await this.plugin.saveSettings();
|
2023-08-20 18:12:38 +00:00
|
|
|
this.plugin.reloadSnippets(); // ? is this necessary to update the snippets?
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-03-15 08:50:57 +00:00
|
|
|
);
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-03-15 08:50:57 +00:00
|
|
|
.setName("Snippet line divider")
|
2023-06-22 12:21:01 +00:00
|
|
|
.setDesc(
|
2023-06-22 12:26:15 +00:00
|
|
|
"This string will divide each separate snippet definition. (Enter the two characters '\\n' to use newlines as your separator.)"
|
2023-06-22 12:21:01 +00:00
|
|
|
)
|
2023-03-15 08:50:57 +00:00
|
|
|
.addText((text) =>
|
|
|
|
|
text
|
|
|
|
|
.setPlaceholder("-==-")
|
|
|
|
|
.setValue(this.plugin.settings.snippetDivider)
|
|
|
|
|
.onChange(async (value) => {
|
2023-03-15 10:30:52 +00:00
|
|
|
this.plugin.settings.snippetDivider = value;
|
2023-03-15 08:50:57 +00:00
|
|
|
await this.plugin.saveSettings();
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-03-15 08:50:57 +00:00
|
|
|
);
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-03-15 08:50:57 +00:00
|
|
|
.setName("Snippet part divider")
|
|
|
|
|
.setDesc(
|
2023-06-22 12:21:01 +00:00
|
|
|
"This string will divide the lhs and rhs of a snippet definition. (I recommend putting spaces in the ends of this string.)"
|
2023-03-15 08:50:57 +00:00
|
|
|
)
|
|
|
|
|
.addText((text) =>
|
|
|
|
|
text
|
|
|
|
|
.setPlaceholder(" |+| ")
|
|
|
|
|
.setValue(this.plugin.settings.snippetPartDivider)
|
|
|
|
|
.onChange(async (value) => {
|
|
|
|
|
this.plugin.settings.snippetPartDivider = value;
|
|
|
|
|
await this.plugin.saveSettings();
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-03-15 08:50:57 +00:00
|
|
|
);
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-03-15 07:04:06 +00:00
|
|
|
.setName("Trigger on Space")
|
|
|
|
|
.setDesc(
|
2023-06-22 12:21:01 +00:00
|
|
|
"If enabled, the snippet function will trigger when space is pressed (but not while shift is held)."
|
2023-03-15 07:04:06 +00:00
|
|
|
)
|
2023-04-14 22:03:44 +00:00
|
|
|
.addDropdown((dropdown) =>
|
|
|
|
|
dropdown
|
|
|
|
|
.addOption(AutoTriggerOptions.Disabled, "Disabled")
|
|
|
|
|
// .addOption(AutoTriggerOptions.EnabledNoWS, "Enabled, no whitespace")
|
2023-04-20 09:55:19 +00:00
|
|
|
.addOption(
|
|
|
|
|
AutoTriggerOptions.EnabledYesWS,
|
2023-08-20 18:12:38 +00:00
|
|
|
"Enabled, also space"
|
2023-04-20 09:55:19 +00:00
|
|
|
)
|
2023-03-15 07:04:06 +00:00
|
|
|
.setValue(this.plugin.settings.triggerOnSpace)
|
|
|
|
|
.onChange(async (value) => {
|
2023-06-22 12:21:01 +00:00
|
|
|
this.plugin.settings.triggerOnSpace =
|
|
|
|
|
value as AutoTriggerOptions;
|
2023-03-15 07:04:06 +00:00
|
|
|
await this.plugin.saveSettings();
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-03-15 07:04:06 +00:00
|
|
|
);
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-04-13 20:57:20 +00:00
|
|
|
.setName("Trigger on Enter")
|
|
|
|
|
.setDesc(
|
2023-06-22 12:21:01 +00:00
|
|
|
"If enabled, the snippet function will trigger when enter is pressed (but not while shift is held)."
|
2023-04-13 20:57:20 +00:00
|
|
|
)
|
2023-04-14 22:03:44 +00:00
|
|
|
.addDropdown((dropdown) =>
|
|
|
|
|
dropdown
|
|
|
|
|
.addOption(AutoTriggerOptions.Disabled, "Disabled")
|
2023-06-22 12:21:01 +00:00
|
|
|
.addOption(
|
|
|
|
|
AutoTriggerOptions.EnabledNoWS,
|
2023-08-20 18:12:38 +00:00
|
|
|
"Enabled, no newline"
|
2023-06-22 12:21:01 +00:00
|
|
|
)
|
2023-04-20 09:55:19 +00:00
|
|
|
.addOption(
|
|
|
|
|
AutoTriggerOptions.EnabledYesWS,
|
2023-08-20 18:12:38 +00:00
|
|
|
"Enabled, also newline"
|
2023-04-20 09:55:19 +00:00
|
|
|
)
|
2023-04-13 20:57:20 +00:00
|
|
|
.setValue(this.plugin.settings.triggerOnEnter)
|
|
|
|
|
.onChange(async (value) => {
|
2023-06-22 12:21:01 +00:00
|
|
|
this.plugin.settings.triggerOnEnter =
|
|
|
|
|
value as AutoTriggerOptions;
|
2023-04-13 20:57:20 +00:00
|
|
|
await this.plugin.saveSettings();
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-04-13 20:57:20 +00:00
|
|
|
);
|
|
|
|
|
|
2023-04-22 01:40:59 +00:00
|
|
|
new Setting(childEl)
|
2023-03-15 07:04:06 +00:00
|
|
|
.setName("Trigger on Tab")
|
|
|
|
|
.setDesc(
|
2023-06-22 12:21:01 +00:00
|
|
|
"If enabled, the snippet function will trigger when tab is pressed (but not while shift is held)."
|
2023-03-15 07:04:06 +00:00
|
|
|
)
|
2023-04-14 22:03:44 +00:00
|
|
|
.addDropdown((dropdown) =>
|
|
|
|
|
dropdown
|
|
|
|
|
.addOption(AutoTriggerOptions.Disabled, "Disabled")
|
2023-06-22 12:21:01 +00:00
|
|
|
.addOption(
|
|
|
|
|
AutoTriggerOptions.EnabledNoWS,
|
2023-08-20 18:12:38 +00:00
|
|
|
"Enabled, no indent"
|
2023-06-22 12:21:01 +00:00
|
|
|
)
|
2023-04-20 09:55:19 +00:00
|
|
|
.addOption(
|
|
|
|
|
AutoTriggerOptions.EnabledYesWS,
|
2023-08-20 18:12:38 +00:00
|
|
|
"Enabled, also indent on simple snippets (no newlines)"
|
2023-04-20 09:55:19 +00:00
|
|
|
)
|
2023-04-07 09:49:45 +00:00
|
|
|
.setValue(this.plugin.settings.triggerOnTab)
|
2023-03-15 07:04:06 +00:00
|
|
|
.onChange(async (value) => {
|
2023-06-22 12:21:01 +00:00
|
|
|
this.plugin.settings.triggerOnTab =
|
|
|
|
|
value as AutoTriggerOptions;
|
2023-03-15 07:04:06 +00:00
|
|
|
await this.plugin.saveSettings();
|
2023-06-22 12:21:01 +00:00
|
|
|
})
|
2023-03-15 07:04:06 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|