UNPKG

alm

Version:

The best IDE for TypeScript

216 lines (215 loc) 8.27 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); /** Imports */ var commands = require("../../commands/commands"); var React = require("react"); var ReactDOM = require("react-dom"); var utils = require("../../../common/utils"); var events = require("../../../common/events"); var monacoUtils = require("../monacoUtils"); /** Load jumpy css */ require('./jumpy.css'); /** * Setup key characters used for jumpy points */ var lowerCharacters = []; for (var i = 'a'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { var key = String.fromCharCode(i); lowerCharacters.push(key); } exports.keys = []; for (var _i = 0, lowerCharacters_1 = lowerCharacters; _i < lowerCharacters_1.length; _i++) { var c1 = lowerCharacters_1[_i]; for (var _a = 0, lowerCharacters_2 = lowerCharacters; _a < lowerCharacters_2.length; _a++) { var c2 = lowerCharacters_2[_a]; exports.keys.push(c1 + c2); } } function getWidgetId(wg) { return "jumpy:" + wg.line + ":" + wg.ch; } /** Gets or creates a state */ function getState(editor) { return editor._jumpyState || (editor._jumpyState = { widgets: [], shown: false, disposible: new events.CompositeDisposible() }); } exports.getState = getState; /** * * The bulk of the logic * */ function addOverlay(editor) { clearAnyOverlay(editor); /** Create the overlays */ var state = createOverlays(editor); /** A clear overlay function just for this editor 🌹 */ var clearOverlay = function () { return clearAnyOverlay(editor); }; // Subscribe to esc to clear state.disposible.add(commands.esc.on(clearOverlay)); /** Subscribe to jump */ state.disposible.add(editor.onKeyDown(function (e) { if (e.keyCode >= monaco.KeyCode.KEY_A && e.keyCode <= monaco.KeyCode.KEY_Z) { // We always prevent ascii chars as the user might have mistyped some keystroke e.preventDefault(); e.stopPropagation(); // The character representation var char = String.fromCharCode(e.browserEvent.which).toLowerCase(); // console.log({char}); // DEBUG var state_1 = getState(editor); if (!state_1.key1) { state_1.key1 = char; // remove not matched state_1.widgets.filter(function (wg) { return !wg.keys.startsWith(state_1.key1); }).forEach(function (wg) { return editor.removeContentWidget(wg.monacoWiget); }); // only keep matched state_1.widgets = state_1.widgets.filter(function (wg) { return wg.keys.startsWith(state_1.key1); }); // remove all if nothing matched if (state_1.widgets.length == 0) { clearOverlay(); } } else { var total_1 = state_1.key1 + char; var matched = state_1.widgets.find(function (wg) { return wg.keys == total_1; }); if (matched) { var position = { lineNumber: matched.line + 1, column: matched.ch + 1 }; editor.setPosition(position); // We actually allow them to jump one line before / one line after // So calling this isn't a bad idea. No-op if the line is in view ;) editor.revealLine(position.lineNumber); } clearOverlay(); } } else { clearOverlay(); } })); /** Best to exit on these conditions too */ state.disposible.add(editor.onDidScrollChange(clearOverlay)); state.disposible.add(editor.onDidChangeCursorSelection(clearOverlay)); state.disposible.add(editor.onDidBlurEditor(clearOverlay)); } /** * Clears previous overlays if any */ function clearAnyOverlay(editor) { var state = getState(editor); if (state.shown) { state.widgets.forEach(function (wg) { return editor.removeContentWidget(wg.monacoWiget); }); state.widgets = []; state.key1 = null; state.key2 = null; state.shown = false; state.disposible.dispose(); } } /** * Renders the overlays on the editor */ function createOverlays(editor) { // The model var doc = editor.getModel(); // DEBUG // console.log(editor); // window.foo = editor; // The text in viewport var range = monacoUtils.getVisibleLines(editor); var text = doc.getValueInRange(range); /** What we use to split the text */ var splitRegex = /^[A-Z]?[0-9a-z]+|^[\{\};]+/; var lineNumbers = []; for (var i = range.startLineNumber; i <= range.endLineNumber; i++) { lineNumbers.push(i); } // keeps track of the next jump point key we can use var keysIndex = 0; var overlayByLines = utils.selectMany(lineNumbers.map(function (lineNumber, i) { var string = doc.getLineContent(lineNumber); var pos = 0; var lineOverlays = []; while (pos < string.length) { var matches = splitRegex.exec(string.substr(pos)); if (matches && matches.length) { var matched = matches[0]; var name_1 = exports.keys[keysIndex++]; var nodeRendered = React.createElement("div", { key: i + ':' + pos, className: "monaco-jumpy", style: {} }, name_1); var node = document.createElement('div'); ReactDOM.render(nodeRendered, node); var widget = { node: node, line: lineNumber - 1, ch: pos, keys: name_1, // This is setup later monacoWiget: null, }; lineOverlays.push(widget); // we want some minimum space between matches pos += Math.max(matched.length, 2); } else { pos++; } } return lineOverlays; })); // Add to dom + State overlayByLines.forEach(function (wg) { wg.monacoWiget = { allowEditorOverflow: true, getId: function () { return getWidgetId(wg); }, getDomNode: function () { return wg.node; }, getPosition: function () { return { position: { lineNumber: wg.line + 1, column: wg.ch + 1 }, preference: [ monaco.editor.ContentWidgetPositionPreference.ABOVE, monaco.editor.ContentWidgetPositionPreference.BELOW, ] }; } }; editor.addContentWidget(wg.monacoWiget); }); // Setup state and return var state = getState(editor); state.widgets = overlayByLines; state.shown = true; state.disposible = new events.CompositeDisposible(); return state; } var CommonEditorRegistry = monaco.CommonEditorRegistry; var EditorAction = monaco.EditorAction; var KeyMod = monaco.KeyMod; var KeyCode = monaco.KeyCode; var EditorContextKeys = monaco.EditorContextKeys; var JumpyAction = /** @class */ (function (_super) { __extends(JumpyAction, _super); function JumpyAction() { return _super.call(this, { id: 'editor.action.jumpy', label: 'Jumpy', alias: 'Jumpy', precondition: EditorContextKeys.Focus, kbOpts: { kbExpr: EditorContextKeys.TextFocus, primary: KeyMod.CtrlCmd | KeyCode.Enter } }) || this; } JumpyAction.prototype.run = function (accessor, editor) { addOverlay(editor); }; return JumpyAction; }(EditorAction)); CommonEditorRegistry.registerEditorAction(new JumpyAction());