Add setting for turning on/off line number gutters and fold gutters

This commit is contained in:
Jonatan Heyman 2023-01-27 17:18:31 +01:00
parent 1fe63860a8
commit 5f98323586
12 changed files with 139 additions and 54 deletions

View File

@ -15,8 +15,25 @@ const schema = {
}, },
additionalProperties: false, additionalProperties: false,
}, },
keymap: { "enum": ["default", "emacs"] },
emacsMetaKey: { "enum": [null, "alt", "meta"] }, settings: {
type: "object",
properties: {
"keymap": { "enum": ["default", "emacs"], default:"default" },
"emacsMetaKey": { "enum": [null, "alt", "meta"], default: null },
"showLineNumberGutter": {type: "boolean", default:true},
"showFoldGutter": {type: "boolean", default:true},
},
}
} }
export default new Store({schema}) const defaults = {
settings: {
keymap: "default",
emacsMetaKey: "meta",
showLineNumberGutter: true,
showFoldGutter: true,
}
}
export default new Store({schema, defaults})

View File

@ -1,3 +1,3 @@
export const WINDOW_CLOSE_EVENT = "window-close" export const WINDOW_CLOSE_EVENT = "window-close"
export const KEYMAP_CHANGE_EVENT = "keymap-change"
export const OPEN_SETTINGS_EVENT = "open-settings" export const OPEN_SETTINGS_EVENT = "open-settings"
export const SETTINGS_CHANGE_EVENT = "settings-change"

View File

