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(" ")
+})