ts-playground-plugin-vim
Version:
Provides Vim keybindings for TypeScript Playground editor.
1,117 lines (1,115 loc) • 292 kB
JavaScript
define(function () { 'use strict';
/**
* An adapter to make CodeMirror's vim bindings work with monaco
*/
// import { TypeOperations } from 'monaco-editor/esm/vs/editor/common/controller/cursorTypeOperations';
var _a = globalThis.monaco, monacoEditor = _a.editor, KeyCode = _a.KeyCode, KeyMod = _a.KeyMod, Range = _a.Range, Position = _a.Position, Selection = _a.Selection, SelectionDirection = _a.SelectionDirection;
var VerticalRevealType = {
Bottom: 4,
};
// for monaco 0.19.x where x < 3
var EditorOptConstants = {
readOnly: 65,
cursorWidth: 20,
fontInfo: 32,
};
var _b = window.navigator, userAgent = _b.userAgent, platform = _b.platform;
var edge = /Edge\/(\d+)/.exec(userAgent);
var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
var mac = ios || /Mac/.test(platform);
var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
function isWordCharBasic(ch) {
return /\w/.test(ch) || ch > "\x80" &&
(ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
}
function Pos(line, column) {
if (!(this instanceof Pos)) {
return new Pos(line, column);
}
this.line = line;
this.ch = column;
}
function signal(cm, signal, args) {
cm.dispatch(signal, args);
}
function dummy(key) {
return function () {
// console.log(key, 'dummy function called with', Array.prototype.slice.call(arguments));
};
}
var StringStream = function (string, tabSize) {
this.pos = this.start = 0;
this.string = string;
this.tabSize = tabSize || 8;
this.lastColumnPos = this.lastColumnValue = 0;
this.lineStart = 0;
};
StringStream.prototype = {
eol: function () { return this.pos >= this.string.length; },
sol: function () { return this.pos == this.lineStart; },
peek: function () { return this.string.charAt(this.pos) || undefined; },
next: function () {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function (match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string")
var ok = ch == match;
else
var ok = ch && (match.test ? match.test(ch) : match(ch));
if (ok) {
++this.pos;
return ch;
}
},
eatWhile: function (match) {
var start = this.pos;
while (this.eat(match)) { }
return this.pos > start;
},
eatSpace: function () {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos)))
++this.pos;
return this.pos > start;
},
skipToEnd: function () { this.pos = this.string.length; },
skipTo: function (ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {
this.pos = found;
return true;
}
},
backUp: function (n) { this.pos -= n; },
column: function () {
throw "not implemented";
},
indentation: function () {
throw "not implemented";
},
match: function (pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
var substr = this.string.substr(this.pos, pattern.length);
if (cased(substr) == cased(pattern)) {
if (consume !== false)
this.pos += pattern.length;
return true;
}
}
else {
var match = this.string.slice(this.pos).match(pattern);
if (match && match.index > 0)
return null;
if (match && consume !== false)
this.pos += match[0].length;
return match;
}
},
current: function () { return this.string.slice(this.start, this.pos); },
hideFirstChars: function (n, inner) {
this.lineStart += n;
try {
return inner();
}
finally {
this.lineStart -= n;
}
}
};
function toCmPos(pos) {
return new Pos(pos.lineNumber - 1, pos.column - 1);
}
function toMonacoPos(pos) {
return new Position(pos.line + 1, pos.ch + 1);
}
var Marker = /** @class */ (function () {
function Marker(cm, id, line, ch) {
this.cm = cm;
this.id = id;
this.lineNumber = line + 1;
this.column = ch + 1;
cm.marks[this.id] = this;
}
Marker.prototype.clear = function () {
delete this.cm.marks[this.id];
};
Marker.prototype.find = function () {
return toCmPos(this);
};
return Marker;
}());
function monacoToCmKey(e, skip) {
if (skip === void 0) { skip = false; }
var addQuotes = true;
var keyName = monaco.KeyCode[e.keyCode];
if (e.key) {
keyName = e.key;
addQuotes = false;
}
var key = keyName;
var skipOnlyShiftCheck = skip;
switch (e.keyCode) {
case KeyCode.Shift:
case KeyCode.Meta:
case KeyCode.Alt:
case KeyCode.Ctrl:
return key;
case KeyCode.Escape:
skipOnlyShiftCheck = true;
key = 'Esc';
break;
}
if (keyName.startsWith('KEY_')) {
key = keyName[keyName.length - 1].toLowerCase();
}
else if (keyName.endsWith('Arrow')) {
skipOnlyShiftCheck = true;
key = keyName.substr(0, keyName.length - 5);
}
else if (keyName.startsWith('US_')) {
key = e.browserEvent.key;
}
if (!skipOnlyShiftCheck && !e.altKey && !e.ctrlKey && !e.metaKey) {
key = e.key || e.browserEvent.key;
}
else {
if (e.altKey) {
key = "Alt-" + key;
}
if (e.ctrlKey) {
key = "Ctrl-" + key;
}
if (e.metaKey) {
key = "Meta-" + key;
}
if (e.shiftKey) {
key = "Shift-" + key;
}
}
if (key.length === 1 && addQuotes) {
key = "'" + key + "'";
}
return key;
}
var CMAdapter = /** @class */ (function () {
function CMAdapter(editor) {
var _this = this;
this.editor = editor;
this.handleKeyDown = function (e) {
// Allow previously registered keydown listeners to handle the event and
// prevent this extension from also handling it.
if (e.browserEvent.defaultPrevented & e.keyCode !== KeyCode.Escape) {
return;
}
if (!_this.attached) {
return;
}
var key = monacoToCmKey(e);
if (_this.replaceMode) {
_this.handleReplaceMode(key, e);
}
if (!key) {
return;
}
if (CMAdapter.keyMap.vim && CMAdapter.keyMap.vim.call) {
var cmd = CMAdapter.keyMap.vim.call(key, _this);
if (cmd) {
e.preventDefault();
e.stopPropagation();
try {
cmd();
}
catch (err) {
console.error(err);
}
}
}
};
this.handleCursorChange = function (e) {
var position = e.position, source = e.source;
var editor = _this.editor;
var selection = editor.getSelection();
if (!_this.ctxInsert.get() && e.source === 'mouse' && selection.isEmpty()) {
var maxCol = editor.getModel().getLineMaxColumn(position.lineNumber);
if (e.position.column === maxCol) {
editor.setPosition(new Position(e.position.lineNumber, maxCol - 1));
return;
}
}
_this.dispatch('cursorActivity', _this, e);
};
this.handleChange = function (e) {
var changes = e.changes;
var change = {
text: changes.reduce(function (acc, change) {
acc.push(change.text);
return acc;
}, []),
origin: '+input'
};
var curOp = _this.curOp = _this.curOp || {};
if (!curOp.changeHandlers) {
curOp.changeHandlers = _this.listeners['change'] && _this.listeners['change'].slice();
}
if (_this.virtualSelectionMode()) {
return;
}
if (!curOp.lastChange) {
curOp.lastChange = curOp.change = change;
}
else {
curOp.lastChange.next = curOp.lastChange = change;
}
_this.dispatch('change', _this, change);
};
this.editor = editor;
this.state = {};
this.marks = {};
this.$uid = 0;
this.disposables = [];
this.listeners = {};
this.curOp = {};
this.attached = false;
this.statusBar = null;
this.addLocalListeners();
this.ctxInsert = this.editor.createContextKey('insertMode', true);
}
CMAdapter.prototype.attach = function () {
CMAdapter.keyMap.vim.attach(this);
};
CMAdapter.prototype.addLocalListeners = function () {
this.disposables.push(this.editor.onDidChangeCursorPosition(this.handleCursorChange), this.editor.onDidChangeModelContent(this.handleChange), this.editor.onKeyDown(this.handleKeyDown));
};
CMAdapter.prototype.handleReplaceMode = function (key, e) {
var fromReplace = false;
var char = key;
var pos = this.editor.getPosition();
var range = new Range(pos.lineNumber, pos.column, pos.lineNumber, pos.column + 1);
var forceMoveMarkers = true;
if (key.startsWith('\'')) {
char = key[1];
}
else if (char === 'Enter') {
char = '\n';
}
else if (char === 'Backspace') {
var lastItem = this.replaceStack.pop();
if (!lastItem) {
return;
}
fromReplace = true;
char = lastItem;
range = new Range(pos.lineNumber, pos.column, pos.lineNumber, pos.column - 1);
}
else {
return;
}
e.preventDefault();
e.stopPropagation();
if (!this.replaceStack) {
this.replaceStack = [];
}
if (!fromReplace) {
this.replaceStack.push(this.editor.getModel().getValueInRange(range));
}
this.editor.executeEdits('vim', [{
text: char,
range: range,
forceMoveMarkers: forceMoveMarkers,
}]);
if (fromReplace) {
this.editor.setPosition(range.getStartPosition());
}
};
CMAdapter.prototype.setOption = function (key, value) {
this.state[key] = value;
if (key === 'theme') {
monacoEditor.setTheme(value);
}
};
CMAdapter.prototype.getConfiguration = function () {
var editor = this.editor;
var opts = EditorOptConstants;
if (typeof editor.getConfiguration === 'function') {
return editor.getConfiguration();
}
else if ('EditorOption' in monacoEditor) { // for monaco 0.19.3 onwards
opts = monacoEditor.EditorOption;
}
return {
readOnly: editor.getOption(opts.readOnly),
viewInfo: {
cursorWidth: editor.getOption(opts.cursorWidth),
},
fontInfo: editor.getOption(opts.fontInfo),
};
};
CMAdapter.prototype.getOption = function (key) {
if (key === 'readOnly') {
return this.getConfiguration().readOnly;
}
else if (key === 'firstLineNumber') {
return this.firstLine() + 1;
}
else if (key === 'indentWithTabs') {
return !this.editor.getModel().getOptions().insertSpaces;
}
else {
if (typeof this.editor.getConfiguration === 'function') {
return this.editor.getRawConfiguration()[key];
}
return this.editor.getRawOptions()[key];
}
};
CMAdapter.prototype.dispatch = function (signal) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var listeners = this.listeners[signal];
if (!listeners) {
return;
}
listeners.forEach(function (handler) { return handler.apply(void 0, args); });
};
CMAdapter.prototype.on = function (event, handler) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push(handler);
};
CMAdapter.prototype.off = function (event, handler) {
var listeners = this.listeners[event];
if (!listeners) {
return;
}
this.listeners[event] = listeners.filter(function (l) { return l !== handler; });
};
CMAdapter.prototype.firstLine = function () {
return 0;
};
CMAdapter.prototype.lastLine = function () {
return this.lineCount() - 1;
};
CMAdapter.prototype.lineCount = function () {
return this.editor.getModel().getLineCount();
};
CMAdapter.prototype.defaultTextHeight = function () {
return 1;
};
CMAdapter.prototype.getLine = function (line) {
if (line < 0) {
return '';
}
var model = this.editor.getModel();
var maxLines = model.getLineCount();
if (line + 1 > maxLines) {
line = maxLines - 1;
}
return this.editor.getModel().getLineContent(line + 1);
};
CMAdapter.prototype.getAnchorForSelection = function (selection) {
if (selection.isEmpty()) {
return selection.getPosition();
}
var selDir = selection.getDirection();
return (selDir === SelectionDirection.LTR) ? selection.getStartPosition() : selection.getEndPosition();
};
CMAdapter.prototype.getHeadForSelection = function (selection) {
if (selection.isEmpty()) {
return selection.getPosition();
}
var selDir = selection.getDirection();
return (selDir === SelectionDirection.LTR) ? selection.getEndPosition() : selection.getStartPosition();
};
CMAdapter.prototype.getCursor = function (type) {
if (type === void 0) { type = null; }
if (!type) {
return toCmPos(this.editor.getPosition());
}
var sel = this.editor.getSelection();
var pos;
if (sel.isEmpty()) {
pos = sel.getPosition();
}
else if (type === 'anchor') {
pos = this.getAnchorForSelection(sel);
}
else {
pos = this.getHeadForSelection(sel);
}
return toCmPos(pos);
};
CMAdapter.prototype.getRange = function (start, end) {
var p1 = toMonacoPos(start);
var p2 = toMonacoPos(end);
return this.editor.getModel().getValueInRange(Range.fromPositions(p1, p2));
};
CMAdapter.prototype.getSelection = function () {
return this.editor.getModel().getValueInRange(this.editor.getSelection());
};
CMAdapter.prototype.replaceRange = function (text, start, end) {
var p1 = toMonacoPos(start);
var p2 = !end ? p1 : toMonacoPos(end);
this.editor.executeEdits('vim', [{
text: text,
range: Range.fromPositions(p1, p2),
}]);
// @TODO - Check if this breaks any other expectation
this.pushUndoStop();
};
CMAdapter.prototype.pushUndoStop = function () {
this.editor.pushUndoStop();
};
CMAdapter.prototype.setCursor = function (line, ch) {
var pos = line;
if (typeof line !== 'object') {
pos = {};
pos.line = line;
pos.ch = ch;
}
var monacoPos = this.editor.getModel().validatePosition(toMonacoPos(pos));
this.editor.setPosition(toMonacoPos(pos));
this.editor.revealPosition(monacoPos);
};
CMAdapter.prototype.somethingSelected = function () {
return !this.editor.getSelection().isEmpty();
};
CMAdapter.prototype.operation = function (fn, force) {
return fn();
};
CMAdapter.prototype.listSelections = function () {
var _this = this;
var selections = this.editor.getSelections();
if (!selections.length || this.inVirtualSelectionMode) {
return [{
anchor: this.getCursor('anchor'),
head: this.getCursor('head'),
}];
}
return selections.map(function (sel) {
var pos = sel.getPosition();
var start = sel.getStartPosition();
var end = sel.getEndPosition();
return {
anchor: _this.clipPos(toCmPos(_this.getAnchorForSelection(sel))),
head: _this.clipPos(toCmPos(_this.getHeadForSelection(sel))),
};
});
};
CMAdapter.prototype.focus = function () {
this.editor.focus();
};
CMAdapter.prototype.setSelections = function (selections, primIndex) {
var hasSel = !!this.editor.getSelections().length;
var sels = selections.map(function (sel, index) {
var anchor = sel.anchor, head = sel.head;
if (hasSel) {
return Selection.fromPositions(toMonacoPos(anchor), toMonacoPos(head));
}
else {
return Selection.fromPositions(toMonacoPos(head), toMonacoPos(anchor));
}
});
if (!primIndex) {
sels.reverse();
}
else if (sels[primIndex]) {
sels.push(sels.splice(primIndex, 1)[0]);
}
if (!sels.length) {
return;
}
var sel = sels[0];
var posToReveal;
if (sel.getDirection() === SelectionDirection.LTR) {
posToReveal = sel.getEndPosition();
}
else {
posToReveal = sel.getStartPosition();
}
this.editor.setSelections(sels);
this.editor.revealPosition(posToReveal);
};
CMAdapter.prototype.setSelection = function (frm, to) {
var range = Range.fromPositions(toMonacoPos(frm), toMonacoPos(to));
this.editor.setSelection(range);
};
CMAdapter.prototype.getSelections = function () {
var editor = this.editor;
return editor.getSelections().map(function (sel) { return editor.getModel().getValueInRange(sel); });
};
CMAdapter.prototype.replaceSelections = function (texts) {
var editor = this.editor;
editor.getSelections().forEach(function (sel, index) {
editor.executeEdits('vim', [{
range: sel,
text: texts[index],
forceMoveMarkers: false,
}]);
});
};
CMAdapter.prototype.toggleOverwrite = function (toggle) {
if (toggle) {
this.enterVimMode();
this.replaceMode = true;
}
else {
this.leaveVimMode();
this.replaceMode = false;
this.replaceStack = [];
}
};
CMAdapter.prototype.charCoords = function (pos, mode) {
return {
top: pos.line,
left: pos.ch,
};
};
CMAdapter.prototype.coordsChar = function (pos, mode) {
};
CMAdapter.prototype.clipPos = function (p) {
var pos = this.editor.getModel().validatePosition(toMonacoPos(p));
return toCmPos(pos);
};
CMAdapter.prototype.setBookmark = function (cursor, options) {
var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch);
if (!options || !options.insertLeft) {
bm.$insertRight = true;
}
this.marks[bm.id] = bm;
return bm;
};
CMAdapter.prototype.getScrollInfo = function () {
var editor = this.editor;
var range = editor.getVisibleRanges()[0];
return {
left: 0,
top: range.startLineNumber - 1,
height: editor.getModel().getLineCount(),
clientHeight: range.endLineNumber - range.startLineNumber + 1,
};
};
CMAdapter.prototype.triggerEditorAction = function (action) {
this.editor.trigger('vim', action);
};
CMAdapter.prototype.dispose = function () {
this.dispatch('dispose');
this.removeOverlay();
if (CMAdapter.keyMap.vim) {
CMAdapter.keyMap.vim.detach(this);
}
this.disposables.forEach(function (d) { return d.dispose(); });
};
CMAdapter.prototype.getInputField = function () { };
CMAdapter.prototype.getWrapperElement = function () { };
CMAdapter.prototype.enterVimMode = function (toVim) {
this.ctxInsert.set(false);
var config = this.getConfiguration();
this.initialCursorWidth = config.viewInfo.cursorWidth || 0;
this.editor.updateOptions({
cursorWidth: config.fontInfo.typicalFullwidthCharacterWidth,
cursorBlinking: 'solid',
});
};
CMAdapter.prototype.leaveVimMode = function () {
this.ctxInsert.set(true);
this.editor.updateOptions({
cursorWidth: this.initialCursorWidth || 0,
cursorBlinking: 'blink',
});
};
CMAdapter.prototype.virtualSelectionMode = function () {
return this.inVirtualSelectionMode;
};
CMAdapter.prototype.markText = function () {
// only used for fat-cursor, not needed
return { clear: function () { }, find: function () { } };
};
CMAdapter.prototype.getUserVisibleLines = function () {
var ranges = this.editor.getVisibleRanges();
if (!ranges.length) {
return {
top: 0,
bottom: 0,
};
}
var res = {
top: Infinity,
bottom: 0,
};
ranges.reduce(function (acc, range) {
if (range.startLineNumber < acc.top) {
acc.top = range.startLineNumber;
}
if (range.endLineNumber > acc.bottom) {
acc.bottom = range.endLineNumber;
}
return acc;
}, res);
res.top -= 1;
res.bottom -= 1;
return res;
};
CMAdapter.prototype.findPosV = function (startPos, amount, unit) {
var editor = this.editor;
var finalAmount = amount;
var pos = toMonacoPos(startPos);
if (unit === 'page') {
var editorHeight = editor.getLayoutInfo().height;
var lineHeight = this.getConfiguration().fontInfo.lineHeight;
finalAmount = finalAmount * Math.floor(editorHeight / lineHeight);
}
if (unit === 'line') {
pos.lineNumber += finalAmount;
}
return toCmPos(pos);
};
CMAdapter.prototype.findMatchingBracket = function (pos) {
var mPos = toMonacoPos(pos);
var res = this.editor.getModel().matchBracket(mPos);
if (!res || !(res.length === 2)) {
return {
to: null,
};
}
return {
to: toCmPos(res[1].getStartPosition()),
};
};
CMAdapter.prototype.findFirstNonWhiteSpaceCharacter = function (line) {
return this.editor.getModel().getLineFirstNonWhitespaceColumn(line + 1) - 1;
};
CMAdapter.prototype.scrollTo = function (x, y) {
if (!x && !y) {
return;
}
if (!x) {
if (y < 0) {
y = this.editor.getPosition().lineNumber - y;
}
this.editor.setScrollTop(this.editor.getTopForLineNumber(y + 1));
}
};
CMAdapter.prototype.moveCurrentLineTo = function (viewPosition) {
var editor = this.editor;
var pos = editor.getPosition();
var range = Range.fromPositions(pos, pos);
switch (viewPosition) {
case 'top':
editor.revealRangeAtTop(range);
return;
case 'center':
editor.revealRangeInCenter(range);
return;
case 'bottom':
// private api. no other way
editor._revealRange(range, VerticalRevealType.Bottom);
return;
}
};
CMAdapter.prototype.getSearchCursor = function (query, pos, caseFold) {
var matchCase = false;
var isRegex = false;
if (query instanceof RegExp && !query.global) {
matchCase = !query.ignoreCase;
query = query.source;
isRegex = true;
}
if (pos.ch == undefined)
pos.ch = Number.MAX_VALUE;
var monacoPos = toMonacoPos(pos);
var context = this;
var editor = this.editor;
var lastSearch = null;
var model = editor.getModel();
var matches = model.findMatches(query, false, isRegex, matchCase) || [];
return {
getMatches: function () { return matches; },
findNext: function () { return this.find(false); },
findPrevious: function () { return this.find(true); },
jumpTo: function (index) {
if (!matches || !matches.length) {
return false;
}
var match = matches[index];
lastSearch = match.range;
context.highlightRanges([lastSearch], 'currentFindMatch');
context.highlightRanges(matches.map(function (m) { return m.range; }).filter(function (r) { return !r.equalsRange(lastSearch); }));
return lastSearch;
},
find: function (back) {
if (!matches || !matches.length) {
return false;
}
var match;
if (back) {
var pos_1 = lastSearch ? lastSearch.getStartPosition() : monacoPos;
match = model.findPreviousMatch(query, pos_1, isRegex, matchCase);
if (!match || !match.range.getStartPosition().isBeforeOrEqual(pos_1)) {
return false;
}
}
else {
var pos_2 = lastSearch ? lastSearch.getEndPosition() : monacoPos;
match = model.findNextMatch(query, pos_2, isRegex, matchCase);
if (!match || !pos_2.isBeforeOrEqual(match.range.getStartPosition())) {
return false;
}
}
lastSearch = match.range;
context.highlightRanges([lastSearch], 'currentFindMatch');
context.highlightRanges(matches.map(function (m) { return m.range; }).filter(function (r) { return !r.equalsRange(lastSearch); }));
return lastSearch;
},
from: function () {
return lastSearch && toCmPos(lastSearch.getStartPosition());
},
to: function () {
return lastSearch && toCmPos(lastSearch.getEndPosition());
},
replace: function (text) {
if (lastSearch) {
editor.executeEdits('vim', [{
range: lastSearch,
text: text,
forceMoveMarkers: true,
}]);
lastSearch.setEndPosition(editor.getPosition());
editor.setPosition(lastSearch.getStartPosition());
}
}
};
};
CMAdapter.prototype.highlightRanges = function (ranges, className) {
if (className === void 0) { className = 'findMatch'; }
var decorationKey = "decoration" + className;
this[decorationKey] = this.editor.deltaDecorations(this[decorationKey] || [], ranges.map(function (range) { return ({
range: range,
options: {
stickiness: monacoEditor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
zIndex: 13,
className: className,
showIfCollapsed: true,
},
}); }));
return this[decorationKey];
};
CMAdapter.prototype.addOverlay = function (_a, hasBoundary, style) {
var query = _a.query;
var matchCase = false;
var isRegex = false;
if (query && query instanceof RegExp && !query.global) {
isRegex = true;
matchCase = !query.ignoreCase;
query = query.source;
}
var match = this.editor.getModel().findNextMatch(query, this.editor.getPosition(), isRegex, matchCase);
if (!match || !match.range) {
return;
}
this.highlightRanges([match.range]);
};
CMAdapter.prototype.removeOverlay = function () {
var _this = this;
['currentFindMatch', 'findMatch'].forEach(function (key) {
_this.editor.deltaDecorations(_this["decoration" + key] || [], []);
});
};
CMAdapter.prototype.scrollIntoView = function (pos) {
if (!pos) {
return;
}
this.editor.revealPosition(toMonacoPos(pos));
};
CMAdapter.prototype.moveH = function (units, type) {
if (type !== 'char') {
return;
}
var pos = this.editor.getPosition();
this.editor.setPosition(new Position(pos.lineNumber, pos.column + units));
};
/**
* Uses internal apis which not sure why is internal
*/
CMAdapter.prototype.scanForBracket = function (pos, dir, dd, config) {
var mPos = toMonacoPos(pos);
var model = this.editor.getModel();
var range = model.matchBracket(mPos);
if (!range || range.length !== 2) {
var bracket = '{([';
for (var i = 0; i < bracket.length; i++) {
var bracketRange = model.findMatchingBracketUp(bracket[i], mPos);
if (bracketRange) {
range = model.matchBracket(bracketRange.getEndPosition());
break;
}
}
}
if (!range || range.length !== 2) {
return null;
}
var res;
if (dir === -1) {
res = range[1].getStartPosition();
}
else {
res = range[0].getStartPosition();
}
return {
pos: toCmPos(res),
ch: model.getValueInRange(dir === -1 ? range[0] : range[1]),
};
};
CMAdapter.prototype.indexFromPos = function (pos) {
return this.editor.getModel().getOffsetAt(toMonacoPos(pos));
};
CMAdapter.prototype.posFromIndex = function (offset) {
return toCmPos(this.editor.getModel().getPositionAt(offset));
};
CMAdapter.prototype.indentLine = function (line, indentRight) {
var editor = this.editor;
var cursors = editor._getCursors();
var pos = new Position(line + 1, 1);
var sel = Selection.fromPositions(pos, pos);
// no other way than to use internal apis to preserve the undoStack for a batch of indents
// editor.executeCommands(
// `editor.action.${indentRight ? 'indent' : 'outdent'}Lines`,
// TypeOperations[indentRight ? 'indent' : 'outdent'](cursors.context.config, this.editor.getModel(), [sel]),
// );
};
CMAdapter.prototype.setStatusBar = function (statusBar) {
this.statusBar = statusBar;
};
CMAdapter.prototype.openDialog = function (html, callback, options) {
if (!this.statusBar) {
return;
}
return this.statusBar.setSec(html, callback, options);
};
CMAdapter.prototype.openNotification = function (html) {
if (!this.statusBar) {
return;
}
this.statusBar.showNotification(html);
};
CMAdapter.Pos = Pos;
CMAdapter.signal = signal;
CMAdapter.on = dummy();
CMAdapter.off = dummy();
CMAdapter.addClass = dummy();
CMAdapter.rmClass = dummy();
CMAdapter.defineOption = dummy();
CMAdapter.keyMap = {
'default': function (key) {
return function (cm) {
return true;
};
}
};
CMAdapter.isWordChar = isWordCharBasic;
CMAdapter.keyName = monacoToCmKey;
CMAdapter.StringStream = StringStream;
CMAdapter.e_stop = function (e) {
if (e.stopPropagation) {
e.stopPropagation();
}
else {
e.cancelBubble = true;
}
CMAdapter.e_preventDefault(e);
return false;
};
CMAdapter.e_preventDefault = function (e) {
if (e.preventDefault) {
e.preventDefault();
if (e.browserEvent) {
e.browserEvent.preventDefault();
}
}
else {
e.returnValue = false;
}
return false;
};
CMAdapter.commands = {
redo: function (cm) {
cm.triggerEditorAction('redo');
},
undo: function (cm) {
cm.triggerEditorAction('undo');
},
newlineAndIndent: function (cm) {
cm.triggerEditorAction('editor.action.insertLineAfter');
}
};
CMAdapter.lookupKey = function lookupKey(key, map, handle) {
if (typeof map === 'string') {
map = CMAdapter.keyMap[map];
}
var found = typeof map == "function" ? map(key) : map[key];
if (found === false)
return "nothing";
if (found === "...")
return "multi";
if (found != null && handle(found))
return "handled";
if (map.fallthrough) {
if (!Array.isArray(map.fallthrough))
return lookupKey(key, map.fallthrough, handle);
for (var i = 0; i < map.fallthrough.length; i++) {
var result = lookupKey(key, map.fallthrough[i], handle);
if (result)
return result;
}
}
};
CMAdapter.defineExtension = function (name, fn) {
CMAdapter.prototype[name] = fn;
};
return CMAdapter;
}());
/* eslint-disable */
var defaultKeymap = [
// Key to key mapping. This goes first to make it possible to override
// existing mappings.
{ keys: '<Left>', type: 'keyToKey', toKeys: 'h' },
{ keys: '<Right>', type: 'keyToKey', toKeys: 'l' },
{ keys: '<Up>', type: 'keyToKey', toKeys: 'k' },
{ keys: '<Down>', type: 'keyToKey', toKeys: 'j' },
{ keys: '<Space>', type: 'keyToKey', toKeys: 'l' },
{ keys: '<BS>', type: 'keyToKey', toKeys: 'h', context: 'normal' },
{ keys: '<C-Space>', type: 'keyToKey', toKeys: 'W' },
{ keys: '<C-BS>', type: 'keyToKey', toKeys: 'B', context: 'normal' },
{ keys: '<S-Space>', type: 'keyToKey', toKeys: 'w' },
{ keys: '<S-BS>', type: 'keyToKey', toKeys: 'b', context: 'normal' },
{ keys: '<C-n>', type: 'keyToKey', toKeys: 'j' },
{ keys: '<C-p>', type: 'keyToKey', toKeys: 'k' },
{ keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>' },
{ keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>' },
{ keys: '<C-[>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
{ keys: '<C-c>', type: 'keyToKey', toKeys: '<Esc>', context: 'insert' },
{ keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' },
{ keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual' },
{ keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' },
{ keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' },
{ keys: '<Home>', type: 'keyToKey', toKeys: '0' },
{ keys: '<End>', type: 'keyToKey', toKeys: '$' },
{ keys: '<PageUp>', type: 'keyToKey', toKeys: '<C-b>' },
{ keys: '<PageDown>', type: 'keyToKey', toKeys: '<C-f>' },
{ keys: '<CR>', type: 'keyToKey', toKeys: 'j^', context: 'normal' },
{ keys: '<CR>', type: 'keyToKey', toKeys: 'j^', context: 'visual' },
{ keys: '<Ins>', type: 'action', action: 'toggleOverwrite', context: 'insert' },
// Motions
{ keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true } },
{ keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true } },
{ keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true } },
{ keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false } },
{ keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true } },
{ keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true } },
{ keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true } },
{ keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true } },
{ keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false } },
{ keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false } },
{ keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true } },
{ keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true } },
{ keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true } },
{ keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false } },
{ keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true } },
{ keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true } },
{ keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true } },
{ keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true } },
{ keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true } },
{ keys: '(', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: false } },
{ keys: ')', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: true } },
{ keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true } },
{ keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false } },
{ keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true } },
{ keys: '<C-u>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true } },
{ keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true } },
{ keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true } },
{ keys: '0', type: 'motion', motion: 'moveToStartOfLine' },
{ keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' },
{ keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar: true } },
{ keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar: true } },
{ keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar: true, repeatOffset: -1 } },
{ keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true } },
{ keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true } },
{ keys: 'f<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true, inclusive: true } },
{ keys: 'F<character>', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false } },
{ keys: 't<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true } },
{ keys: 'T<character>', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false } },
{ keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true } },
{ keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false } },
{ keys: '\'<character>', type: 'motion', motion: 'goToMark', motionArgs: { toJumplist: true, linewise: true } },
{ keys: '`<character>', type: 'motion', motion: 'goToMark', motionArgs: { toJumplist: true } },
{ keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } },
{ keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } },
{ keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } },
{ keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } },
// the next two aren't motions but must come before more general motion declarations
{ keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true } },
{ keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true } },
{ keys: ']<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true } },
{ keys: '[<character>', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true } },
{ keys: '|', type: 'motion', motion: 'moveToColumn' },
{ keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context: 'visual' },
{ keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: { sameLine: true }, context: 'visual' },
// Operators
{ keys: 'd', type: 'operator', operator: 'delete' },
{ keys: 'y', type: 'operator', operator: 'yank' },
{ keys: 'c', type: 'operator', operator: 'change' },
{ keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true } },
{ keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false } },
{ keys: 'g~', type: 'operator', operator: 'changeCase' },
{ keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: { toLower: true }, isEdit: true },
{ keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: { toLower: false }, isEdit: true },
{ keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true } },
{ keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true } },
// Operator-Motion dual commands
{ keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false } },
{ keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true } },
{ keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal' },
{ keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual' },
{ keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'expandToLine', motionArgs: { linewise: true }, context: 'normal' },
{ keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual' },
{ keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal' },
{ keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual' },
{ keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal' },
{ keys: '~', type: 'operator', operator: 'changeCase', context: 'visual' },
{ keys: '<C-w>', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' },
// Actions
{ keys: '<C-i>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true } },
{ keys: '<C-o>', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false } },
{ keys: '<C-e>', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true } },
{ keys: '<C-y>', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true } },
{ keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' },
{ keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' },
{ keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' },
{ keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' },
{ keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }, context: 'normal' },
{ keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' },
{ keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' },
{ keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' },
{ keys: 'v', type: 'action', action: 'toggleVisualMode' },
{ keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true } },
{ keys: '<C-v>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true } },
{ keys: '<C-q>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true } },
{ keys: 'gv', type: 'action', action: 'reselectLastSelection' },
{ keys: 'J', type: 'action', action: 'joinLines', isEdit: true },
{ keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true } },
{ keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true } },
{ keys: 'r<character>', type: 'action', action: 'replace', isEdit: true },
{ keys: '@<character>', type: 'action', action: 'replayMacro' },
{ keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' },
// Handle Replace-mode as a special case of insert mode.
{ keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true } },
{ keys: 'u', type: 'action', action: 'undo', context: 'normal' },
{ keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: { toLower: true }, context: 'visual', isEdit: true },
{ keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: { toLower: false }, context: 'visual', isEdit: true },
{ keys: '<C-r>', type: 'action', action: 'redo' },
{ keys: 'm<character>', type: 'action', action: 'setMark' },
{ keys