diff --git a/package-lock.json b/package-lock.json index 296294e..83b5a3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-latex-suite", - "version": "1.9.1", + "version": "1.9.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "obsidian-latex-suite", - "version": "1.9.1", + "version": "1.9.2", "license": "MIT", "dependencies": { "set.prototype.difference": "^1.1.5", diff --git a/src/latex_suite.ts b/src/latex_suite.ts index 310871f..9a4680b 100644 --- a/src/latex_suite.ts +++ b/src/latex_suite.ts @@ -20,6 +20,7 @@ import { concealPlugin } from "./editor_extensions/conceal"; import { LatexSuiteCMSettings } from "./settings/settings"; import { colorPairedBracketsPluginLowestPrec, highlightCursorBracketsPlugin } from "./editor_extensions/highlight_brackets"; import { cursorTooltipBaseTheme, cursorTooltipField } from "./editor_extensions/math_tooltip"; +import { isComposing } from "./utils/editor_utils"; export const handleUpdate = (update: ViewUpdate) => { const cursorTriggeredByChange = update.state.field(cursorTriggerStateField, false); @@ -37,12 +38,12 @@ export const handleUpdate = (update: ViewUpdate) => { } export const onKeydown = (event: KeyboardEvent, view: EditorView) => { - const success = handleKeydown(event.key, event.shiftKey, event.ctrlKey || event.metaKey, view); + const success = handleKeydown(event.key, event.shiftKey, event.ctrlKey || event.metaKey, isComposing(view, event), view); if (success) event.preventDefault(); } -export const handleKeydown = (key: string, shiftKey: boolean, ctrlKey: boolean, view: EditorView) => { +export const handleKeydown = (key: string, shiftKey: boolean, ctrlKey: boolean, isIME: boolean, view: EditorView) => { const settings = getLatexSuiteConfig(view); const ctx = Context.fromView(view); @@ -51,6 +52,9 @@ export const handleKeydown = (key: string, shiftKey: boolean, ctrlKey: boolean, if (settings.snippetsEnabled) { + // Prevent IME from triggering keydown events. + if (settings.suppressSnippetTriggerOnIME && isIME) return; + // Allows Ctrl + z for undo, instead of triggering a snippet ending with z if (!ctrlKey) { try { diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 63ddbb7..a6710a7 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -6,6 +6,7 @@ import { DEFAULT_SNIPPET_VARIABLES } from "src/utils/default_snippet_variables"; interface LatexSuiteBasicSettings { snippetsEnabled: boolean; snippetsTrigger: "Tab" | " " + suppressSnippetTriggerOnIME: boolean; removeSnippetWhitespace: boolean; loadSnippetsFromFile: boolean; loadSnippetVariablesFromFile: boolean; @@ -52,6 +53,7 @@ export const DEFAULT_SETTINGS: LatexSuitePluginSettings = { // Basic settings snippetsEnabled: true, snippetsTrigger: "Tab", + suppressSnippetTriggerOnIME: true, removeSnippetWhitespace: true, loadSnippetsFromFile: false, loadSnippetVariablesFromFile: false, diff --git a/src/settings/settings_tab.ts b/src/settings/settings_tab.ts index 6d276e8..d807e9e 100644 --- a/src/settings/settings_tab.ts +++ b/src/settings/settings_tab.ts @@ -410,6 +410,17 @@ export class LatexSuiteSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })); + new Setting(containerEl) + .setName("Don't trigger snippets when IME is active") + .setDesc("Whether to suppress the snippet triggering when an IME is active.") + .addToggle((toggle) => toggle + .setValue(this.plugin.settings.suppressSnippetTriggerOnIME) + .onChange(async (value) => { + this.plugin.settings.suppressSnippetTriggerOnIME = value; + await this.plugin.saveSettings(); + }) + ); + new Setting(containerEl) .setName("Code languages to interpret as math mode") .setDesc("Codeblock languages where the whole code block should be treated like a math block, separated by commas.") diff --git a/src/utils/editor_utils.ts b/src/utils/editor_utils.ts index 2e3638e..1374782 100644 --- a/src/utils/editor_utils.ts +++ b/src/utils/editor_utils.ts @@ -134,3 +134,15 @@ export function escalateToToken(cursor: TreeCursor, dir: Direction, target: stri return null; } + + +/** + * Check if the user is typing in an IME composition. + * Returns true even if the given event is the first keydown event of an IME composition. + */ +export function isComposing(view: EditorView, event: KeyboardEvent): boolean { + // view.composing and event.isComposing are false for the first keydown event of an IME composition, + // so we need to check for event.keyCode === 229 to prevent IME from triggering keydown events. + // Note that keyCode is deprecated - it is used here because it is apparently the only way to detect the first keydown event of an IME composition. + return view.composing || event.keyCode === 229; +}