From d440c7c6514efd09c68e715ae548a3ba7f553184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 2 Jun 2026 15:15:51 +0200 Subject: [PATCH 1/4] propert tab behavior this time(i hope) --- .../codeEditor/extensions/customKeyMaps.js | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/client/components/codeEditor/extensions/customKeyMaps.js b/client/components/codeEditor/extensions/customKeyMaps.js index db3edf47f..49c2412fe 100644 --- a/client/components/codeEditor/extensions/customKeyMaps.js +++ b/client/components/codeEditor/extensions/customKeyMaps.js @@ -1,14 +1,43 @@ /* eslint max-lines: ["error", { "max": 300 }] */ import { keymap } from '@codemirror/view'; import { undo, redo, indentMore, deleteLine } from '@codemirror/commands'; +import { EditorSelection } from '@codemirror/state'; import { Prec } from '@codemirror/state'; -const insertTab = (view)=>{ - const { from, to } = view.state.selection.main; +const insertTab = (view) => { + const shouldIndent = view.state.selection.ranges.some(range => + view.state.doc.lineAt(range.from).number !== + view.state.doc.lineAt(range.to).number + ); + + if(shouldIndent) return indentMore(view); + + const changes = []; + const ranges = []; + + for(const range of view.state.selection.ranges) { + console.log(range); + changes.push({ + from : range.from, + to : range.to, + insert : ' ' + }); + + ranges.push({ + anchor : range.from + }); + } + const tr = view.state.update({ changes }); view.dispatch({ - changes : { from, to, insert: ' ' }, - selection : { anchor: from + 2 } + changes, + selection: EditorSelection.create( + view.state.selection.ranges.map(range => + EditorSelection.cursor( + tr.changes.mapPos(range.from, 1) + 2 + ) + ) + ) }); return true; @@ -170,6 +199,8 @@ const newPage = (view)=>{ export const generalKeymap = Prec.high(keymap.of([ { key: 'Tab', run: insertTab }, + //{ key: 'Shift-Tab', run: indentMore }, + { key: 'Shift-Tab', run: indentLess }, { key: 'Mod-z', run: undo }, //i think it may be unnecessary { key: 'Mod-Shift-z', run: redo }, { key: 'Mod-y', run: redo }, @@ -177,8 +208,7 @@ export const generalKeymap = Prec.high(keymap.of([ ])); export const markdownKeymap = Prec.highest(keymap.of([ - //{ key: 'Shift-Tab', run: indentMore }, - { key: 'Shift-Tab', run: indentLess }, + { key: 'Mod-b', run: wrapSelection('**', '**') }, // makeBold { key: 'Mod-i', run: wrapSelection('*', '*') }, // makeItalic { key: 'Mod-u', run: wrapSelection('', '') }, // makeUnderline From 6a51116844897f19c09f1e965f9093575f6f96d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 2 Jun 2026 15:17:03 +0200 Subject: [PATCH 2/4] format --- .../codeEditor/extensions/customKeyMaps.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client/components/codeEditor/extensions/customKeyMaps.js b/client/components/codeEditor/extensions/customKeyMaps.js index 49c2412fe..773e1265b 100644 --- a/client/components/codeEditor/extensions/customKeyMaps.js +++ b/client/components/codeEditor/extensions/customKeyMaps.js @@ -4,9 +4,8 @@ import { undo, redo, indentMore, deleteLine } from '@codemirror/commands'; import { EditorSelection } from '@codemirror/state'; import { Prec } from '@codemirror/state'; -const insertTab = (view) => { - const shouldIndent = view.state.selection.ranges.some(range => - view.state.doc.lineAt(range.from).number !== +const insertTab = (view)=>{ + const shouldIndent = view.state.selection.ranges.some((range)=>view.state.doc.lineAt(range.from).number !== view.state.doc.lineAt(range.to).number ); @@ -15,7 +14,7 @@ const insertTab = (view) => { const changes = []; const ranges = []; - for(const range of view.state.selection.ranges) { + for (const range of view.state.selection.ranges) { console.log(range); changes.push({ from : range.from, @@ -31,11 +30,10 @@ const insertTab = (view) => { view.dispatch({ changes, - selection: EditorSelection.create( - view.state.selection.ranges.map(range => - EditorSelection.cursor( - tr.changes.mapPos(range.from, 1) + 2 - ) + selection : EditorSelection.create( + view.state.selection.ranges.map((range)=>EditorSelection.cursor( + tr.changes.mapPos(range.from, 1) + 2 + ) ) ) }); From 0335767afa77d3f68f2d13450772889bfe33ab0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 2 Jun 2026 15:17:14 +0200 Subject: [PATCH 3/4] remove logs --- client/components/codeEditor/extensions/customKeyMaps.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/components/codeEditor/extensions/customKeyMaps.js b/client/components/codeEditor/extensions/customKeyMaps.js index 773e1265b..91f33125d 100644 --- a/client/components/codeEditor/extensions/customKeyMaps.js +++ b/client/components/codeEditor/extensions/customKeyMaps.js @@ -15,7 +15,6 @@ const insertTab = (view)=>{ const ranges = []; for (const range of view.state.selection.ranges) { - console.log(range); changes.push({ from : range.from, to : range.to, From c9da8742eb5b472a2290ceff8dc74a62e1522fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 16 Jun 2026 10:23:58 +0200 Subject: [PATCH 4/4] adding comments, removing leftover code, renaming constant --- .../codeEditor/extensions/customKeyMaps.js | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/client/components/codeEditor/extensions/customKeyMaps.js b/client/components/codeEditor/extensions/customKeyMaps.js index 91f33125d..581268222 100644 --- a/client/components/codeEditor/extensions/customKeyMaps.js +++ b/client/components/codeEditor/extensions/customKeyMaps.js @@ -1,10 +1,12 @@ /* eslint max-lines: ["error", { "max": 300 }] */ import { keymap } from '@codemirror/view'; -import { undo, redo, indentMore, deleteLine } from '@codemirror/commands'; +import { undo, redo, indentMore, indentLess, deleteLine } from '@codemirror/commands'; import { EditorSelection } from '@codemirror/state'; import { Prec } from '@codemirror/state'; const insertTab = (view)=>{ + // If any selection spans multiple lines, delegates to CodeMirror's indentMore + // Otherwise inserts two spaces at each cursor/selection const shouldIndent = view.state.selection.ranges.some((range)=>view.state.doc.lineAt(range.from).number !== view.state.doc.lineAt(range.to).number ); @@ -12,26 +14,23 @@ const insertTab = (view)=>{ if(shouldIndent) return indentMore(view); const changes = []; - const ranges = []; for (const range of view.state.selection.ranges) { changes.push({ from : range.from, to : range.to, - insert : ' ' - }); - - ranges.push({ - anchor : range.from + insert : ' ' // Insert two spaces, not a tab char! }); } - const tr = view.state.update({ changes }); + // Create a transaction so we can map old positions to + // their new positions after the edits are applied + const mappedChanges = view.state.update({ changes }); view.dispatch({ changes, selection : EditorSelection.create( view.state.selection.ranges.map((range)=>EditorSelection.cursor( - tr.changes.mapPos(range.from, 1) + 2 + mappedChanges.changes.mapPos(range.from, 1) + 2 ) ) ) @@ -40,20 +39,6 @@ const insertTab = (view)=>{ return true; }; -const indentLess = (view)=>{ - const { from, to } = view.state.selection.main; - const lines = []; - for (let l = view.state.doc.lineAt(from).number; l <= view.state.doc.lineAt(to).number; l++) { - const line = view.state.doc.line(l); - const match = line.text.match(/^ {1,2}/); // match up to 2 spaces - if(match) { - lines.push({ from: line.from, to: line.from + match[0].length, insert: '' }); - } - } - if(lines.length > 0) view.dispatch({ changes: lines }); - return true; -}; - const wrapSelection = (prefix, suffix)=>(view)=>{ const changes = []; @@ -195,13 +180,12 @@ const newPage = (view)=>{ }; export const generalKeymap = Prec.high(keymap.of([ - { key: 'Tab', run: insertTab }, - //{ key: 'Shift-Tab', run: indentMore }, - { key: 'Shift-Tab', run: indentLess }, - { key: 'Mod-z', run: undo }, //i think it may be unnecessary + { key: 'Tab', run: insertTab }, //runs indentMore if multiple lines selected in a single selection + { key: 'Shift-Tab', run: indentLess }, + { key: 'Mod-z', run: undo }, //it may be unnecessary { key: 'Mod-Shift-z', run: redo }, - { key: 'Mod-y', run: redo }, - { key: 'Mod-d', run: deleteLine }, + { key: 'Mod-y', run: redo }, //user asked, so double keybind + { key: 'Mod-d', run: deleteLine }, //annoyingly overrides "selectNextOccurrence" because users asked ])); export const markdownKeymap = Prec.highest(keymap.of([