UNPKG

monaco-editor-core

Version:

A browser based code editor

401 lines (400 loc) • 15 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Position } from './position.js'; /** * A range in the editor. (startLineNumber,startColumn) is <= (endLineNumber,endColumn) */ export class Range { constructor(startLineNumber, startColumn, endLineNumber, endColumn) { if ((startLineNumber > endLineNumber) || (startLineNumber === endLineNumber && startColumn > endColumn)) { this.startLineNumber = endLineNumber; this.startColumn = endColumn; this.endLineNumber = startLineNumber; this.endColumn = startColumn; } else { this.startLineNumber = startLineNumber; this.startColumn = startColumn; this.endLineNumber = endLineNumber; this.endColumn = endColumn; } } /** * Test if this range is empty. */ isEmpty() { return Range.isEmpty(this); } /** * Test if `range` is empty. */ static isEmpty(range) { return (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn); } /** * Test if position is in this range. If the position is at the edges, will return true. */ containsPosition(position) { return Range.containsPosition(this, position); } /** * Test if `position` is in `range`. If the position is at the edges, will return true. */ static containsPosition(range, position) { if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) { return false; } if (position.lineNumber === range.startLineNumber && position.column < range.startColumn) { return false; } if (position.lineNumber === range.endLineNumber && position.column > range.endColumn) { return false; } return true; } /** * Test if `position` is in `range`. If the position is at the edges, will return false. * @internal */ static strictContainsPosition(range, position) { if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) { return false; } if (position.lineNumber === range.startLineNumber && position.column <= range.startColumn) { return false; } if (position.lineNumber === range.endLineNumber && position.column >= range.endColumn) { return false; } return true; } /** * Test if range is in this range. If the range is equal to this range, will return true. */ containsRange(range) { return Range.containsRange(this, range); } /** * Test if `otherRange` is in `range`. If the ranges are equal, will return true. */ static containsRange(range, otherRange) { if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) { return false; } if (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) { return false; } if (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn < range.startColumn) { return false; } if (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn > range.endColumn) { return false; } return true; } /** * Test if `range` is strictly in this range. `range` must start after and end before this range for the result to be true. */ strictContainsRange(range) { return Range.strictContainsRange(this, range); } /** * Test if `otherRange` is strictly in `range` (must start after, and end before). If the ranges are equal, will return false. */ static strictContainsRange(range, otherRange) { if (otherRange.startLineNumber < range.startLineNumber || otherRange.endLineNumber < range.startLineNumber) { return false; } if (otherRange.startLineNumber > range.endLineNumber || otherRange.endLineNumber > range.endLineNumber) { return false; } if (otherRange.startLineNumber === range.startLineNumber && otherRange.startColumn <= range.startColumn) { return false; } if (otherRange.endLineNumber === range.endLineNumber && otherRange.endColumn >= range.endColumn) { return false; } return true; } /** * A reunion of the two ranges. * The smallest position will be used as the start point, and the largest one as the end point. */ plusRange(range) { return Range.plusRange(this, range); } /** * A reunion of the two ranges. * The smallest position will be used as the start point, and the largest one as the end point. */ static plusRange(a, b) { let startLineNumber; let startColumn; let endLineNumber; let endColumn; if (b.startLineNumber < a.startLineNumber) { startLineNumber = b.startLineNumber; startColumn = b.startColumn; } else if (b.startLineNumber === a.startLineNumber) { startLineNumber = b.startLineNumber; startColumn = Math.min(b.startColumn, a.startColumn); } else { startLineNumber = a.startLineNumber; startColumn = a.startColumn; } if (b.endLineNumber > a.endLineNumber) { endLineNumber = b.endLineNumber; endColumn = b.endColumn; } else if (b.endLineNumber === a.endLineNumber) { endLineNumber = b.endLineNumber; endColumn = Math.max(b.endColumn, a.endColumn); } else { endLineNumber = a.endLineNumber; endColumn = a.endColumn; } return new Range(startLineNumber, startColumn, endLineNumber, endColumn); } /** * A intersection of the two ranges. */ intersectRanges(range) { return Range.intersectRanges(this, range); } /** * A intersection of the two ranges. */ static intersectRanges(a, b) { let resultStartLineNumber = a.startLineNumber; let resultStartColumn = a.startColumn; let resultEndLineNumber = a.endLineNumber; let resultEndColumn = a.endColumn; const otherStartLineNumber = b.startLineNumber; const otherStartColumn = b.startColumn; const otherEndLineNumber = b.endLineNumber; const otherEndColumn = b.endColumn; if (resultStartLineNumber < otherStartLineNumber) { resultStartLineNumber = otherStartLineNumber; resultStartColumn = otherStartColumn; } else if (resultStartLineNumber === otherStartLineNumber) { resultStartColumn = Math.max(resultStartColumn, otherStartColumn); } if (resultEndLineNumber > otherEndLineNumber) { resultEndLineNumber = otherEndLineNumber; resultEndColumn = otherEndColumn; } else if (resultEndLineNumber === otherEndLineNumber) { resultEndColumn = Math.min(resultEndColumn, otherEndColumn); } // Check if selection is now empty if (resultStartLineNumber > resultEndLineNumber) { return null; } if (resultStartLineNumber === resultEndLineNumber && resultStartColumn > resultEndColumn) { return null; } return new Range(resultStartLineNumber, resultStartColumn, resultEndLineNumber, resultEndColumn); } /** * Test if this range equals other. */ equalsRange(other) { return Range.equalsRange(this, other); } /** * Test if range `a` equals `b`. */ static equalsRange(a, b) { if (!a && !b) { return true; } return (!!a && !!b && a.startLineNumber === b.startLineNumber && a.startColumn === b.startColumn && a.endLineNumber === b.endLineNumber && a.endColumn === b.endColumn); } /** * Return the end position (which will be after or equal to the start position) */ getEndPosition() { return Range.getEndPosition(this); } /** * Return the end position (which will be after or equal to the start position) */ static getEndPosition(range) { return new Position(range.endLineNumber, range.endColumn); } /** * Return the start position (which will be before or equal to the end position) */ getStartPosition() { return Range.getStartPosition(this); } /** * Return the start position (which will be before or equal to the end position) */ static getStartPosition(range) { return new Position(range.startLineNumber, range.startColumn); } /** * Transform to a user presentable string representation. */ toString() { return '[' + this.startLineNumber + ',' + this.startColumn + ' -> ' + this.endLineNumber + ',' + this.endColumn + ']'; } /** * Create a new range using this range's start position, and using endLineNumber and endColumn as the end position. */ setEndPosition(endLineNumber, endColumn) { return new Range(this.startLineNumber, this.startColumn, endLineNumber, endColumn); } /** * Create a new range using this range's end position, and using startLineNumber and startColumn as the start position. */ setStartPosition(startLineNumber, startColumn) { return new Range(startLineNumber, startColumn, this.endLineNumber, this.endColumn); } /** * Create a new empty range using this range's start position. */ collapseToStart() { return Range.collapseToStart(this); } /** * Create a new empty range using this range's start position. */ static collapseToStart(range) { return new Range(range.startLineNumber, range.startColumn, range.startLineNumber, range.startColumn); } /** * Create a new empty range using this range's end position. */ collapseToEnd() { return Range.collapseToEnd(this); } /** * Create a new empty range using this range's end position. */ static collapseToEnd(range) { return new Range(range.endLineNumber, range.endColumn, range.endLineNumber, range.endColumn); } /** * Moves the range by the given amount of lines. */ delta(lineCount) { return new Range(this.startLineNumber + lineCount, this.startColumn, this.endLineNumber + lineCount, this.endColumn); } // --- static fromPositions(start, end = start) { return new Range(start.lineNumber, start.column, end.lineNumber, end.column); } static lift(range) { if (!range) { return null; } return new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } /** * Test if `obj` is an `IRange`. */ static isIRange(obj) { return (obj && (typeof obj.startLineNumber === 'number') && (typeof obj.startColumn === 'number') && (typeof obj.endLineNumber === 'number') && (typeof obj.endColumn === 'number')); } /** * Test if the two ranges are touching in any way. */ static areIntersectingOrTouching(a, b) { // Check if `a` is before `b` if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn < b.startColumn)) { return false; } // Check if `b` is before `a` if (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn < a.startColumn)) { return false; } // These ranges must intersect return true; } /** * Test if the two ranges are intersecting. If the ranges are touching it returns true. */ static areIntersecting(a, b) { // Check if `a` is before `b` if (a.endLineNumber < b.startLineNumber || (a.endLineNumber === b.startLineNumber && a.endColumn <= b.startColumn)) { return false; } // Check if `b` is before `a` if (b.endLineNumber < a.startLineNumber || (b.endLineNumber === a.startLineNumber && b.endColumn <= a.startColumn)) { return false; } // These ranges must intersect return true; } /** * A function that compares ranges, useful for sorting ranges * It will first compare ranges on the startPosition and then on the endPosition */ static compareRangesUsingStarts(a, b) { if (a && b) { const aStartLineNumber = a.startLineNumber | 0; const bStartLineNumber = b.startLineNumber | 0; if (aStartLineNumber === bStartLineNumber) { const aStartColumn = a.startColumn | 0; const bStartColumn = b.startColumn | 0; if (aStartColumn === bStartColumn) { const aEndLineNumber = a.endLineNumber | 0; const bEndLineNumber = b.endLineNumber | 0; if (aEndLineNumber === bEndLineNumber) { const aEndColumn = a.endColumn | 0; const bEndColumn = b.endColumn | 0; return aEndColumn - bEndColumn; } return aEndLineNumber - bEndLineNumber; } return aStartColumn - bStartColumn; } return aStartLineNumber - bStartLineNumber; } const aExists = (a ? 1 : 0); const bExists = (b ? 1 : 0); return aExists - bExists; } /** * A function that compares ranges, useful for sorting ranges * It will first compare ranges on the endPosition and then on the startPosition */ static compareRangesUsingEnds(a, b) { if (a.endLineNumber === b.endLineNumber) { if (a.endColumn === b.endColumn) { if (a.startLineNumber === b.startLineNumber) { return a.startColumn - b.startColumn; } return a.startLineNumber - b.startLineNumber; } return a.endColumn - b.endColumn; } return a.endLineNumber - b.endLineNumber; } /** * Test if the range spans multiple lines. */ static spansMultipleLines(range) { return range.endLineNumber > range.startLineNumber; } toJSON() { return this; } }