@ -6,7 +6,7 @@ export function onBeforeInputEvent({win, event, input, currentKeymap}) {
//console.log("keyboard event", input) //console.log("keyboard event", input)
let metaKey = "alt" let metaKey = "alt"
if (isMac) { if (isMac) {
metaKey = CONFIG.get("emacsMetaKey", "meta") metaKey = CONFIG.get("settings.emacsMetaKey", "meta")
} }
if (currentKeymap === "emacs") { if (currentKeymap === "emacs") {
/** /**

View File

@ -4,7 +4,7 @@ import { join } from 'node:path'
import * as jetpack from "fs-jetpack"; import * as jetpack from "fs-jetpack";
import menu from './menu' import menu from './menu'
import { initialContent, initialDevContent } from '../initial-content' import { initialContent, initialDevContent } from '../initial-content'
import { WINDOW_CLOSE_EVENT, KEYMAP_CHANGE_EVENT } from '../constants'; import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
import CONFIG from "../config" import CONFIG from "../config"
import { onBeforeInputEvent } from "../keymap" import { onBeforeInputEvent } from "../keymap"
import { isMac } from '../detect-platform'; import { isMac } from '../detect-platform';
@ -191,8 +191,10 @@ ipcMain.handle('buffer-content:saveAndQuit', async (event, content) => {
app.quit() app.quit()
}) })
ipcMain.handle('keymap:set', (event, keymap) => { ipcMain.handle('settings:set', (event, settings) => {
currentKeymap = keymap if (settings.keymap !== CONFIG.get("keymap")) {
win?.webContents.send(KEYMAP_CHANGE_EVENT, keymap) currentKeymap = settings.keymap
CONFIG.set("keymap", keymap) }
CONFIG.set("settings", settings)
win?.webContents.send(SETTINGS_CHANGE_EVENT, settings)
}) })

View File

@ -1,5 +1,5 @@
const { app, Menu } = require('electron') const { app, Menu } = require('electron')
import { WINDOW_CLOSE_EVENT, KEYMAP_CHANGE_EVENT, OPEN_SETTINGS_EVENT } from '../constants'; import { OPEN_SETTINGS_EVENT } from '../constants';
const isMac = process.platform === 'darwin' const isMac = process.platform === 'darwin'

View File

@ -2,7 +2,7 @@ const { contextBridge } = require('electron')
import darkMode from "./theme-mode" import darkMode from "./theme-mode"
import { isMac, isWindows, isLinux } from "../detect-platform" import { isMac, isWindows, isLinux } from "../detect-platform"
import { ipcRenderer } from "electron" import { ipcRenderer } from "electron"
import { WINDOW_CLOSE_EVENT, KEYMAP_CHANGE_EVENT, OPEN_SETTINGS_EVENT } from "../constants" import { WINDOW_CLOSE_EVENT, OPEN_SETTINGS_EVENT, SETTINGS_CHANGE_EVENT } from "../constants"
import CONFIG from "../config" import CONFIG from "../config"
//contextBridge.exposeInMainWorld("platform", ) //contextBridge.exposeInMainWorld("platform", )
@ -42,18 +42,14 @@ contextBridge.exposeInMainWorld("heynote", {
}, },
}, },
keymap: { settings: CONFIG.get("settings"),
set(keymap) {
ipcRenderer.invoke("keymap:set", keymap); setSettings(settings) {
}, ipcRenderer.invoke("settings:set", settings)
setEmacsMetaKey(key) { },
CONFIG.set("emacsMetaKey", key)
}, onSettingsChange(callback) {
initial: CONFIG.get("keymap", "default"), ipcRenderer.on(SETTINGS_CHANGE_EVENT, (event, settings) => callback(settings))
getEmacsMetaKey: () => CONFIG.get("emacsMetaKey", isMac ? "meta" : "alt"),
onKeymapChange(callback) {
ipcRenderer.on(KEYMAP_CHANGE_EVENT, (event, keymap) => callback(keymap))
},
}, },
}) })

View File

@ -24,7 +24,7 @@
development: window.location.href.indexOf("dev=1") !== -1, development: window.location.href.indexOf("dev=1") !== -1,
showLanguageSelector: false, showLanguageSelector: false,
showSettings: false, showSettings: false,
keymap: window.heynote.keymap.initial, settings: window.heynote.settings,
} }
}, },
@ -36,8 +36,8 @@
window.darkMode.onChange((theme) => { window.darkMode.onChange((theme) => {
this.theme = theme this.theme = theme
}) })
window.heynote.keymap.onKeymapChange((keymap) => { window.heynote.onSettingsChange((settings) => {
this.keymap = keymap this.settings = settings
}) })
window.heynote.onOpenSettings(() => { window.heynote.onOpenSettings(() => {
this.showSettings = true this.showSettings = true
@ -103,7 +103,9 @@
:theme="theme" :theme="theme"
:development="development" :development="development"
:debugSyntaxTree="false" :debugSyntaxTree="false"
:keymap="keymap" :keymap="settings.keymap"
:showLineNumberGutter="settings.showLineNumberGutter"
:showFoldGutter="settings.showFoldGutter"
class="editor" class="editor"
ref="editor" ref="editor"
@openLanguageSelector="openLanguageSelector" @openLanguageSelector="openLanguageSelector"
@ -127,7 +129,7 @@
/> />
<Settings <Settings
v-if="showSettings" v-if="showSettings"
:initialKeymap="keymap" :initialSettings="settings"
@closeSettings="closeSettings" @closeSettings="closeSettings"
/> />
</div> </div>

View File

@ -11,6 +11,14 @@
type: String, type: String,
default: "default", default: "default",
}, },
showLineNumberGutter: {
type: Boolean,
default: true,
},
showFoldGutter: {
type: Boolean,
default: true,
},
}, },
data() { data() {
@ -43,6 +51,8 @@
window.heynote.buffer.save(content) window.heynote.buffer.save(content)
}, },
keymap: this.keymap, keymap: this.keymap,
showLineNumberGutter: this.showLineNumberGutter,
showFoldGutter: this.showFoldGutter,
}) })
}) })
// set up window close handler that will save the buffer and quit // set up window close handler that will save the buffer and quit
@ -77,7 +87,15 @@
keymap(keymap) { keymap(keymap) {
this.editor.setKeymap(keymap) this.editor.setKeymap(keymap)
} },
showLineNumberGutter(show) {
this.editor.setLineNumberGutter(show)
},
showFoldGutter(show) {
this.editor.setFoldGutter(show)
},
}, },
methods: { methods: {

View File

@ -2,6 +2,7 @@
export default { export default {
props: { props: {
initialKeymap: String, initialKeymap: String,
initialSettings: Object,
}, },
data() { data() {
@ -10,9 +11,11 @@
{ name: "Default", value: "default" }, { name: "Default", value: "default" },
{ name: "Emacs", value: "emacs" }, { name: "Emacs", value: "emacs" },
], ],
keymap: this.initialKeymap, keymap: this.initialSettings.keymap,
metaKey: window.heynote.keymap.getEmacsMetaKey(), metaKey: this.initialSettings.emacsMetaKey,
isMac: window.heynote.platform.isMac, isMac: window.heynote.platform.isMac,
showLineNumberGutter: this.initialSettings.showLineNumberGutter,
showFoldGutter: this.initialSettings.showFoldGutter,
} }
}, },
@ -24,22 +27,21 @@
window.removeEventListener("keydown", this.onKeyDown); window.removeEventListener("keydown", this.onKeyDown);
}, },
watch: {
keymap(value) {
window.heynote.keymap.set(value)
},
metaKey(value) {
window.heynote.keymap.setEmacsMetaKey(value)
}
},
methods: { methods: {
onKeyDown(event) { onKeyDown(event) {
if (event.key === "Escape") { if (event.key === "Escape") {
this.$emit("closeSettings") this.$emit("closeSettings")
} }
}, },
updateSettings() {
window.heynote.setSettings({
showLineNumberGutter: this.showLineNumberGutter,
showFoldGutter: this.showFoldGutter,
keymap: this.keymap,
emacsMetaKey: this.metaKey,
})
}
} }
} }
</script> </script>
@ -52,7 +54,7 @@
<div class="row"> <div class="row">
<div class="entry"> <div class="entry">
<h2>Keymap</h2> <h2>Keymap</h2>
<select ref="keymapSelector" v-model="keymap"> <select ref="keymapSelector" v-model="keymap" @change="updateSettings">
<template v-for="km in keymaps" :key="km.value"> <template v-for="km in keymaps" :key="km.value">
<option :selected="km.value === keymap" :value="km.value">{{ km.name }}</option> <option :selected="km.value === keymap" :value="km.value">{{ km.name }}</option>
</template> </template>
@ -60,12 +62,35 @@
</div> </div>
<div class="entry" v-if="keymap === 'emacs' && isMac"> <div class="entry" v-if="keymap === 'emacs' && isMac">
<h2>Meta Key</h2> <h2>Meta Key</h2>
<select v-model="metaKey"> <select v-model="metaKey" @change="updateSettings">
<option :selected="metaKey === 'meta'" value="meta">Command</option> <option :selected="metaKey === 'meta'" value="meta">Command</option>
<option :selected="metaKey === 'alt'" value="alt">Option</option> <option :selected="metaKey === 'alt'" value="alt">Option</option>
</select> </select>
</div> </div>
</div> </div>
<div class="row">
<div class="entry">
<h2>Gutters</h2>
<div class="checkbox">
<input
type="checkbox"
id="showLineNumbers"
v-model="showLineNumberGutter"
@change="updateSettings"
/>
<label for="showLineNumbers">Show line numbers</label>
</div>
<div class="checkbox">
<input
type="checkbox"
id="showFoldGutter"
v-model="showFoldGutter"
@change="updateSettings"
/>
<label for="showFoldGutter">Show fold gutter</label>
</div>
</div>
</div>
</div> </div>
<button <button
@click="$emit('closeSettings')" @click="$emit('closeSettings')"

View File

@ -268,7 +268,7 @@ export function getBlockLineFromPos(state, pos) {
return null return null
} }
const blockLineNumbers = lineNumbers({ export const blockLineNumbers = lineNumbers({
formatNumber(lineNo, state) { formatNumber(lineNo, state) {
if (state.doc.lines >= lineNo) { if (state.doc.lines >= lineNo) {
const lineInfo = getBlockLineFromPos(state, state.doc.line(lineNo).from) const lineInfo = getBlockLineFromPos(state, state.doc.line(lineNo).from)
@ -309,7 +309,6 @@ export const noteBlockExtension = (editor) => {
blockLayer, blockLayer,
preventFirstBlockFromBeingDeleted, preventFirstBlockFromBeingDeleted,
preventSelectionBeforeFirstBlock, preventSelectionBeforeFirstBlock,
blockLineNumbers,
emitCursorChange(editor), emitCursorChange(editor),
] ]
} }

View File

@ -1,13 +1,13 @@
import { Annotation, EditorState, Compartment } from "@codemirror/state" import { Annotation, EditorState, Compartment } from "@codemirror/state"
import { EditorView, keymap, drawSelection, ViewPlugin } from "@codemirror/view" import { EditorView, keymap, drawSelection, ViewPlugin, lineNumbers } from "@codemirror/view"
import { indentUnit, forceParsing } from "@codemirror/language" import { indentUnit, forceParsing, foldGutter } from "@codemirror/language"
import { heynoteLight } from "./theme/light.js" import { heynoteLight } from "./theme/light.js"
import { heynoteDark } from "./theme/dark.js" import { heynoteDark } from "./theme/dark.js"
import { heynoteBase } from "./theme/base.js" import { heynoteBase } from "./theme/base.js"
import { customSetup } from "./setup.js" import { customSetup } from "./setup.js"
import { heynoteLang } from "./lang-heynote/heynote.js" import { heynoteLang } from "./lang-heynote/heynote.js"
import { noteBlockExtension } from "./block/block.js" import { noteBlockExtension, blockLineNumbers } from "./block/block.js"
import { changeCurrentBlockLanguage } from "./block/commands.js" import { changeCurrentBlockLanguage } from "./block/commands.js"
import { heynoteKeymap, emacsKeymap } from "./keymap.js" import { heynoteKeymap, emacsKeymap } from "./keymap.js"
import { heynoteCopyPaste } from "./copy-paste" import { heynoteCopyPaste } from "./copy-paste"
@ -26,10 +26,22 @@ function getKeymapExtensions(editor, keymap) {
export class HeynoteEditor { export class HeynoteEditor {
constructor({element, content, focus=true, theme="light", saveFunction=null, keymap="default"}) { constructor({
element,
content,
focus=true,
theme="light",
saveFunction=null,
keymap="default",
showLineNumberGutter=true,
showFoldGutter=true,
}) {
this.element = element this.element = element
this.themeCompartment = new Compartment this.themeCompartment = new Compartment
this.keymapCompartment = new Compartment this.keymapCompartment = new Compartment
this.lineNumberCompartmentPre = new Compartment
this.lineNumberCompartment = new Compartment
this.foldGutterCompartment = new Compartment
this.deselectOnCopy = keymap === "emacs" this.deselectOnCopy = keymap === "emacs"
const state = EditorState.create({ const state = EditorState.create({
@ -39,7 +51,9 @@ export class HeynoteEditor {
heynoteCopyPaste(this), heynoteCopyPaste(this),
//minimalSetup, //minimalSetup,
this.lineNumberCompartment.of(showLineNumberGutter ? [lineNumbers(), blockLineNumbers] : []),
customSetup, customSetup,
this.foldGutterCompartment.of(showFoldGutter ? [foldGutter()] : []),
this.themeCompartment.of(theme === "dark" ? heynoteDark : heynoteLight), this.themeCompartment.of(theme === "dark" ? heynoteDark : heynoteLight),
heynoteBase, heynoteBase,
@ -77,6 +91,10 @@ export class HeynoteEditor {
} }
} }
getContent() {
return this.view.state.sliceDoc()
}
focus() { focus() {
this.view.focus() this.view.focus()
} }
@ -102,8 +120,16 @@ export class HeynoteEditor {
changeCurrentBlockLanguage(this.view.state, this.view.dispatch, lang, auto) changeCurrentBlockLanguage(this.view.state, this.view.dispatch, lang, auto)
} }
getContent() { setLineNumberGutter(show) {
return this.view.state.sliceDoc() this.view.dispatch({
effects: this.lineNumberCompartment.reconfigure(show ? [lineNumbers(), blockLineNumbers] : []),
})
}
setFoldGutter(show) {
this.view.dispatch({
effects: this.foldGutterCompartment.reconfigure(show ? [foldGutter()] : []),
})
} }
} }

View File

@ -47,11 +47,11 @@ and an array literal), copy it into your own code, and adjust it
as desired. as desired.
*/ */
const customSetup = /*@__PURE__*/(() => [ const customSetup = /*@__PURE__*/(() => [
lineNumbers(), //lineNumbers(),
highlightActiveLineGutter(), highlightActiveLineGutter(),
highlightSpecialChars(), highlightSpecialChars(),
history(), history(),
foldGutter(), //foldGutter(),
drawSelection(), drawSelection(),
dropCursor(), dropCursor(),
EditorState.allowMultipleSelections.of(true), EditorState.allowMultipleSelections.of(true),