Stackedit/src/services/cledit/cleditKeystroke.js
Benoit Schweblin 1d8b67c321 Upgraded eslint
2018-05-06 01:46:33 +01:00

189 lines
5.4 KiB
JavaScript

import cledit from './cleditCore';
function Keystroke(handler, priority) {
this.handler = handler;
this.priority = priority || 100;
}
cledit.Keystroke = Keystroke;
let clearNewline;
const charTypes = Object.create(null);
// Word separators, as in Sublime Text
'./\\()"\'-:,.;<>~!@#$%^&*|+=[]{}`~?'.split('').cl_each((wordSeparator) => {
charTypes[wordSeparator] = 'wordSeparator';
});
charTypes[' '] = 'space';
charTypes['\t'] = 'space';
charTypes['\n'] = 'newLine';
function getNextWordOffset(text, offset, isBackward) {
let previousType;
let result = offset;
while ((isBackward && result > 0) || (!isBackward && result < text.length)) {
const currentType = charTypes[isBackward ? text[result - 1] : text[result]] || 'word';
if (previousType && currentType !== previousType) {
if (previousType === 'word' || currentType === 'space' || previousType === 'newLine' || currentType === 'newLine') {
break;
}
}
previousType = currentType;
if (isBackward) {
result -= 1;
} else {
result += 1;
}
}
return result;
}
cledit.defaultKeystrokes = [
new Keystroke((evt, state, editor) => {
if ((!evt.ctrlKey && !evt.metaKey) || evt.altKey) {
return false;
}
const keyCode = evt.charCode || evt.keyCode;
const keyCodeChar = String.fromCharCode(keyCode).toLowerCase();
let action;
switch (keyCodeChar) {
case 'y':
action = 'redo';
break;
case 'z':
action = evt.shiftKey ? 'redo' : 'undo';
break;
default:
}
if (action) {
evt.preventDefault();
setTimeout(() => editor.undoMgr[action](), 10);
return true;
}
return false;
}),
new Keystroke((evt, state) => {
if (evt.which !== 9 /* tab */ || evt.metaKey || evt.ctrlKey) {
return false;
}
const strSplice = (str, i, remove, add = '') =>
str.slice(0, i) + add + str.slice(i + (+remove || 0));
evt.preventDefault();
const isInverse = evt.shiftKey;
const lf = state.before.lastIndexOf('\n') + 1;
if (isInverse) {
if (/\s/.test(state.before.charAt(lf))) {
state.before = strSplice(state.before, lf, 1);
}
state.selection = state.selection.replace(/^[ \t]/gm, '');
} else if (state.selection) {
state.before = strSplice(state.before, lf, 0, '\t');
state.selection = state.selection.replace(/\n(?=[\s\S])/g, '\n\t');
} else {
state.before += '\t';
}
return true;
}),
new Keystroke((evt, state, editor) => {
if (evt.which !== 13 /* enter */) {
clearNewline = false;
return false;
}
evt.preventDefault();
const lf = state.before.lastIndexOf('\n') + 1;
if (clearNewline) {
state.before = state.before.substring(0, lf);
state.selection = '';
clearNewline = false;
return true;
}
clearNewline = false;
const previousLine = state.before.slice(lf);
const indent = previousLine.match(/^\s*/)[0];
if (indent.length) {
clearNewline = true;
}
editor.undoMgr.setCurrentMode('single');
state.before += `\n${indent}`;
state.selection = '';
return true;
}),
new Keystroke((evt, state, editor) => {
if (evt.which !== 8 /* backspace */ && evt.which !== 46 /* delete */) {
return false;
}
editor.undoMgr.setCurrentMode('delete');
if (!state.selection) {
const isJump = (cledit.Utils.isMac && evt.altKey) || (!cledit.Utils.isMac && evt.ctrlKey);
if (isJump) {
// Custom kill word behavior
const text = state.before + state.after;
const offset = getNextWordOffset(text, state.before.length, evt.which === 8);
if (evt.which === 8) {
state.before = state.before.slice(0, offset);
} else {
state.after = state.after.slice(offset - text.length);
}
evt.preventDefault();
return true;
} else if (evt.which === 8 && state.before.slice(-1) === '\n') {
// Special treatment for end of lines
state.before = state.before.slice(0, -1);
evt.preventDefault();
return true;
} else if (evt.which === 46 && state.after.slice(0, 1) === '\n') {
state.after = state.after.slice(1);
evt.preventDefault();
return true;
}
} else {
state.selection = '';
evt.preventDefault();
return true;
}
return false;
}),
new Keystroke((evt, state, editor) => {
if (evt.which !== 37 /* left arrow */ && evt.which !== 39 /* right arrow */) {
return false;
}
const isJump = (cledit.Utils.isMac && evt.altKey) || (!cledit.Utils.isMac && evt.ctrlKey);
if (!isJump) {
return false;
}
// Custom jump behavior
const textContent = editor.getContent();
const offset = getNextWordOffset(
textContent,
editor.selectionMgr.selectionEnd,
evt.which === 37,
);
if (evt.shiftKey) {
// rebuild the state completely
const min = Math.min(editor.selectionMgr.selectionStart, offset);
const max = Math.max(editor.selectionMgr.selectionStart, offset);
state.before = textContent.slice(0, min);
state.after = textContent.slice(max);
state.selection = textContent.slice(min, max);
state.isBackwardSelection = editor.selectionMgr.selectionStart > offset;
} else {
state.before = textContent.slice(0, offset);
state.after = textContent.slice(offset);
state.selection = '';
}
evt.preventDefault();
return true;
}),
];