Open sam-rez opened 1 year ago
@sam-rez
You need to find the answer to this question here: https://discuss.codemirror.net/
@jaywcjlove,
looking for answer there doesn't help. In there it explicitly says that tab key is not bound by default. And the documentation seems to be rather.. terse.
@uiwjs/react-codemirror
, on the other hand, adds it by default, and the wrong one - it is exactly the expected behavior of that function, I believe.
Btw, I found it weird - I'd expect a prop called indentWithTab
to set default indentation to tab, not add a keybinding to tab button to indent with spaces.
@sam-rez,
react-codemirror
uses indentMore
and indentLess
for tab by default, which are exactly that - indenting entire line left/right. You have to change that behavior to make it work:
indentWithTab={false}
to the component. extensions={[ keymap.of([{ key: 'Tab', run: insertTab }]) ]}
extensions={[ keymap.of([{ key: 'Tab', run: insertTab, shift: indentLess }]) ]}
insertTab
and indentLess
are in @codemirror/commands
package, keymap
is in @codemirror/view
package.
Also, if you want shift+tab to shift line(s) left only when you have something selected, you'll have to create your own command, similar to insertTab
command:
import type { StateCommand } from '@codemirror/state';
import { indentLess } from '@codemirror/commands';
export const indentSelectionLess: StateCommand = ({state, dispatch}) => {
if (state.readOnly) return false;
if (state.selection.ranges.some(r => !r.empty)) return indentLess({state, dispatch})
return false;
}
...and if you want tab to insert the default indentation unit (in my case, with tabSize: 2, it is 2 spaces) - you could use something like this:
import type { StateCommand } from '@codemirror/state';
import { indentMore } from '@codemirror/commands';
import { indentUnit } from '@codemirror/language';
export const indentOrInsertTab: StateCommand = ({ state, dispatch }) => {
if (state.readOnly) return false;
if (state.selection.ranges.some((r) => !r.empty)) return indentMore({ state, dispatch });
dispatch(state.update(state.replaceSelection(state.facet(indentUnit)), { scrollIntoView: true, userEvent: 'input' }));
return true;
};
So, final keybinding would look something like this:
{
key: 'Tab',
run: indentOrInsertTab,
shift: indentSelectionLess,
}
that will insert default indentation (spaces or tab if tab is set as indentUnit) when there's nothing selected, indent lines if something is selected, and pressing shift+tab would unindent only when there's something selected.
When I use tab it causes the entire line to shift.
Is there a way to only have it tab from where the cursor is?