From e49f1ca586ec317d3f39426f42d2078d3c9e769d Mon Sep 17 00:00:00 2001 From: Spencer Gouw Date: Sun, 8 Oct 2023 17:24:04 -0500 Subject: [PATCH] wip: exploring state fields --- main.ts | 122 ++++++++++++++++++++++++++++++++--- snippet.ts => src/snippet.ts | 7 ++ symbol.ts => src/symbol.ts | 2 +- 3 files changed, 120 insertions(+), 11 deletions(-) rename snippet.ts => src/snippet.ts (70%) rename symbol.ts => src/symbol.ts (98%) diff --git a/main.ts b/main.ts index 97981a5..92c72f7 100644 --- a/main.ts +++ b/main.ts @@ -8,8 +8,24 @@ import { Setting, } from "obsidian"; -import { Symbol } from "symbol"; -import { LHS, RHS, Snippet } from "snippet"; +import { syntaxTree } from "@codemirror/language"; +import { + Extension, + RangeSetBuilder, + EditorState, + StateField, + StateEffect, + Transaction, +} from "@codemirror/state"; +import { + EditorView, + WidgetType, + Decoration, + DecorationSet, +} from "@codemirror/view"; + +import { Symbol } from "src/symbol"; +import { LHS, RHS, Snippet, SnippetType } from "src/snippet"; enum AutoTriggerOptions { Disabled = "disabled", @@ -17,13 +33,6 @@ enum AutoTriggerOptions { EnabledYesWS = "y-ws", } -enum SnippetType { - SLSR = 0, - SLMR = 1, - MLSR = 2, - MLMR = 3, -} - interface JellySnippetsSettings { snippetsFile: string; triggerOnSpace: AutoTriggerOptions; @@ -48,6 +57,83 @@ const DEFAULT_SETTINGS: JellySnippetsSettings = { snippetDivider: "-==-", }; +const addEffect = StateEffect.define(); +const subEffect = StateEffect.define(); +const mulEffect = StateEffect.define(); +const divEffect = StateEffect.define(); +const resetEffect = StateEffect.define(); + +// StateField.define(..) takes a StateFieldSpec as argument +export const calculatorField = StateField.define({ + create(state: EditorState): number { + return 0; + }, + update(oldState: number, transaction: Transaction): number { + let newState = oldState; + + for (let effect of transaction.effects) { + if (effect.is(addEffect)) { + newState += effect.value; + } else if (effect.is(subEffect)) { + newState -= effect.value; + } else if (effect.is(mulEffect)) { + newState *= effect.value; + } else if (effect.is(divEffect)) { + newState /= effect.value; + } else if (effect.is(resetEffect)) { + newState = 0; + } + } + + return newState; + }, +}); + +export class EmojiWidget extends WidgetType { + toDOM(view: EditorView): HTMLElement { + const div = document.createElement("span"); + + div.innerText = "👉"; + + return div; + } +} + +const decoration = Decoration.replace({ + widget: new EmojiWidget(), +}); + +export const emojiListField = StateField.define({ + create(state): DecorationSet { + return Decoration.none; + }, + update(oldState: DecorationSet, transaction: Transaction): DecorationSet { + const builder = new RangeSetBuilder(); + + syntaxTree(transaction.state).iterate({ + enter(node) { + if (node.type.name.startsWith("list")) { + // Position of the '-' or the '*'. + const listCharFrom = node.from - 2; + + builder.add( + listCharFrom, + listCharFrom + 1, + Decoration.replace({ + widget: new EmojiWidget(), + }) + ); + } + }, + }); + + return builder.finish(); + }, + provide(field: StateField): Extension { + return EditorView.decorations.from(field); + }, +}); + export default class JellySnippets extends Plugin { settings: JellySnippetsSettings; private multilineSnippets: { [key: LHS]: RHS } = {}; @@ -55,6 +141,21 @@ export default class JellySnippets extends Plugin { async onload() { await this.loadSettings(); + this.registerEditorExtension(emojiListField); + + this.addCommand({ + id: "example-editor-command", + name: "Example editor command", + editorCallback: (editor, view) => { + // @ts-expect-error, not typed + const editorView = view.editor.cm as EditorView; + + editorView.dispatch({ + effects: [], + }); + }, + }); + /* // Check settings and load snippets in. this.reloadSnippets(); @@ -75,7 +176,7 @@ export default class JellySnippets extends Plugin { } }; - // Register for main window. + // Register key events for main window. this.registerDomEvent(document, "keydown", onKeyEvent); // If window changes, registerDomEvent for new window if so. @@ -103,6 +204,7 @@ export default class JellySnippets extends Plugin { }); this.addSettingTab(new JellySnippetsSettingTab(this.app, this)); + */ } onunload() {} diff --git a/snippet.ts b/src/snippet.ts similarity index 70% rename from snippet.ts rename to src/snippet.ts index 1218341..8096c50 100644 --- a/snippet.ts +++ b/src/snippet.ts @@ -11,3 +11,10 @@ export type Snippet = { lhs: LHS; rhs: RHS; }; + +export enum SnippetType { + SLSR = 0, + SLMR = 1, + MLSR = 2, + MLMR = 3, +} diff --git a/symbol.ts b/src/symbol.ts similarity index 98% rename from symbol.ts rename to src/symbol.ts index a2b844c..231afec 100644 --- a/symbol.ts +++ b/src/symbol.ts @@ -1,4 +1,4 @@ -import { RHS } from "snippet"; +import { RHS } from "src/snippet"; export enum Symbol { // on parse