UNPKG

@krassowski/jupyterlab-lsp

Version:

Language Server Protocol integration for JupyterLab

150 lines 5.59 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. // (Parts of the FreeTooltip code are copy-paste from Tooltip, ideally this would be PRed be merged) import { HoverBox } from '@jupyterlab/apputils'; import { MimeModel } from '@jupyterlab/rendermime'; import { Tooltip } from '@jupyterlab/tooltip'; import { Widget } from '@lumino/widgets'; import { PositionConverter } from '../converter'; const MIN_HEIGHT = 20; const MAX_HEIGHT = 250; const CLASS_NAME = 'lsp-tooltip'; /** * Tooltip which can be placed at any character, not only at the current position (derived from getCursorPosition) */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore export class FreeTooltip extends Tooltip { constructor(options) { super(options); this.options = options; this._setGeometry(); // TODO: remove once https://github.com/jupyterlab/jupyterlab/pull/11010 is merged & released const model = new MimeModel({ data: options.bundle }); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const content = this._content; content .renderModel(model) .then(() => this._setGeometry()) .catch(console.warn); } handleEvent(event) { if (this.isHidden || this.isDisposed) { return; } const { node } = this; const target = event.target; switch (event.type) { case 'keydown': { const keyCode = event.keyCode; // ESC or Backspace cancel anyways if (node.contains(target) || (!this.options.hideOnKeyPress && keyCode != 27 && keyCode != 8)) { return; } this.dispose(); break; } default: super.handleEvent(event); break; } } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore _setGeometry() { // Find the start of the current token for hover box placement. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const editor = this._editor; const cursor = this.options.position == null ? editor.getCursorPosition() : this.options.position; const end = editor.getOffsetAt(cursor); const line = editor.getLine(cursor.line); if (!line) { return; } let position; switch (this.options.alignment) { case 'start': { const tokens = line.substring(0, end).split(/\W+/); const last = tokens[tokens.length - 1]; const start = last ? end - last.length : end; position = editor.getPositionAt(start); break; } case 'end': { const tokens = line.substring(0, end).split(/\W+/); const last = tokens[tokens.length - 1]; const start = last ? end - last.length : end; position = editor.getPositionAt(start); break; } default: { position = cursor; break; } } if (!position) { return; } const anchor = editor.getCoordinateForPosition(position); const style = window.getComputedStyle(this.node); const paddingLeft = parseInt(style.paddingLeft, 10) || 0; // Calculate the geometry of the tooltip. HoverBox.setGeometry({ anchor, host: editor.host, maxHeight: MAX_HEIGHT, minHeight: MIN_HEIGHT, node: this.node, offset: { horizontal: -1 * paddingLeft }, privilege: this.options.privilege || 'below', style: style }); } } export class EditorTooltipManager { constructor(rendermime_registry) { this.rendermime_registry = rendermime_registry; this.currentTooltip = null; } create(options) { this.remove(); this.currentOptions = options; let { markup, position, adapter } = options; let widget = adapter.widget; const bundle = markup.kind === 'plaintext' ? { 'text/plain': markup.value } : { 'text/markdown': markup.value }; const tooltip = new FreeTooltip(Object.assign(Object.assign({}, (options.tooltip || {})), { anchor: widget.content, bundle: bundle, editor: options.ce_editor, rendermime: this.rendermime_registry, position: PositionConverter.cm_to_ce(position) })); tooltip.addClass(CLASS_NAME); if (options.className) { tooltip.addClass(options.className); } Widget.attach(tooltip, document.body); this.currentTooltip = tooltip; return tooltip; } get position() { return this.currentOptions.position; } isShown(id) { var _a; if (id && this.currentOptions && ((_a = this.currentOptions) === null || _a === void 0 ? void 0 : _a.id) !== id) { return false; } return (this.currentTooltip !== null && !this.currentTooltip.isDisposed && this.currentTooltip.isVisible); } remove() { if (this.currentTooltip !== null) { this.currentTooltip.dispose(); this.currentTooltip = null; } } } //# sourceMappingURL=free_tooltip.js.map