Add Emacs set mark mode (C-Space)

This commit is contained in:
Jonatan Heyman 2023-03-12 18:22:16 +01:00
parent 1292c6ced3
commit 0bbdb262e6
4 changed files with 113 additions and 46 deletions

View File

@ -2,6 +2,7 @@ import { EditorState, EditorSelection } from "@codemirror/state"
import { EditorView } from "@codemirror/view"
import { LANGUAGES } from './languages.js';
import { setEmacsMarkMode } from "./emacs.js"
const languageTokensMatcher = LANGUAGES.map(l => l.token).join("|")
@ -38,6 +39,10 @@ export const heynoteCopyPaste = (editor) => {
userEvent: "delete.cut"
})
}
// if we're in Emacs mode, we want to exit mark mode in case we're in it
setEmacsMarkMode(false)
// if Editor.deselectOnCopy is set (e.g. we're in Emacs mode), we want to remove the selection after we've copied the text
if (editor.deselectOnCopy && event.type == "copy") {
const newSelection = EditorSelection.create(

View File

@ -11,7 +11,8 @@ import { heynoteLang } from "./lang-heynote/heynote.js"
import { noteBlockExtension, blockLineNumbers } from "./block/block.js"
import { changeCurrentBlockLanguage } from "./block/commands.js"
import { formatBlockContent } from "./block/format-code.js"
import { heynoteKeymap, emacsKeymap } from "./keymap.js"
import { heynoteKeymap } from "./keymap.js"
import { emacsKeymap } from "./emacs.js"
import { heynoteCopyPaste } from "./copy-paste"
import { languageDetection } from "./language-detection/autodetect.js"
import { autoSaveContent } from "./save.js"

101
src/editor/emacs.js Normal file
View File

@ -0,0 +1,101 @@
import { Direction} from "@codemirror/view"
import { EditorSelection, EditorState, Prec } from "@codemirror/state"
import {
undo, redo,
cursorGroupLeft, cursorGroupRight, selectGroupLeft, selectGroupRight,
simplifySelection,
deleteCharForward, deleteCharBackward, deleteToLineEnd,
splitLine,
transposeChars,
cursorPageDown,
cursorCharLeft, selectCharLeft,
cursorCharRight, selectCharRight,
cursorLineUp, selectLineUp,
cursorLineDown, selectLineDown,
cursorLineStart, selectLineStart,
cursorLineEnd, selectLineEnd,
} from "@codemirror/commands"
import { heynoteKeymap, keymapFromSpec } from "./keymap.js"
import {
gotoPreviousBlock, gotoNextBlock,
selectNextBlock, selectPreviousBlock,
gotoPreviousParagraph, gotoNextParagraph,
selectNextParagraph, selectPreviousParagraph,
selectAll,
} from "./block/commands.js"
// if set to true, all keybindings for moving around is changed to their corresponding select commands
let emacsMarkMode = false
export function setEmacsMarkMode(value) {
emacsMarkMode = value
}
/**
* Return a command that will conditionally execute either the default command or the mark mode command
*
* @param defaultCmd Default command to execute
* @param {*} markModeCmd Command to execute if mark mode is active
*/
function emacsMoveCommand(defaultCmd, markModeCmd) {
return (view) => emacsMarkMode ? markModeCmd(view) : defaultCmd(view)
}
/**
* C-g command that exits mark mode and simplifies selection
*/
function emacsCancel(view) {
simplifySelection(view)
setEmacsMarkMode(false)
}
/**
* Exit mark mode before executing selectAll command
*/
function emacsSelectAll(view) {
setEmacsMarkMode(false)
return selectAll(view)
}
export function emacsKeymap(editor) {
return [
heynoteKeymap(editor),
Prec.highest(keymapFromSpec([
["Ctrl-Shift--", undo],
["Ctrl-.", redo],
["Ctrl-g", emacsCancel],
{key:"Ctrl-ArrowLeft", run:cursorGroupLeft, shift:selectGroupLeft},
{key:"Ctrl-ArrowRight", run:cursorGroupRight, shift:selectGroupRight},
["ArrowLeft", emacsMoveCommand(cursorCharLeft, selectCharLeft)],
["ArrowRight", emacsMoveCommand(cursorCharRight, selectCharRight)],
["ArrowUp", emacsMoveCommand(cursorLineUp, selectLineUp)],
["ArrowDown", emacsMoveCommand(cursorLineDown, selectLineDown)],
["Ctrl-d", deleteCharForward],
["Ctrl-h", deleteCharBackward],
["Ctrl-k", deleteToLineEnd],
["Ctrl-o", splitLine],
["Ctrl-t", transposeChars],
["Ctrl-v", cursorPageDown],
{ key: "Ctrl-b", run: emacsMoveCommand(cursorCharLeft, selectCharLeft), shift: selectCharLeft, preventDefault: true },
{ key: "Ctrl-f", run: emacsMoveCommand(cursorCharRight, selectCharRight), shift: selectCharRight },
{ key: "Ctrl-p", run: emacsMoveCommand(cursorLineUp, selectLineUp), shift: selectLineUp },
{ key: "Ctrl-n", run: emacsMoveCommand(cursorLineDown, selectLineDown), shift: selectLineDown },
{ key: "Ctrl-a", run: emacsMoveCommand(cursorLineStart, selectLineStart), shift: selectLineStart },
{ key: "Ctrl-e", run: emacsMoveCommand(cursorLineEnd, selectLineEnd), shift: selectLineEnd },
])),
Prec.highest(keymapFromSpec([
["Ctrl-Space", (view) => { emacsMarkMode = !emacsMarkMode }],
["Mod-a", emacsSelectAll],
{key:"Mod-ArrowUp", run:emacsMoveCommand(gotoPreviousBlock, selectPreviousBlock), shift:selectPreviousBlock},
{key:"Mod-ArrowDown", run:emacsMoveCommand(gotoNextBlock, selectNextBlock), shift:selectNextBlock},
{key:"Ctrl-ArrowUp", run:emacsMoveCommand(gotoPreviousParagraph, selectPreviousParagraph), shift:selectPreviousParagraph},
{key:"Ctrl-ArrowDown", run:emacsMoveCommand(gotoNextParagraph, selectNextParagraph), shift:selectNextParagraph},
])),
]
}

View File

@ -1,21 +1,8 @@
import { EditorView, keymap } from "@codemirror/view"
import { EditorSelection } from "@codemirror/state"
import { keymap } from "@codemirror/view"
//import { EditorSelection, EditorState } from "@codemirror/state"
import {
indentWithTab, insertTab, indentLess, indentMore,
undo, redo,
cursorGroupLeft, cursorGroupRight, selectGroupLeft, selectGroupRight,
simplifySelection,
deleteCharForward, deleteCharBackward, deleteToLineEnd,
splitLine,
transposeChars,
cursorPageDown,
cursorCharLeft, selectCharLeft,
cursorCharRight, selectCharRight,
cursorLineUp, selectLineUp,
cursorLineDown, selectLineDown,
cursorLineStart, selectLineStart,
cursorLineEnd, selectLineEnd,
}from "@codemirror/commands"
indentLess, indentMore,
} from "@codemirror/commands"
import {
insertNewBlockAtCursor,
@ -31,7 +18,7 @@ import {
import { formatBlockContent } from "./block/format-code.js"
function keymapFromSpec(specs) {
export function keymapFromSpec(specs) {
return keymap.of(specs.map((spec) => {
if (spec.run) {
return {...spec, preventDefault: true}
@ -63,30 +50,3 @@ export function heynoteKeymap(editor) {
{key:"Ctrl-ArrowDown", run:gotoNextParagraph, shift:selectNextParagraph},
])
}
export function emacsKeymap(editor) {
return [
heynoteKeymap(editor),
keymapFromSpec([
["Ctrl-Shift--", undo],
["Ctrl-.", redo],
["Ctrl-g", simplifySelection],
{key:"Ctrl-ArrowLeft", run:cursorGroupLeft, shift:selectGroupLeft},
{key:"Ctrl-ArrowRight", run:cursorGroupRight, shift:selectGroupRight},
["Ctrl-d", deleteCharForward],
["Ctrl-h", deleteCharBackward],
["Ctrl-k", deleteToLineEnd],
["Ctrl-o", splitLine],
["Ctrl-t", transposeChars],
["Ctrl-v", cursorPageDown],
{ key: "Ctrl-b", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true },
{ key: "Ctrl-f", run: cursorCharRight, shift: selectCharRight },
{ key: "Ctrl-p", run: cursorLineUp, shift: selectLineUp },
{ key: "Ctrl-n", run: cursorLineDown, shift: selectLineDown },
{ key: "Ctrl-a", run: cursorLineStart, shift: selectLineStart },
{ key: "Ctrl-e", run: cursorLineEnd, shift: selectLineEnd },
]),
]
}