diff --git a/docs/changelog.md b/docs/changelog.md index 543ff44..090c4fa 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -8,6 +8,7 @@ Here are the most notable changes in each release. For a more detailed list of c - Added support for custom key bindings. See [the documentation](https://heynote.com/docs/#user-content-custom-key-bindings) for more info. - Added a "command palette" that can be accessed by pressing `Ctrl/Cmd+Shift+P`, or just typing `>` in the buffer selector. The command palette allows you to discover all available commands in the app, and to quickly execute them. +- Added support for configuring the tab size. ### Other changes diff --git a/electron/config.js b/electron/config.js index 0436060..0db2c24 100644 --- a/electron/config.js +++ b/electron/config.js @@ -48,6 +48,7 @@ const schema = { "showInMenu": {type: "boolean", default: false}, "alwaysOnTop": {type: "boolean", default: false}, "bracketClosing": {type: "boolean", default: false}, + "tabSize": {type: "integer", default: 4}, "defaultBlockLanguage": {type: "string"}, "defaultBlockLanguageAutoDetect": {type: "boolean"}, @@ -86,6 +87,7 @@ const defaults = { showInMenu: false, alwaysOnTop: false, bracketClosing: false, + tabSize: 4, }, theme: "system", } diff --git a/src/components/settings/Settings.vue b/src/components/settings/Settings.vue index 98e3f71..be95ab4 100644 --- a/src/components/settings/Settings.vue +++ b/src/components/settings/Settings.vue @@ -45,6 +45,7 @@ showInMenu: this.initialSettings.showInMenu, alwaysOnTop: this.initialSettings.alwaysOnTop, bracketClosing: this.initialSettings.bracketClosing, + tabSize: this.initialSettings.tabSize || 4, autoUpdate: this.initialSettings.autoUpdate, bufferPath: this.initialSettings.bufferPath, fontFamily: this.initialSettings.fontFamily || defaultFontFamily, @@ -116,6 +117,7 @@ alwaysOnTop: this.alwaysOnTop, autoUpdate: this.autoUpdate, bracketClosing: this.bracketClosing, + tabSize: this.tabSize, bufferPath: this.bufferPath, fontFamily: this.fontFamily === defaultFontFamily ? undefined : this.fontFamily, fontSize: this.fontSize === defaultFontSize ? undefined : this.fontSize, @@ -279,6 +281,19 @@ +
+
+

Tab Size

+ +
+

Default Block Language

diff --git a/src/editor/editor.js b/src/editor/editor.js index 37a7cbf..2914858 100644 --- a/src/editor/editor.js +++ b/src/editor/editor.js @@ -43,6 +43,7 @@ export class HeynoteEditor { bracketClosing=false, fontFamily, fontSize, + tabSize=4, defaultBlockToken, defaultBlockAutoDetect, keyBindings, @@ -56,6 +57,7 @@ export class HeynoteEditor { this.foldGutterCompartment = new Compartment this.readOnlyCompartment = new Compartment this.closeBracketsCompartment = new Compartment + this.indentUnitCompartment = new Compartment this.deselectOnCopy = keymap === "emacs" this.emacsMetaKey = emacsMetaKey this.fontTheme = new Compartment @@ -84,7 +86,7 @@ export class HeynoteEditor { this.themeCompartment.of(theme === "dark" ? heynoteDark : heynoteLight), heynoteBase, this.fontTheme.of(getFontTheme(fontFamily, fontSize)), - indentUnit.of(" "), + this.indentUnitCompartment.of(indentUnit.of(" ".repeat(tabSize))), EditorView.scrollMargins.of(f => { return {top: 80, bottom: 80} }), @@ -425,6 +427,12 @@ export class HeynoteEditor { selectAll(this.view) } + setTabSize(tabSize) { + this.view.dispatch({ + effects: this.indentUnitCompartment.reconfigure(indentUnit.of(" ".repeat(tabSize))) + }) + } + executeCommand(command) { const cmd = HEYNOTE_COMMANDS[command] if (!cmd) { diff --git a/src/stores/editor-cache.js b/src/stores/editor-cache.js index b02a1fe..4912ce5 100644 --- a/src/stores/editor-cache.js +++ b/src/stores/editor-cache.js @@ -36,6 +36,7 @@ export const useEditorCacheStore = defineStore("editorCache", { bracketClosing: settingsStore.settings.bracketClosing, fontFamily: settingsStore.settings.fontFamily, fontSize: settingsStore.settings.fontSize, + tabSize: settingsStore.settings.tabSize, defaultBlockToken: settingsStore.settings.defaultBlockLanguage, defaultBlockAutoDetect: settingsStore.settings.defaultBlockLanguageAutoDetect, keyBindings: settingsStore.settings.keyBindings, @@ -139,6 +140,9 @@ export const useEditorCacheStore = defineStore("editorCache", { case "fontSize": editor.setFont(newSettings.fontFamily, newSettings.fontSize) break + case "tabSize": + editor.setTabSize(newSettings.tabSize) + break case "defaultBlockLanguage": case "defaultBlockLanguageAutoDetect": editor.setDefaultBlockLanguage(newSettings.defaultBlockLanguage, newSettings.defaultBlockLanguageAutoDetect) diff --git a/tests/tab-size-setting.spec.js b/tests/tab-size-setting.spec.js new file mode 100644 index 0000000..cb8c2cb --- /dev/null +++ b/tests/tab-size-setting.spec.js @@ -0,0 +1,23 @@ +import { test, expect } from "@playwright/test"; +import { HeynotePage } from "./test-utils.js"; + +let heynotePage + +test.beforeEach(async ({ page }) => { + heynotePage = new HeynotePage(page) + await heynotePage.goto() +}); + +test("test default tab size", async ({ page }) => { + await page.locator("body").press("Tab") + expect(await heynotePage.getBlockContent(0)).toBe(" ") +}) + +test("test custom tab size", async ({ page }) => { + await page.locator("css=.status-block.settings").click() + await page.locator("css=li.tab-editing").click() + await page.locator("css=select.tab-size").selectOption("2") + await page.locator("body").press("Escape") + await page.locator("body").press("Tab") + expect(await heynotePage.getBlockContent(0)).toBe(" ") +})