mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Initial VS Code 1.19 source merge (#571)
* Initial 1.19 xcopy * Fix yarn build * Fix numerous build breaks * Next batch of build break fixes * More build break fixes * Runtime breaks * Additional post merge fixes * Fix windows setup file * Fix test failures. * Update license header blocks to refer to source eula
This commit is contained in:
@@ -7,11 +7,9 @@
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IEditorContributionCtor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { EditorAction, CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { EditorBrowserRegistry } from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import { EditorAction, EditorExtensionsRegistry, IEditorContributionCtor } from 'vs/editor/browser/editorExtensions';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
@@ -30,10 +28,10 @@ export class CodeEditor extends CodeEditorWidget {
|
||||
}
|
||||
|
||||
protected _getContributions(): IEditorContributionCtor[] {
|
||||
return [].concat(EditorBrowserRegistry.getEditorContributions()).concat(CommonEditorRegistry.getEditorContributions());
|
||||
return EditorExtensionsRegistry.getEditorContributions();
|
||||
}
|
||||
|
||||
protected _getActions(): EditorAction[] {
|
||||
return CommonEditorRegistry.getEditorActions();
|
||||
return EditorExtensionsRegistry.getEditorActions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,6 @@ class CSSBasedConfigurationCache {
|
||||
delete this._values[itemId];
|
||||
}
|
||||
|
||||
public getKeys(): BareFontInfo[] {
|
||||
return Object.keys(this._keys).map(id => this._keys[id]);
|
||||
}
|
||||
|
||||
public getValues(): FontInfo[] {
|
||||
return Object.keys(this._keys).map(id => this._values[id]);
|
||||
}
|
||||
@@ -100,7 +96,7 @@ export interface ISerializedFontInfo {
|
||||
|
||||
class CSSBasedConfiguration extends Disposable {
|
||||
|
||||
public static INSTANCE = new CSSBasedConfiguration();
|
||||
public static readonly INSTANCE = new CSSBasedConfiguration();
|
||||
|
||||
private _cache: CSSBasedConfigurationCache;
|
||||
private _evictUntrustedReadingsTimeout: number;
|
||||
|
||||
1799
src/vs/editor/browser/controller/coreCommands.ts
Normal file
1799
src/vs/editor/browser/controller/coreCommands.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -494,7 +494,7 @@ class MouseDownOperation extends Disposable {
|
||||
|
||||
class MouseDownState {
|
||||
|
||||
private static CLEAR_MOUSE_DOWN_COUNT_TIME = 400; // ms
|
||||
private static readonly CLEAR_MOUSE_DOWN_COUNT_TIME = 400; // ms
|
||||
|
||||
private _altKey: boolean;
|
||||
public get altKey(): boolean { return this._altKey; }
|
||||
|
||||
@@ -32,6 +32,10 @@ export interface IMarginData {
|
||||
offsetX: number;
|
||||
}
|
||||
|
||||
export interface IEmptyContentData {
|
||||
isAfterLines: boolean;
|
||||
}
|
||||
|
||||
interface IETextRange {
|
||||
boundingHeight: number;
|
||||
boundingLeft: number;
|
||||
@@ -397,6 +401,9 @@ class HitTestRequest extends BareHitTestRequest {
|
||||
}
|
||||
}
|
||||
|
||||
const EMPTY_CONTENT_AFTER_LINES: IEmptyContentData = { isAfterLines: true };
|
||||
const EMPTY_CONTENT_IN_LINES: IEmptyContentData = { isAfterLines: false };
|
||||
|
||||
export class MouseTargetFactory {
|
||||
|
||||
private _context: ViewContext;
|
||||
@@ -608,7 +615,7 @@ export class MouseTargetFactory {
|
||||
// This most likely indicates it happened after the last view-line
|
||||
const lineCount = ctx.model.getLineCount();
|
||||
const maxLineColumn = ctx.model.getLineMaxColumn(lineCount);
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineCount, maxLineColumn));
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineCount, maxLineColumn), void 0, EMPTY_CONTENT_AFTER_LINES);
|
||||
}
|
||||
|
||||
if (domHitTestExecuted) {
|
||||
@@ -682,9 +689,9 @@ export class MouseTargetFactory {
|
||||
if (request.mouseContentHorizontalOffset > lineWidth) {
|
||||
if (browser.isEdge && pos.column === 1) {
|
||||
// See https://github.com/Microsoft/vscode/issues/10875
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineNumber, ctx.model.getLineMaxColumn(lineNumber)));
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, new Position(lineNumber, ctx.model.getLineMaxColumn(lineNumber)), void 0, EMPTY_CONTENT_IN_LINES);
|
||||
}
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, pos);
|
||||
return request.fulfill(MouseTargetType.CONTENT_EMPTY, pos, void 0, EMPTY_CONTENT_IN_LINES);
|
||||
}
|
||||
|
||||
let visibleRange = ctx.visibleRangeForPosition2(lineNumber, column);
|
||||
|
||||
@@ -28,7 +28,7 @@ function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent, currentEven
|
||||
r.translationX += lastEvent.translationX;
|
||||
}
|
||||
return r;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically IE10 and IE11
|
||||
@@ -188,12 +188,10 @@ class StandardPointerHandler extends MouseHandler implements IDisposable {
|
||||
|
||||
class TouchHandler extends MouseHandler {
|
||||
|
||||
private gesture: Gesture;
|
||||
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
super(context, viewController, viewHelper);
|
||||
|
||||
this.gesture = new Gesture(this.viewHelper.linesContentDomNode);
|
||||
Gesture.addTarget(this.viewHelper.linesContentDomNode);
|
||||
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));
|
||||
@@ -202,7 +200,6 @@ class TouchHandler extends MouseHandler {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.gesture.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import { PartFingerprints, PartFingerprint, ViewPart } from 'vs/editor/browser/v
|
||||
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
|
||||
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
|
||||
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
export interface ITextAreaHandlerHelper {
|
||||
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalRange;
|
||||
@@ -54,8 +55,6 @@ export class TextAreaHandler extends ViewPart {
|
||||
|
||||
private readonly _viewController: ViewController;
|
||||
private readonly _viewHelper: ITextAreaHandlerHelper;
|
||||
|
||||
private _pixelRatio: number;
|
||||
private _accessibilitySupport: platform.AccessibilitySupport;
|
||||
private _contentLeft: number;
|
||||
private _contentWidth: number;
|
||||
@@ -86,7 +85,6 @@ export class TextAreaHandler extends ViewPart {
|
||||
|
||||
const conf = this._context.configuration.editor;
|
||||
|
||||
this._pixelRatio = conf.pixelRatio;
|
||||
this._accessibilitySupport = conf.accessibilitySupport;
|
||||
this._contentLeft = conf.layoutInfo.contentLeft;
|
||||
this._contentWidth = conf.layoutInfo.contentWidth;
|
||||
@@ -306,9 +304,6 @@ export class TextAreaHandler extends ViewPart {
|
||||
if (e.lineHeight) {
|
||||
this._lineHeight = conf.lineHeight;
|
||||
}
|
||||
if (e.pixelRatio) {
|
||||
this._pixelRatio = conf.pixelRatio;
|
||||
}
|
||||
if (e.accessibilitySupport) {
|
||||
this._accessibilitySupport = conf.accessibilitySupport;
|
||||
this._textAreaInput.writeScreenReaderContent('strategy changed');
|
||||
@@ -361,20 +356,6 @@ export class TextAreaHandler extends ViewPart {
|
||||
this._textAreaInput.focusTextArea();
|
||||
}
|
||||
|
||||
public setAriaActiveDescendant(id: string): void {
|
||||
if (id) {
|
||||
this.textArea.setAttribute('role', 'combobox');
|
||||
if (this.textArea.getAttribute('aria-activedescendant') !== id) {
|
||||
this.textArea.setAttribute('aria-haspopup', 'true');
|
||||
this.textArea.setAttribute('aria-activedescendant', id);
|
||||
}
|
||||
} else {
|
||||
this.textArea.setAttribute('role', 'textbox');
|
||||
this.textArea.removeAttribute('aria-activedescendant');
|
||||
this.textArea.removeAttribute('aria-haspopup');
|
||||
}
|
||||
}
|
||||
|
||||
// --- end view API
|
||||
|
||||
private _primaryCursorVisibleRange: HorizontalRange = null;
|
||||
@@ -487,7 +468,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
if (this._context.configuration.editor.viewInfo.glyphMargin) {
|
||||
tac.setClassName('monaco-editor-background textAreaCover ' + Margin.CLASS_NAME);
|
||||
} else {
|
||||
if (this._context.configuration.editor.viewInfo.renderLineNumbers) {
|
||||
if (this._context.configuration.editor.viewInfo.renderLineNumbers !== RenderLineNumbersType.Off) {
|
||||
tac.setClassName('monaco-editor-background textAreaCover ' + LineNumbersOverlay.CLASS_NAME);
|
||||
} else {
|
||||
tac.setClassName('monaco-editor-background textAreaCover');
|
||||
|
||||
@@ -31,7 +31,7 @@ export interface ITypeData {
|
||||
|
||||
export class TextAreaState {
|
||||
|
||||
public static EMPTY = new TextAreaState('', 0, 0, null, null);
|
||||
public static readonly EMPTY = new TextAreaState('', 0, 0, null, null);
|
||||
|
||||
public readonly value: string;
|
||||
public readonly selectionStart: number;
|
||||
@@ -47,19 +47,6 @@ export class TextAreaState {
|
||||
this.selectionEndPosition = selectionEndPosition;
|
||||
}
|
||||
|
||||
public equals(other: TextAreaState): boolean {
|
||||
if (other instanceof TextAreaState) {
|
||||
return (
|
||||
this.value === other.value
|
||||
&& this.selectionStart === other.selectionStart
|
||||
&& this.selectionEnd === other.selectionEnd
|
||||
&& Position.equals(this.selectionStartPosition, other.selectionStartPosition)
|
||||
&& Position.equals(this.selectionEndPosition, other.selectionEndPosition)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return '[ <' + this.value + '>, selectionStart: ' + this.selectionStart + ', selectionEnd: ' + this.selectionEnd + ']';
|
||||
}
|
||||
@@ -228,7 +215,7 @@ export class TextAreaState {
|
||||
}
|
||||
|
||||
export class PagedScreenReaderStrategy {
|
||||
private static _LINES_PER_PAGE = 10;
|
||||
private static readonly _LINES_PER_PAGE = 10;
|
||||
|
||||
private static _getPageOfLine(lineNumber: number): number {
|
||||
return Math.floor((lineNumber - 1) / PagedScreenReaderStrategy._LINES_PER_PAGE);
|
||||
|
||||
73
src/vs/editor/browser/core/editorState.ts
Normal file
73
src/vs/editor/browser/core/editorState.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export const enum CodeEditorStateFlag {
|
||||
Value = 1,
|
||||
Selection = 2,
|
||||
Position = 4,
|
||||
Scroll = 8
|
||||
}
|
||||
|
||||
export class EditorState {
|
||||
|
||||
private readonly flags: number;
|
||||
|
||||
private readonly position: Position;
|
||||
private readonly selection: Range;
|
||||
private readonly modelVersionId: string;
|
||||
private readonly scrollLeft: number;
|
||||
private readonly scrollTop: number;
|
||||
|
||||
constructor(editor: ICodeEditor, flags: number) {
|
||||
this.flags = flags;
|
||||
|
||||
if ((this.flags & CodeEditorStateFlag.Value) !== 0) {
|
||||
var model = editor.getModel();
|
||||
this.modelVersionId = model ? strings.format('{0}#{1}', model.uri.toString(), model.getVersionId()) : null;
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Position) !== 0) {
|
||||
this.position = editor.getPosition();
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Selection) !== 0) {
|
||||
this.selection = editor.getSelection();
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Scroll) !== 0) {
|
||||
this.scrollLeft = editor.getScrollLeft();
|
||||
this.scrollTop = editor.getScrollTop();
|
||||
}
|
||||
}
|
||||
|
||||
private _equals(other: any): boolean {
|
||||
|
||||
if (!(other instanceof EditorState)) {
|
||||
return false;
|
||||
}
|
||||
var state = <EditorState>other;
|
||||
|
||||
if (this.modelVersionId !== state.modelVersionId) {
|
||||
return false;
|
||||
}
|
||||
if (this.scrollLeft !== state.scrollLeft || this.scrollTop !== state.scrollTop) {
|
||||
return false;
|
||||
}
|
||||
if (!this.position && state.position || this.position && !state.position || this.position && state.position && !this.position.equals(state.position)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.selection && state.selection || this.selection && !state.selection || this.selection && state.selection && !this.selection.equalsRange(state.selection)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public validate(editor: ICodeEditor): boolean {
|
||||
return this._equals(new EditorState(editor, this.flags));
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,16 @@
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { Position, IPosition } from 'vs/editor/common/core/position';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import * as editorOptions from 'vs/editor/common/config/editorOptions';
|
||||
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
|
||||
import { IModelContentChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICursors, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
|
||||
/**
|
||||
@@ -289,11 +293,6 @@ export interface IEditorMouseEvent {
|
||||
readonly target: IMouseTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, editorCommon.IEditorContribution>;
|
||||
|
||||
/**
|
||||
* An overview ruler
|
||||
* @internal
|
||||
@@ -308,7 +307,90 @@ export interface IOverviewRuler {
|
||||
/**
|
||||
* A rich code editor.
|
||||
*/
|
||||
export interface ICodeEditor extends editorCommon.ICommonCodeEditor {
|
||||
export interface ICodeEditor extends editorCommon.IEditor {
|
||||
/**
|
||||
* An event emitted when the content of the current model has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModelContent(listener: (e: IModelContentChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the language of the current model has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModelLanguage(listener: (e: IModelLanguageChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the language configuration of the current model has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModelLanguageConfiguration(listener: (e: IModelLanguageConfigurationChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the options of the current model has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModelOptions(listener: (e: IModelOptionsChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the configuration of the editor has changed. (e.g. `editor.updateOptions()`)
|
||||
* @event
|
||||
*/
|
||||
onDidChangeConfiguration(listener: (e: editorOptions.IConfigurationChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the cursor position has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeCursorPosition(listener: (e: ICursorPositionChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the cursor selection has changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeCursorSelection(listener: (e: ICursorSelectionChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the model of this editor has changed (e.g. `editor.setModel()`).
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModel(listener: (e: editorCommon.IModelChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the decorations of the current model have changed.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeModelDecorations(listener: (e: IModelDecorationsChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the text inside this editor gained focus (i.e. cursor blinking).
|
||||
* @event
|
||||
*/
|
||||
onDidFocusEditorText(listener: () => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the text inside this editor lost focus.
|
||||
* @event
|
||||
*/
|
||||
onDidBlurEditorText(listener: () => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the text inside this editor or an editor widget gained focus.
|
||||
* @event
|
||||
*/
|
||||
onDidFocusEditor(listener: () => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the text inside this editor or an editor widget lost focus.
|
||||
* @event
|
||||
*/
|
||||
onDidBlurEditor(listener: () => void): IDisposable;
|
||||
/**
|
||||
* An event emitted before interpreting typed characters (on the keyboard).
|
||||
* @event
|
||||
* @internal
|
||||
*/
|
||||
onWillType(listener: (text: string) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted before interpreting typed characters (on the keyboard).
|
||||
* @event
|
||||
* @internal
|
||||
*/
|
||||
onDidType(listener: (text: string) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when users paste text in the editor.
|
||||
* @event
|
||||
* @internal
|
||||
*/
|
||||
onDidPaste(listener: (range: Range) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted on a "mouseup".
|
||||
* @event
|
||||
@@ -367,6 +449,202 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor {
|
||||
*/
|
||||
onDidScrollChange(listener: (e: editorCommon.IScrollEvent) => void): IDisposable;
|
||||
|
||||
/**
|
||||
* Saves current view state of the editor in a serializable object.
|
||||
*/
|
||||
saveViewState(): editorCommon.ICodeEditorViewState;
|
||||
|
||||
/**
|
||||
* Restores the view state of the editor from a serializable object generated by `saveViewState`.
|
||||
*/
|
||||
restoreViewState(state: editorCommon.ICodeEditorViewState): void;
|
||||
|
||||
/**
|
||||
* Returns true if this editor or one of its widgets has keyboard focus.
|
||||
*/
|
||||
hasWidgetFocus(): boolean;
|
||||
|
||||
/**
|
||||
* Get a contribution of this editor.
|
||||
* @id Unique identifier of the contribution.
|
||||
* @return The contribution or null if contribution not found.
|
||||
*/
|
||||
getContribution<T extends editorCommon.IEditorContribution>(id: string): T;
|
||||
|
||||
/**
|
||||
* Execute `fn` with the editor's services.
|
||||
* @internal
|
||||
*/
|
||||
invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T;
|
||||
|
||||
/**
|
||||
* Type the getModel() of IEditor.
|
||||
*/
|
||||
getModel(): editorCommon.IModel;
|
||||
|
||||
/**
|
||||
* Returns the current editor's configuration
|
||||
*/
|
||||
getConfiguration(): editorOptions.InternalEditorOptions;
|
||||
|
||||
/**
|
||||
* Returns the 'raw' editor's configuration (without any validation or defaults).
|
||||
* @internal
|
||||
*/
|
||||
getRawConfiguration(): editorOptions.IEditorOptions;
|
||||
|
||||
/**
|
||||
* Get value of the current model attached to this editor.
|
||||
* @see IModel.getValue
|
||||
*/
|
||||
getValue(options?: { preserveBOM: boolean; lineEnding: string; }): string;
|
||||
|
||||
/**
|
||||
* Set the value of the current model attached to this editor.
|
||||
* @see IModel.setValue
|
||||
*/
|
||||
setValue(newValue: string): void;
|
||||
|
||||
/**
|
||||
* Get the scrollWidth of the editor's viewport.
|
||||
*/
|
||||
getScrollWidth(): number;
|
||||
/**
|
||||
* Get the scrollLeft of the editor's viewport.
|
||||
*/
|
||||
getScrollLeft(): number;
|
||||
|
||||
/**
|
||||
* Get the scrollHeight of the editor's viewport.
|
||||
*/
|
||||
getScrollHeight(): number;
|
||||
/**
|
||||
* Get the scrollTop of the editor's viewport.
|
||||
*/
|
||||
getScrollTop(): number;
|
||||
|
||||
/**
|
||||
* Change the scrollLeft of the editor's viewport.
|
||||
*/
|
||||
setScrollLeft(newScrollLeft: number): void;
|
||||
/**
|
||||
* Change the scrollTop of the editor's viewport.
|
||||
*/
|
||||
setScrollTop(newScrollTop: number): void;
|
||||
/**
|
||||
* Change the scroll position of the editor's viewport.
|
||||
*/
|
||||
setScrollPosition(position: editorCommon.INewScrollPosition): void;
|
||||
|
||||
/**
|
||||
* Get an action that is a contribution to this editor.
|
||||
* @id Unique identifier of the contribution.
|
||||
* @return The action or null if action not found.
|
||||
*/
|
||||
getAction(id: string): editorCommon.IEditorAction;
|
||||
|
||||
/**
|
||||
* Execute a command on the editor.
|
||||
* The edits will land on the undo-redo stack, but no "undo stop" will be pushed.
|
||||
* @param source The source of the call.
|
||||
* @param command The command to execute
|
||||
*/
|
||||
executeCommand(source: string, command: editorCommon.ICommand): void;
|
||||
|
||||
/**
|
||||
* Push an "undo stop" in the undo-redo stack.
|
||||
*/
|
||||
pushUndoStop(): boolean;
|
||||
|
||||
/**
|
||||
* Execute edits on the editor.
|
||||
* The edits will land on the undo-redo stack, but no "undo stop" will be pushed.
|
||||
* @param source The source of the call.
|
||||
* @param edits The edits to execute.
|
||||
* @param endCursoState Cursor state after the edits were applied.
|
||||
*/
|
||||
executeEdits(source: string, edits: editorCommon.IIdentifiedSingleEditOperation[], endCursoState?: Selection[]): boolean;
|
||||
|
||||
/**
|
||||
* Execute multiple (concommitent) commands on the editor.
|
||||
* @param source The source of the call.
|
||||
* @param command The commands to execute
|
||||
*/
|
||||
executeCommands(source: string, commands: editorCommon.ICommand[]): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getCursors(): ICursors;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_getCursorConfiguration(): CursorConfiguration;
|
||||
|
||||
/**
|
||||
* Get all the decorations on a line (filtering out decorations from other editors).
|
||||
*/
|
||||
getLineDecorations(lineNumber: number): editorCommon.IModelDecoration[];
|
||||
|
||||
/**
|
||||
* All decorations added through this call will get the ownerId of this editor.
|
||||
* @see IModel.deltaDecorations
|
||||
*/
|
||||
deltaDecorations(oldDecorations: string[], newDecorations: editorCommon.IModelDeltaDecoration[]): string[];
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setDecorations(decorationTypeKey: string, ranges: editorCommon.IDecorationOptions[]): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
removeDecorations(decorationTypeKey: string): void;
|
||||
|
||||
/**
|
||||
* Get the layout info for the editor.
|
||||
*/
|
||||
getLayoutInfo(): editorOptions.EditorLayoutInfo;
|
||||
|
||||
/**
|
||||
* Returns the range that is currently centered in the view port.
|
||||
*/
|
||||
getCenteredRangeInViewport(): Range;
|
||||
|
||||
/**
|
||||
* Get the view zones.
|
||||
* @internal
|
||||
*/
|
||||
getWhitespaces(): IEditorWhitespace[];
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line w.r.t. to the first line.
|
||||
*/
|
||||
getTopForLineNumber(lineNumber: number): number;
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the position w.r.t. to the first line.
|
||||
*/
|
||||
getTopForPosition(lineNumber: number, column: number): number;
|
||||
|
||||
/**
|
||||
* Set the model ranges that will be hidden in the view.
|
||||
* @internal
|
||||
*/
|
||||
setHiddenAreas(ranges: IRange[]): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getTelemetryData(): { [key: string]: any; };
|
||||
|
||||
/**
|
||||
* Returns the editor's dom node
|
||||
*/
|
||||
@@ -405,17 +683,6 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor {
|
||||
*/
|
||||
changeViewZones(callback: (accessor: IViewZoneChangeAccessor) => void): void;
|
||||
|
||||
/**
|
||||
* Returns the range that is currently centered in the view port.
|
||||
*/
|
||||
getCenteredRangeInViewport(): Range;
|
||||
|
||||
/**
|
||||
* Get the view zones.
|
||||
* @internal
|
||||
*/
|
||||
getWhitespaces(): IEditorWhitespace[];
|
||||
|
||||
/**
|
||||
* Get the horizontal position (left offset) for the column w.r.t to the beginning of the line.
|
||||
* This method works only if the line `lineNumber` is currently rendered (in the editor's viewport).
|
||||
@@ -428,16 +695,6 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor {
|
||||
*/
|
||||
render(): void;
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line w.r.t. to the first line.
|
||||
*/
|
||||
getTopForLineNumber(lineNumber: number): number;
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the position w.r.t. to the first line.
|
||||
*/
|
||||
getTopForPosition(lineNumber: number, column: number): number;
|
||||
|
||||
/**
|
||||
* Get the hit test target at coordinates `clientX` and `clientY`.
|
||||
* The coordinates are relative to the top-left of the viewport.
|
||||
@@ -455,29 +712,112 @@ export interface ICodeEditor extends editorCommon.ICommonCodeEditor {
|
||||
*/
|
||||
getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; };
|
||||
|
||||
/**
|
||||
* Set the model ranges that will be hidden in the view.
|
||||
* @internal
|
||||
*/
|
||||
setHiddenAreas(ranges: IRange[]): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setAriaActiveDescendant(id: string): void;
|
||||
|
||||
/**
|
||||
* Apply the same font settings as the editor to `target`.
|
||||
*/
|
||||
applyFontInfo(target: HTMLElement): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a line in the diff editor
|
||||
*/
|
||||
export interface IDiffLineInformation {
|
||||
readonly equivalentLineNumber: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A rich diff editor.
|
||||
*/
|
||||
export interface IDiffEditor extends editorCommon.ICommonDiffEditor {
|
||||
export interface IDiffEditor extends editorCommon.IEditor {
|
||||
|
||||
/**
|
||||
* Returns whether the diff editor is ignoring trim whitespace or not.
|
||||
* @internal
|
||||
*/
|
||||
readonly ignoreTrimWhitespace: boolean;
|
||||
/**
|
||||
* Returns whether the diff editor is rendering side by side or not.
|
||||
* @internal
|
||||
*/
|
||||
readonly renderSideBySide: boolean;
|
||||
/**
|
||||
* Returns whether the diff editor is rendering +/- indicators or not.
|
||||
* @internal
|
||||
*/
|
||||
readonly renderIndicators: boolean;
|
||||
|
||||
/**
|
||||
* @see ICodeEditor.getDomNode
|
||||
*/
|
||||
getDomNode(): HTMLElement;
|
||||
|
||||
/**
|
||||
* An event emitted when the diff information computed by this diff editor has been updated.
|
||||
* @event
|
||||
*/
|
||||
onDidUpdateDiff(listener: () => void): IDisposable;
|
||||
|
||||
/**
|
||||
* Saves current view state of the editor in a serializable object.
|
||||
*/
|
||||
saveViewState(): editorCommon.IDiffEditorViewState;
|
||||
|
||||
/**
|
||||
* Restores the view state of the editor from a serializable object generated by `saveViewState`.
|
||||
*/
|
||||
restoreViewState(state: editorCommon.IDiffEditorViewState): void;
|
||||
|
||||
/**
|
||||
* Type the getModel() of IEditor.
|
||||
*/
|
||||
getModel(): editorCommon.IDiffEditorModel;
|
||||
|
||||
/**
|
||||
* Get the `original` editor.
|
||||
*/
|
||||
getOriginalEditor(): ICodeEditor;
|
||||
|
||||
/**
|
||||
* Get the `modified` editor.
|
||||
*/
|
||||
getModifiedEditor(): ICodeEditor;
|
||||
|
||||
/**
|
||||
* Get the computed diff information.
|
||||
*/
|
||||
getLineChanges(): editorCommon.ILineChange[];
|
||||
|
||||
/**
|
||||
* Get information based on computed diff about a line number from the original model.
|
||||
* If the diff computation is not finished or the model is missing, will return null.
|
||||
*/
|
||||
getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation;
|
||||
|
||||
/**
|
||||
* Get information based on computed diff about a line number from the modified model.
|
||||
* If the diff computation is not finished or the model is missing, will return null.
|
||||
*/
|
||||
getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
*@internal
|
||||
*/
|
||||
export function isCodeEditor(thing: any): thing is ICodeEditor {
|
||||
if (thing && typeof (<ICodeEditor>thing).getEditorType === 'function') {
|
||||
return (<ICodeEditor>thing).getEditorType() === editorCommon.EditorType.ICodeEditor;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*@internal
|
||||
*/
|
||||
export function isDiffEditor(thing: any): thing is IDiffEditor {
|
||||
if (thing && typeof (<IDiffEditor>thing).getEditorType === 'function') {
|
||||
return (<IDiffEditor>thing).getEditorType() === editorCommon.EditorType.IDiffEditor;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IEditorContributionCtor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export function editorContribution(ctor: IEditorContributionCtor): void {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorBrowserContribution(ctor);
|
||||
}
|
||||
|
||||
export namespace EditorBrowserRegistry {
|
||||
export function getEditorContributions(): IEditorContributionCtor[] {
|
||||
return EditorContributionRegistry.INSTANCE.getEditorBrowserContributions();
|
||||
}
|
||||
}
|
||||
|
||||
const Extensions = {
|
||||
EditorContributions: 'editor.contributions'
|
||||
};
|
||||
|
||||
class EditorContributionRegistry {
|
||||
|
||||
public static INSTANCE = new EditorContributionRegistry();
|
||||
|
||||
private editorContributions: IEditorContributionCtor[];
|
||||
|
||||
constructor() {
|
||||
this.editorContributions = [];
|
||||
}
|
||||
|
||||
public registerEditorBrowserContribution(ctor: IEditorContributionCtor): void {
|
||||
this.editorContributions.push(ctor);
|
||||
}
|
||||
|
||||
public getEditorBrowserContributions(): IEditorContributionCtor[] {
|
||||
return this.editorContributions.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
Registry.add(Extensions.EditorContributions, EditorContributionRegistry.INSTANCE);
|
||||
@@ -135,10 +135,10 @@ export class EditorMouseEventFactory {
|
||||
}
|
||||
|
||||
public onMouseMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {
|
||||
let myMerger: dom.IEventMerger<EditorMouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
let myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
return merger(lastEvent, this._create(currentEvent));
|
||||
};
|
||||
return dom.addDisposableThrottledListener<EditorMouseEvent>(target, 'mousemove', callback, myMerger, minimumTimeMs);
|
||||
return dom.addDisposableThrottledListener<EditorMouseEvent, MouseEvent>(target, 'mousemove', callback, myMerger, minimumTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
|
||||
this._globalMouseMoveMonitor.stopMonitoring(true);
|
||||
}, true);
|
||||
|
||||
let myMerger: dom.IEventMerger<EditorMouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
let myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));
|
||||
};
|
||||
|
||||
|
||||
332
src/vs/editor/browser/editorExtensions.ts
Normal file
332
src/vs/editor/browser/editorExtensions.ts
Normal file
@@ -0,0 +1,332 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ServicesAccessor, IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { KeybindingsRegistry, ICommandAndKeybindingRule, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions';
|
||||
import { IEditorService } from 'vs/platform/editor/common/editor';
|
||||
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICodeEditorService, getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export type ServicesAccessor = ServicesAccessor;
|
||||
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, editorCommon.IEditorContribution>;
|
||||
|
||||
//#region Command
|
||||
|
||||
export interface ICommandKeybindingsOptions extends IKeybindings {
|
||||
kbExpr?: ContextKeyExpr;
|
||||
weight?: number;
|
||||
}
|
||||
export interface ICommandOptions {
|
||||
id: string;
|
||||
precondition: ContextKeyExpr;
|
||||
kbOpts?: ICommandKeybindingsOptions;
|
||||
description?: ICommandHandlerDescription;
|
||||
}
|
||||
export abstract class Command {
|
||||
public readonly id: string;
|
||||
public readonly precondition: ContextKeyExpr;
|
||||
private readonly _kbOpts: ICommandKeybindingsOptions;
|
||||
private readonly _description: ICommandHandlerDescription;
|
||||
|
||||
constructor(opts: ICommandOptions) {
|
||||
this.id = opts.id;
|
||||
this.precondition = opts.precondition;
|
||||
this._kbOpts = opts.kbOpts;
|
||||
this._description = opts.description;
|
||||
}
|
||||
|
||||
public toCommandAndKeybindingRule(defaultWeight: number): ICommandAndKeybindingRule {
|
||||
const kbOpts = this._kbOpts || { primary: 0 };
|
||||
|
||||
let kbWhen = kbOpts.kbExpr;
|
||||
if (this.precondition) {
|
||||
if (kbWhen) {
|
||||
kbWhen = ContextKeyExpr.and(kbWhen, this.precondition);
|
||||
} else {
|
||||
kbWhen = this.precondition;
|
||||
}
|
||||
}
|
||||
|
||||
const weight = (typeof kbOpts.weight === 'number' ? kbOpts.weight : defaultWeight);
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
handler: (accessor, args) => this.runCommand(accessor, args),
|
||||
weight: weight,
|
||||
when: kbWhen,
|
||||
primary: kbOpts.primary,
|
||||
secondary: kbOpts.secondary,
|
||||
win: kbOpts.win,
|
||||
linux: kbOpts.linux,
|
||||
mac: kbOpts.mac,
|
||||
description: this._description
|
||||
};
|
||||
}
|
||||
|
||||
public abstract runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void>;
|
||||
}
|
||||
|
||||
//#endregion Command
|
||||
|
||||
//#region EditorCommand
|
||||
|
||||
function getWorkbenchActiveEditor(accessor: ServicesAccessor): ICodeEditor {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
let activeEditor = (<any>editorService).getActiveEditor && (<any>editorService).getActiveEditor();
|
||||
return getCodeEditor(activeEditor);
|
||||
}
|
||||
|
||||
export interface IContributionCommandOptions<T> extends ICommandOptions {
|
||||
handler: (controller: T) => void;
|
||||
}
|
||||
export interface EditorControllerCommand<T extends editorCommon.IEditorContribution> {
|
||||
new(opts: IContributionCommandOptions<T>): EditorCommand;
|
||||
}
|
||||
export abstract class EditorCommand extends Command {
|
||||
|
||||
/**
|
||||
* Create a command class that is bound to a certain editor contribution.
|
||||
*/
|
||||
public static bindToContribution<T extends editorCommon.IEditorContribution>(controllerGetter: (editor: ICodeEditor) => T): EditorControllerCommand<T> {
|
||||
return class EditorControllerCommandImpl extends EditorCommand {
|
||||
private _callback: (controller: T) => void;
|
||||
|
||||
constructor(opts: IContributionCommandOptions<T>) {
|
||||
super(opts);
|
||||
|
||||
this._callback = opts.handler;
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
|
||||
let controller = controllerGetter(editor);
|
||||
if (controller) {
|
||||
this._callback(controllerGetter(editor));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void> {
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
|
||||
// Find the editor with text focus
|
||||
let editor = codeEditorService.getFocusedCodeEditor();
|
||||
|
||||
if (!editor) {
|
||||
// Fallback to use what the workbench considers the active editor
|
||||
editor = getWorkbenchActiveEditor(accessor);
|
||||
}
|
||||
|
||||
if (!editor) {
|
||||
// well, at least we tried...
|
||||
return;
|
||||
}
|
||||
|
||||
return editor.invokeWithinContext((editorAccessor) => {
|
||||
const kbService = editorAccessor.get(IContextKeyService);
|
||||
if (!kbService.contextMatchesRules(this.precondition)) {
|
||||
// precondition does not hold
|
||||
return;
|
||||
}
|
||||
|
||||
return this.runEditorCommand(editorAccessor, editor, args);
|
||||
});
|
||||
}
|
||||
|
||||
public abstract runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void>;
|
||||
}
|
||||
|
||||
//#endregion EditorCommand
|
||||
|
||||
//#region EditorAction
|
||||
|
||||
export interface IEditorCommandMenuOptions {
|
||||
group?: string;
|
||||
order?: number;
|
||||
when?: ContextKeyExpr;
|
||||
}
|
||||
export interface IActionOptions extends ICommandOptions {
|
||||
label: string;
|
||||
alias: string;
|
||||
menuOpts?: IEditorCommandMenuOptions;
|
||||
}
|
||||
export abstract class EditorAction extends EditorCommand {
|
||||
|
||||
public label: string;
|
||||
public alias: string;
|
||||
private menuOpts: IEditorCommandMenuOptions;
|
||||
|
||||
constructor(opts: IActionOptions) {
|
||||
super(opts);
|
||||
this.label = opts.label;
|
||||
this.alias = opts.alias;
|
||||
this.menuOpts = opts.menuOpts;
|
||||
}
|
||||
|
||||
public toMenuItem(): IMenuItem {
|
||||
if (!this.menuOpts) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
command: {
|
||||
id: this.id,
|
||||
title: this.label
|
||||
},
|
||||
when: ContextKeyExpr.and(this.precondition, this.menuOpts.when),
|
||||
group: this.menuOpts.group,
|
||||
order: this.menuOpts.order
|
||||
};
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void> {
|
||||
this.reportTelemetry(accessor, editor);
|
||||
return this.run(accessor, editor, args || {});
|
||||
}
|
||||
|
||||
protected reportTelemetry(accessor: ServicesAccessor, editor: ICodeEditor) {
|
||||
/* __GDPR__
|
||||
"editorActionInvoked" : {
|
||||
"name" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"id": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"${include}": [
|
||||
"${EditorTelemetryData}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
accessor.get(ITelemetryService).publicLog('editorActionInvoked', { name: this.label, id: this.id, ...editor.getTelemetryData() });
|
||||
}
|
||||
|
||||
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void>;
|
||||
}
|
||||
|
||||
//#endregion EditorAction
|
||||
|
||||
// --- Registration of commands and actions
|
||||
|
||||
export function registerLanguageCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) {
|
||||
CommandsRegistry.registerCommand(id, (accessor, args) => handler(accessor, args || {}));
|
||||
}
|
||||
|
||||
export function registerDefaultLanguageCommand(id: string, handler: (model: editorCommon.IModel, position: Position, args: { [n: string]: any }) => any) {
|
||||
registerLanguageCommand(id, function (accessor, args) {
|
||||
|
||||
const { resource, position } = args;
|
||||
if (!(resource instanceof URI)) {
|
||||
throw illegalArgument('resource');
|
||||
}
|
||||
if (!Position.isIPosition(position)) {
|
||||
throw illegalArgument('position');
|
||||
}
|
||||
|
||||
const model = accessor.get(IModelService).getModel(resource);
|
||||
if (!model) {
|
||||
throw illegalArgument('Can not find open model for ' + resource);
|
||||
}
|
||||
|
||||
const editorPosition = Position.lift(position);
|
||||
|
||||
return handler(model, editorPosition, args);
|
||||
});
|
||||
}
|
||||
|
||||
export function registerEditorCommand<T extends EditorCommand>(editorCommand: T): T {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorCommand(editorCommand);
|
||||
return editorCommand;
|
||||
}
|
||||
|
||||
export function registerEditorAction(ctor: { new(): EditorAction; }): void {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorAction(new ctor());
|
||||
}
|
||||
|
||||
export function registerInstantiatedEditorAction(editorAction: EditorAction): void {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorAction(editorAction);
|
||||
}
|
||||
|
||||
export function registerEditorContribution(ctor: IEditorContributionCtor): void {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorContribution(ctor);
|
||||
}
|
||||
|
||||
export namespace EditorExtensionsRegistry {
|
||||
|
||||
export function getEditorCommand(commandId: string): EditorCommand {
|
||||
return EditorContributionRegistry.INSTANCE.getEditorCommand(commandId);
|
||||
}
|
||||
|
||||
export function getEditorActions(): EditorAction[] {
|
||||
return EditorContributionRegistry.INSTANCE.getEditorActions();
|
||||
}
|
||||
|
||||
export function getEditorContributions(): IEditorContributionCtor[] {
|
||||
return EditorContributionRegistry.INSTANCE.getEditorContributions();
|
||||
}
|
||||
}
|
||||
|
||||
// Editor extension points
|
||||
const Extensions = {
|
||||
EditorCommonContributions: 'editor.contributions'
|
||||
};
|
||||
|
||||
class EditorContributionRegistry {
|
||||
|
||||
public static readonly INSTANCE = new EditorContributionRegistry();
|
||||
|
||||
private editorContributions: IEditorContributionCtor[];
|
||||
private editorActions: EditorAction[];
|
||||
private editorCommands: { [commandId: string]: EditorCommand; };
|
||||
|
||||
constructor() {
|
||||
this.editorContributions = [];
|
||||
this.editorActions = [];
|
||||
this.editorCommands = Object.create(null);
|
||||
}
|
||||
|
||||
public registerEditorContribution(ctor: IEditorContributionCtor): void {
|
||||
this.editorContributions.push(ctor);
|
||||
}
|
||||
|
||||
public registerEditorAction(action: EditorAction) {
|
||||
|
||||
let menuItem = action.toMenuItem();
|
||||
if (menuItem) {
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem);
|
||||
}
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(action.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
|
||||
this.editorActions.push(action);
|
||||
}
|
||||
|
||||
public getEditorContributions(): IEditorContributionCtor[] {
|
||||
return this.editorContributions.slice(0);
|
||||
}
|
||||
|
||||
public getEditorActions(): EditorAction[] {
|
||||
return this.editorActions.slice(0);
|
||||
}
|
||||
|
||||
public registerEditorCommand(editorCommand: EditorCommand) {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule(editorCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
|
||||
this.editorCommands[editorCommand.id] = editorCommand;
|
||||
}
|
||||
|
||||
public getEditorCommand(commandId: string): EditorCommand {
|
||||
return (this.editorCommands[commandId] || null);
|
||||
}
|
||||
|
||||
}
|
||||
Registry.add(Extensions.EditorCommonContributions, EditorContributionRegistry.INSTANCE);
|
||||
151
src/vs/editor/browser/services/abstractCodeEditorService.ts
Normal file
151
src/vs/editor/browser/services/abstractCodeEditorService.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IDecorationRenderOptions, IModelDecorationOptions, IModel } from 'vs/editor/common/editorCommon';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export abstract class AbstractCodeEditorService implements ICodeEditorService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private _onCodeEditorAdd: Emitter<ICodeEditor>;
|
||||
private _onCodeEditorRemove: Emitter<ICodeEditor>;
|
||||
private _codeEditors: { [editorId: string]: ICodeEditor; };
|
||||
|
||||
private _onDiffEditorAdd: Emitter<IDiffEditor>;
|
||||
private _onDiffEditorRemove: Emitter<IDiffEditor>;
|
||||
private _diffEditors: { [editorId: string]: IDiffEditor; };
|
||||
|
||||
constructor() {
|
||||
this._codeEditors = Object.create(null);
|
||||
this._diffEditors = Object.create(null);
|
||||
this._onCodeEditorAdd = new Emitter<ICodeEditor>();
|
||||
this._onCodeEditorRemove = new Emitter<ICodeEditor>();
|
||||
this._onDiffEditorAdd = new Emitter<IDiffEditor>();
|
||||
this._onDiffEditorRemove = new Emitter<IDiffEditor>();
|
||||
}
|
||||
|
||||
addCodeEditor(editor: ICodeEditor): void {
|
||||
this._codeEditors[editor.getId()] = editor;
|
||||
this._onCodeEditorAdd.fire(editor);
|
||||
}
|
||||
|
||||
get onCodeEditorAdd(): Event<ICodeEditor> {
|
||||
return this._onCodeEditorAdd.event;
|
||||
}
|
||||
|
||||
removeCodeEditor(editor: ICodeEditor): void {
|
||||
if (delete this._codeEditors[editor.getId()]) {
|
||||
this._onCodeEditorRemove.fire(editor);
|
||||
}
|
||||
}
|
||||
|
||||
get onCodeEditorRemove(): Event<ICodeEditor> {
|
||||
return this._onCodeEditorRemove.event;
|
||||
}
|
||||
|
||||
listCodeEditors(): ICodeEditor[] {
|
||||
return Object.keys(this._codeEditors).map(id => this._codeEditors[id]);
|
||||
}
|
||||
|
||||
addDiffEditor(editor: IDiffEditor): void {
|
||||
this._diffEditors[editor.getId()] = editor;
|
||||
this._onDiffEditorAdd.fire(editor);
|
||||
}
|
||||
|
||||
get onDiffEditorAdd(): Event<IDiffEditor> {
|
||||
return this._onDiffEditorAdd.event;
|
||||
}
|
||||
|
||||
removeDiffEditor(editor: IDiffEditor): void {
|
||||
if (delete this._diffEditors[editor.getId()]) {
|
||||
this._onDiffEditorRemove.fire(editor);
|
||||
}
|
||||
}
|
||||
|
||||
get onDiffEditorRemove(): Event<IDiffEditor> {
|
||||
return this._onDiffEditorRemove.event;
|
||||
}
|
||||
|
||||
listDiffEditors(): IDiffEditor[] {
|
||||
return Object.keys(this._diffEditors).map(id => this._diffEditors[id]);
|
||||
}
|
||||
|
||||
getFocusedCodeEditor(): ICodeEditor {
|
||||
let editorWithWidgetFocus: ICodeEditor = null;
|
||||
|
||||
let editors = this.listCodeEditors();
|
||||
for (let i = 0; i < editors.length; i++) {
|
||||
let editor = editors[i];
|
||||
|
||||
if (editor.isFocused()) {
|
||||
// bingo!
|
||||
return editor;
|
||||
}
|
||||
|
||||
if (editor.hasWidgetFocus()) {
|
||||
editorWithWidgetFocus = editor;
|
||||
}
|
||||
}
|
||||
|
||||
return editorWithWidgetFocus;
|
||||
}
|
||||
|
||||
abstract registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
|
||||
abstract removeDecorationType(key: string): void;
|
||||
abstract resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions;
|
||||
|
||||
private _transientWatchers: { [uri: string]: ModelTransientSettingWatcher; } = {};
|
||||
|
||||
public setTransientModelProperty(model: IModel, key: string, value: any): void {
|
||||
const uri = model.uri.toString();
|
||||
|
||||
let w: ModelTransientSettingWatcher;
|
||||
if (this._transientWatchers.hasOwnProperty(uri)) {
|
||||
w = this._transientWatchers[uri];
|
||||
} else {
|
||||
w = new ModelTransientSettingWatcher(uri, model, this);
|
||||
this._transientWatchers[uri] = w;
|
||||
}
|
||||
|
||||
w.set(key, value);
|
||||
}
|
||||
|
||||
public getTransientModelProperty(model: IModel, key: string): any {
|
||||
const uri = model.uri.toString();
|
||||
|
||||
if (!this._transientWatchers.hasOwnProperty(uri)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this._transientWatchers[uri].get(key);
|
||||
}
|
||||
|
||||
_removeWatcher(w: ModelTransientSettingWatcher): void {
|
||||
delete this._transientWatchers[w.uri];
|
||||
}
|
||||
}
|
||||
|
||||
export class ModelTransientSettingWatcher {
|
||||
public readonly uri: string;
|
||||
private readonly _values: { [key: string]: any; };
|
||||
|
||||
constructor(uri: string, model: IModel, owner: AbstractCodeEditorService) {
|
||||
this.uri = uri;
|
||||
this._values = {};
|
||||
model.onWillDispose(() => owner._removeWatcher(this));
|
||||
}
|
||||
|
||||
public set(key: string, value: any): void {
|
||||
this._values[key] = value;
|
||||
}
|
||||
|
||||
public get(key: string): any {
|
||||
return this._values[key];
|
||||
}
|
||||
}
|
||||
382
src/vs/editor/browser/services/bulkEdit.ts
Normal file
382
src/vs/editor/browser/services/bulkEdit.ts
Normal file
@@ -0,0 +1,382 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
import { IStringDictionary, forEach, values, groupBy, size } from 'vs/base/common/collections';
|
||||
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { IFileService, IFileChange } from 'vs/platform/files/common/files';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { Selection, ISelection } from 'vs/editor/common/core/selection';
|
||||
import { IIdentifiedSingleEditOperation, IModel, EndOfLineSequence } from 'vs/editor/common/editorCommon';
|
||||
import { IProgressRunner } from 'vs/platform/progress/common/progress';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export interface IResourceEdit {
|
||||
resource: URI;
|
||||
range?: IRange;
|
||||
newText: string;
|
||||
newEol?: EndOfLineSequence;
|
||||
}
|
||||
|
||||
interface IRecording {
|
||||
stop(): void;
|
||||
hasChanged(resource: URI): boolean;
|
||||
allChanges(): IFileChange[];
|
||||
}
|
||||
|
||||
class ChangeRecorder {
|
||||
|
||||
private _fileService: IFileService;
|
||||
|
||||
constructor(fileService?: IFileService) {
|
||||
this._fileService = fileService;
|
||||
}
|
||||
|
||||
public start(): IRecording {
|
||||
|
||||
const changes: IStringDictionary<IFileChange[]> = Object.create(null);
|
||||
|
||||
let stop: IDisposable;
|
||||
if (this._fileService) {
|
||||
stop = this._fileService.onFileChanges((event) => {
|
||||
event.changes.forEach(change => {
|
||||
|
||||
const key = String(change.resource);
|
||||
let array = changes[key];
|
||||
|
||||
if (!array) {
|
||||
changes[key] = array = [];
|
||||
}
|
||||
|
||||
array.push(change);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
stop: () => { return stop && stop.dispose(); },
|
||||
hasChanged: (resource: URI) => !!changes[resource.toString()],
|
||||
allChanges: () => flatten(values(changes))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class EditTask implements IDisposable {
|
||||
|
||||
private _initialSelections: Selection[];
|
||||
private _endCursorSelection: Selection;
|
||||
private get _model(): IModel { return this._modelReference.object.textEditorModel; }
|
||||
private _modelReference: IReference<ITextEditorModel>;
|
||||
private _edits: IIdentifiedSingleEditOperation[];
|
||||
private _newEol: EndOfLineSequence;
|
||||
|
||||
constructor(modelReference: IReference<ITextEditorModel>) {
|
||||
this._endCursorSelection = null;
|
||||
this._modelReference = modelReference;
|
||||
this._edits = [];
|
||||
}
|
||||
|
||||
public addEdit(edit: IResourceEdit): void {
|
||||
|
||||
if (typeof edit.newEol === 'number') {
|
||||
// honor eol-change
|
||||
this._newEol = edit.newEol;
|
||||
}
|
||||
|
||||
if (edit.range || edit.newText) {
|
||||
// create edit operation
|
||||
let range: Range;
|
||||
if (!edit.range) {
|
||||
range = this._model.getFullModelRange();
|
||||
} else {
|
||||
range = Range.lift(edit.range);
|
||||
}
|
||||
this._edits.push(EditOperation.replaceMove(range, edit.newText));
|
||||
}
|
||||
}
|
||||
|
||||
public apply(): void {
|
||||
if (this._edits.length > 0) {
|
||||
|
||||
this._edits = this._edits.map((value, index) => ({ value, index })).sort((a, b) => {
|
||||
let ret = Range.compareRangesUsingStarts(a.value.range, b.value.range);
|
||||
if (ret === 0) {
|
||||
ret = a.index - b.index;
|
||||
}
|
||||
return ret;
|
||||
}).map(element => element.value);
|
||||
|
||||
this._initialSelections = this._getInitialSelections();
|
||||
this._model.pushStackElement();
|
||||
this._model.pushEditOperations(this._initialSelections, this._edits, (edits) => this._getEndCursorSelections(edits));
|
||||
this._model.pushStackElement();
|
||||
}
|
||||
if (this._newEol !== undefined) {
|
||||
this._model.pushStackElement();
|
||||
this._model.setEOL(this._newEol);
|
||||
this._model.pushStackElement();
|
||||
}
|
||||
}
|
||||
|
||||
protected _getInitialSelections(): Selection[] {
|
||||
const firstRange = this._edits[0].range;
|
||||
const initialSelection = new Selection(
|
||||
firstRange.startLineNumber,
|
||||
firstRange.startColumn,
|
||||
firstRange.endLineNumber,
|
||||
firstRange.endColumn
|
||||
);
|
||||
return [initialSelection];
|
||||
}
|
||||
|
||||
private _getEndCursorSelections(inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] {
|
||||
let relevantEditIndex = 0;
|
||||
for (let i = 0; i < inverseEditOperations.length; i++) {
|
||||
const editRange = inverseEditOperations[i].range;
|
||||
for (let j = 0; j < this._initialSelections.length; j++) {
|
||||
const selectionRange = this._initialSelections[j];
|
||||
if (Range.areIntersectingOrTouching(editRange, selectionRange)) {
|
||||
relevantEditIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const srcRange = inverseEditOperations[relevantEditIndex].range;
|
||||
this._endCursorSelection = new Selection(
|
||||
srcRange.endLineNumber,
|
||||
srcRange.endColumn,
|
||||
srcRange.endLineNumber,
|
||||
srcRange.endColumn
|
||||
);
|
||||
return [this._endCursorSelection];
|
||||
}
|
||||
|
||||
public getEndCursorSelection(): Selection {
|
||||
return this._endCursorSelection;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
if (this._model) {
|
||||
this._modelReference.dispose();
|
||||
this._modelReference = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SourceModelEditTask extends EditTask {
|
||||
|
||||
private _knownInitialSelections: Selection[];
|
||||
|
||||
constructor(modelReference: IReference<ITextEditorModel>, initialSelections: Selection[]) {
|
||||
super(modelReference);
|
||||
this._knownInitialSelections = initialSelections;
|
||||
}
|
||||
|
||||
protected _getInitialSelections(): Selection[] {
|
||||
return this._knownInitialSelections;
|
||||
}
|
||||
}
|
||||
|
||||
class BulkEditModel implements IDisposable {
|
||||
|
||||
private _textModelResolverService: ITextModelService;
|
||||
private _numberOfResourcesToModify: number = 0;
|
||||
private _edits: IStringDictionary<IResourceEdit[]> = Object.create(null);
|
||||
private _tasks: EditTask[];
|
||||
private _sourceModel: URI;
|
||||
private _sourceSelections: Selection[];
|
||||
private _sourceModelTask: SourceModelEditTask;
|
||||
|
||||
constructor(textModelResolverService: ITextModelService, sourceModel: URI, sourceSelections: Selection[], edits: IResourceEdit[], private progress: IProgressRunner = null) {
|
||||
this._textModelResolverService = textModelResolverService;
|
||||
this._sourceModel = sourceModel;
|
||||
this._sourceSelections = sourceSelections;
|
||||
this._sourceModelTask = null;
|
||||
|
||||
for (let edit of edits) {
|
||||
this._addEdit(edit);
|
||||
}
|
||||
}
|
||||
|
||||
private _addEdit(edit: IResourceEdit): void {
|
||||
let array = this._edits[edit.resource.toString()];
|
||||
if (!array) {
|
||||
this._edits[edit.resource.toString()] = array = [];
|
||||
this._numberOfResourcesToModify += 1;
|
||||
}
|
||||
array.push(edit);
|
||||
}
|
||||
|
||||
public prepare(): TPromise<BulkEditModel> {
|
||||
|
||||
if (this._tasks) {
|
||||
throw new Error('illegal state - already prepared');
|
||||
}
|
||||
|
||||
this._tasks = [];
|
||||
const promises: TPromise<any>[] = [];
|
||||
|
||||
if (this.progress) {
|
||||
this.progress.total(this._numberOfResourcesToModify * 2);
|
||||
}
|
||||
|
||||
forEach(this._edits, entry => {
|
||||
const promise = this._textModelResolverService.createModelReference(URI.parse(entry.key)).then(ref => {
|
||||
const model = ref.object;
|
||||
|
||||
if (!model || !model.textEditorModel) {
|
||||
throw new Error(`Cannot load file ${entry.key}`);
|
||||
}
|
||||
|
||||
const textEditorModel = model.textEditorModel;
|
||||
let task: EditTask;
|
||||
|
||||
if (this._sourceModel && textEditorModel.uri.toString() === this._sourceModel.toString()) {
|
||||
this._sourceModelTask = new SourceModelEditTask(ref, this._sourceSelections);
|
||||
task = this._sourceModelTask;
|
||||
} else {
|
||||
task = new EditTask(ref);
|
||||
}
|
||||
|
||||
entry.value.forEach(edit => task.addEdit(edit));
|
||||
this._tasks.push(task);
|
||||
if (this.progress) {
|
||||
this.progress.worked(1);
|
||||
}
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
|
||||
|
||||
return TPromise.join(promises).then(_ => this);
|
||||
}
|
||||
|
||||
public apply(): Selection {
|
||||
this._tasks.forEach(task => this.applyTask(task));
|
||||
let r: Selection = null;
|
||||
if (this._sourceModelTask) {
|
||||
r = this._sourceModelTask.getEndCursorSelection();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private applyTask(task: EditTask): void {
|
||||
task.apply();
|
||||
if (this.progress) {
|
||||
this.progress.worked(1);
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._tasks = dispose(this._tasks);
|
||||
}
|
||||
}
|
||||
|
||||
export interface BulkEdit {
|
||||
progress(progress: IProgressRunner): void;
|
||||
add(edit: IResourceEdit[]): void;
|
||||
finish(): TPromise<ISelection>;
|
||||
ariaMessage(): string;
|
||||
}
|
||||
|
||||
export function bulkEdit(textModelResolverService: ITextModelService, editor: ICodeEditor, edits: IResourceEdit[], fileService?: IFileService, progress: IProgressRunner = null): TPromise<any> {
|
||||
let bulk = createBulkEdit(textModelResolverService, editor, fileService);
|
||||
bulk.add(edits);
|
||||
bulk.progress(progress);
|
||||
return bulk.finish();
|
||||
}
|
||||
|
||||
export function createBulkEdit(textModelResolverService: ITextModelService, editor?: ICodeEditor, fileService?: IFileService): BulkEdit {
|
||||
|
||||
let all: IResourceEdit[] = [];
|
||||
let recording = new ChangeRecorder(fileService).start();
|
||||
let progressRunner: IProgressRunner;
|
||||
|
||||
function progress(progress: IProgressRunner) {
|
||||
progressRunner = progress;
|
||||
}
|
||||
|
||||
function add(edits: IResourceEdit[]): void {
|
||||
all.push(...edits);
|
||||
}
|
||||
|
||||
function getConcurrentEdits() {
|
||||
let names: string[];
|
||||
for (let edit of all) {
|
||||
if (recording.hasChanged(edit.resource)) {
|
||||
if (!names) {
|
||||
names = [];
|
||||
}
|
||||
names.push(edit.resource.fsPath);
|
||||
}
|
||||
}
|
||||
if (names) {
|
||||
return nls.localize('conflict', "These files have changed in the meantime: {0}", names.join(', '));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function finish(): TPromise<ISelection> {
|
||||
|
||||
if (all.length === 0) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
let concurrentEdits = getConcurrentEdits();
|
||||
if (concurrentEdits) {
|
||||
return TPromise.wrapError<ISelection>(new Error(concurrentEdits));
|
||||
}
|
||||
|
||||
let uri: URI;
|
||||
let selections: Selection[];
|
||||
|
||||
if (editor && editor.getModel()) {
|
||||
uri = editor.getModel().uri;
|
||||
selections = editor.getSelections();
|
||||
}
|
||||
|
||||
const model = new BulkEditModel(textModelResolverService, uri, selections, all, progressRunner);
|
||||
|
||||
return model.prepare().then(_ => {
|
||||
|
||||
let concurrentEdits = getConcurrentEdits();
|
||||
if (concurrentEdits) {
|
||||
throw new Error(concurrentEdits);
|
||||
}
|
||||
|
||||
recording.stop();
|
||||
|
||||
const result = model.apply();
|
||||
model.dispose();
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function ariaMessage(): string {
|
||||
let editCount = all.length;
|
||||
let resourceCount = size(groupBy(all, edit => edit.resource.toString()));
|
||||
if (editCount === 0) {
|
||||
return nls.localize('summary.0', "Made no edits");
|
||||
} else if (editCount > 1 && resourceCount > 1) {
|
||||
return nls.localize('summary.nm', "Made {0} text edits in {1} files", editCount, resourceCount);
|
||||
} else {
|
||||
return nls.localize('summary.n0', "Made {0} text edits in one file", editCount, resourceCount);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
progress,
|
||||
add,
|
||||
finish,
|
||||
ariaMessage
|
||||
};
|
||||
}
|
||||
79
src/vs/editor/browser/services/codeEditorService.ts
Normal file
79
src/vs/editor/browser/services/codeEditorService.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDecorationRenderOptions, IModelDecorationOptions, IModel } from 'vs/editor/common/editorCommon';
|
||||
import { IEditor } from 'vs/platform/editor/common/editor';
|
||||
import { ICodeEditor, IDiffEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
export const ICodeEditorService = createDecorator<ICodeEditorService>('codeEditorService');
|
||||
|
||||
export interface ICodeEditorService {
|
||||
_serviceBrand: any;
|
||||
|
||||
onCodeEditorAdd: Event<ICodeEditor>;
|
||||
onCodeEditorRemove: Event<ICodeEditor>;
|
||||
|
||||
onDiffEditorAdd: Event<IDiffEditor>;
|
||||
onDiffEditorRemove: Event<IDiffEditor>;
|
||||
|
||||
addCodeEditor(editor: ICodeEditor): void;
|
||||
removeCodeEditor(editor: ICodeEditor): void;
|
||||
listCodeEditors(): ICodeEditor[];
|
||||
|
||||
addDiffEditor(editor: IDiffEditor): void;
|
||||
removeDiffEditor(editor: IDiffEditor): void;
|
||||
listDiffEditors(): IDiffEditor[];
|
||||
|
||||
/**
|
||||
* Returns the current focused code editor (if the focus is in the editor or in an editor widget) or null.
|
||||
*/
|
||||
getFocusedCodeEditor(): ICodeEditor;
|
||||
|
||||
registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
|
||||
removeDecorationType(key: string): void;
|
||||
resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions;
|
||||
|
||||
setTransientModelProperty(model: IModel, key: string, value: any): void;
|
||||
getTransientModelProperty(model: IModel, key: string): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses `editor.getControl()` and returns either a `codeEditor` or a `diffEditor` or nothing.
|
||||
*/
|
||||
export function getCodeOrDiffEditor(editor: IEditor): { codeEditor: ICodeEditor; diffEditor: IDiffEditor } {
|
||||
if (editor) {
|
||||
let control = editor.getControl();
|
||||
if (control) {
|
||||
if (isCodeEditor(control)) {
|
||||
return {
|
||||
codeEditor: control,
|
||||
diffEditor: null
|
||||
};
|
||||
}
|
||||
if (isDiffEditor(control)) {
|
||||
return {
|
||||
codeEditor: null,
|
||||
diffEditor: control
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
codeEditor: null,
|
||||
diffEditor: null
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses `editor.getControl()` and returns either the code editor, or the modified editor of a diff editor or nothing.
|
||||
*/
|
||||
export function getCodeEditor(editor: IEditor): ICodeEditor {
|
||||
let r = getCodeOrDiffEditor(editor);
|
||||
return r.codeEditor || (r.diffEditor && <ICodeEditor>r.diffEditor.getModifiedEditor()) || null;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
IDecorationRenderOptions, IModelDecorationOptions, IModelDecorationOverviewRulerOptions, IThemeDecorationRenderOptions,
|
||||
IContentDecorationRenderOptions, OverviewRulerLane, TrackedRangeStickiness, isThemeColor
|
||||
} from 'vs/editor/common/editorCommon';
|
||||
import { AbstractCodeEditorService } from 'vs/editor/common/services/abstractCodeEditorService';
|
||||
import { AbstractCodeEditorService } from 'vs/editor/browser/services/abstractCodeEditorService';
|
||||
import { IDisposable, dispose as disposeAll } from 'vs/base/common/lifecycle';
|
||||
import { IThemeService, ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
@@ -35,7 +35,7 @@ export class CodeEditorServiceImpl extends AbstractCodeEditorService {
|
||||
styleSheet: this._styleSheet,
|
||||
key: key,
|
||||
parentTypeKey: parentTypeKey,
|
||||
options: options
|
||||
options: options || Object.create(null)
|
||||
};
|
||||
if (!parentTypeKey) {
|
||||
provider = new DecorationTypeOptionsProvider(this._themeService, providerArgs);
|
||||
@@ -283,7 +283,7 @@ class DecorationCSSRules {
|
||||
|
||||
private _buildCSS(): void {
|
||||
let options = this._providerArgs.options;
|
||||
let unthemedCSS, lightCSS, darkCSS: string;
|
||||
let unthemedCSS: string, lightCSS: string, darkCSS: string;
|
||||
switch (this._ruleType) {
|
||||
case ModelDecorationCSSRuleType.ClassName:
|
||||
unthemedCSS = this.getCSSTextForModelDecorationClassName(options);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
|
||||
import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/common/controller/coreCommands';
|
||||
import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
|
||||
import { Configuration } from 'vs/editor/browser/config/configuration';
|
||||
|
||||
export interface ExecCoreEditorCommandFunc {
|
||||
|
||||
@@ -90,8 +90,6 @@ export class View extends ViewEventHandler {
|
||||
private overflowGuardContainer: FastDomNode<HTMLElement>;
|
||||
|
||||
// Actual mutable state
|
||||
private _isDisposed: boolean;
|
||||
|
||||
private _renderAnimationFrame: IDisposable;
|
||||
|
||||
constructor(
|
||||
@@ -103,7 +101,6 @@ export class View extends ViewEventHandler {
|
||||
execCoreEditorCommandFunc: ExecCoreEditorCommandFunc
|
||||
) {
|
||||
super();
|
||||
this._isDisposed = false;
|
||||
this._cursor = cursor;
|
||||
this._renderAnimationFrame = null;
|
||||
this.outgoingEvents = new ViewOutgoingEvents(model);
|
||||
@@ -344,7 +341,6 @@ export class View extends ViewEventHandler {
|
||||
// --- end event handlers
|
||||
|
||||
public dispose(): void {
|
||||
this._isDisposed = true;
|
||||
if (this._renderAnimationFrame !== null) {
|
||||
this._renderAnimationFrame.dispose();
|
||||
this._renderAnimationFrame = null;
|
||||
@@ -533,10 +529,6 @@ export class View extends ViewEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public setAriaActiveDescendant(id: string): void {
|
||||
this._textAreaHandler.setAriaActiveDescendant(id);
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
this._textAreaHandler.focusTextArea();
|
||||
}
|
||||
|
||||
@@ -12,13 +12,10 @@ import { createStringBuilder, IStringBuilder } from 'vs/editor/common/core/strin
|
||||
/**
|
||||
* Represents a visible line
|
||||
*/
|
||||
export interface IVisibleLine {
|
||||
export interface IVisibleLine extends ILine {
|
||||
getDomNode(): HTMLElement;
|
||||
setDomNode(domNode: HTMLElement): void;
|
||||
|
||||
onContentChanged(): void;
|
||||
onTokensChanged(): void;
|
||||
|
||||
/**
|
||||
* Return null if the HTML should not be touched.
|
||||
* Return the new HTML otherwise.
|
||||
@@ -538,7 +535,7 @@ class ViewLayerRenderer<T extends IVisibleLine> {
|
||||
}
|
||||
}
|
||||
|
||||
private static _sb = createStringBuilder(100000);
|
||||
private static readonly _sb = createStringBuilder(100000);
|
||||
|
||||
private _finishRendering(ctx: IRendererContext<T>, domNodeIsEmpty: boolean, deltaTop: number[]): void {
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common
|
||||
export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
|
||||
private _context: ViewContext;
|
||||
private _lineHeight: number;
|
||||
private _readOnly: boolean;
|
||||
private _renderLineHighlight: 'none' | 'gutter' | 'line' | 'all';
|
||||
private _selectionIsEmpty: boolean;
|
||||
private _primaryCursorIsInEditableRange: boolean;
|
||||
@@ -28,7 +27,6 @@ export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
|
||||
super();
|
||||
this._context = context;
|
||||
this._lineHeight = this._context.configuration.editor.lineHeight;
|
||||
this._readOnly = this._context.configuration.editor.readOnly;
|
||||
this._renderLineHighlight = this._context.configuration.editor.viewInfo.renderLineHighlight;
|
||||
|
||||
this._selectionIsEmpty = true;
|
||||
@@ -52,9 +50,6 @@ export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
|
||||
if (e.lineHeight) {
|
||||
this._lineHeight = this._context.configuration.editor.lineHeight;
|
||||
}
|
||||
if (e.readOnly) {
|
||||
this._readOnly = this._context.configuration.editor.readOnly;
|
||||
}
|
||||
if (e.viewInfo) {
|
||||
this._renderLineHighlight = this._context.configuration.editor.viewInfo.renderLineHighlight;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/v
|
||||
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ISimplifiedMouseEvent } from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
|
||||
|
||||
export class EditorScrollbar extends ViewPart {
|
||||
|
||||
@@ -89,6 +88,7 @@ export class EditorScrollbar extends ViewPart {
|
||||
this._register(dom.addDisposableListener(viewDomNode.domNode, 'scroll', (e: Event) => onBrowserDesperateReveal(viewDomNode.domNode, true, true)));
|
||||
this._register(dom.addDisposableListener(linesContent.domNode, 'scroll', (e: Event) => onBrowserDesperateReveal(linesContent.domNode, true, false)));
|
||||
this._register(dom.addDisposableListener(overflowGuardDomNode.domNode, 'scroll', (e: Event) => onBrowserDesperateReveal(overflowGuardDomNode.domNode, true, false)));
|
||||
this._register(dom.addDisposableListener(this.scrollbarDomNode.domNode, 'scroll', (e: Event) => onBrowserDesperateReveal(this.scrollbarDomNode.domNode, true, false)));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -115,10 +115,6 @@ export class EditorScrollbar extends ViewPart {
|
||||
this.scrollbar.delegateVerticalScrollbarMouseDown(browserEvent);
|
||||
}
|
||||
|
||||
public delegateSliderMouseDown(e: ISimplifiedMouseEvent, onDragFinished: () => void): void {
|
||||
this.scrollbar.delegateSliderMouseDown(e, onDragFinished);
|
||||
}
|
||||
|
||||
// --- begin event handlers
|
||||
|
||||
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
|
||||
|
||||
@@ -14,20 +14,19 @@ import { ViewContext } from 'vs/editor/common/view/viewContext';
|
||||
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
|
||||
public static CLASS_NAME = 'line-numbers';
|
||||
public static readonly CLASS_NAME = 'line-numbers';
|
||||
|
||||
private _context: ViewContext;
|
||||
|
||||
private _lineHeight: number;
|
||||
private _renderLineNumbers: boolean;
|
||||
private _renderLineNumbers: RenderLineNumbersType;
|
||||
private _renderCustomLineNumbers: (lineNumber: number) => string;
|
||||
private _renderRelativeLineNumbers: boolean;
|
||||
private _lineNumbersLeft: number;
|
||||
private _lineNumbersWidth: number;
|
||||
|
||||
private _lastCursorModelPosition: Position;
|
||||
private _renderResult: string[];
|
||||
|
||||
@@ -47,7 +46,6 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
this._lineHeight = config.lineHeight;
|
||||
this._renderLineNumbers = config.viewInfo.renderLineNumbers;
|
||||
this._renderCustomLineNumbers = config.viewInfo.renderCustomLineNumbers;
|
||||
this._renderRelativeLineNumbers = config.viewInfo.renderRelativeLineNumbers;
|
||||
this._lineNumbersLeft = config.layoutInfo.lineNumbersLeft;
|
||||
this._lineNumbersWidth = config.layoutInfo.lineNumbersWidth;
|
||||
}
|
||||
@@ -69,7 +67,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
const primaryViewPosition = e.selections[0].getPosition();
|
||||
this._lastCursorModelPosition = this._context.model.coordinatesConverter.convertViewPositionToModelPosition(primaryViewPosition);
|
||||
|
||||
if (this._renderRelativeLineNumbers) {
|
||||
if (this._renderLineNumbers === RenderLineNumbersType.Relative || this._renderLineNumbers === RenderLineNumbersType.Interval) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -106,7 +104,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
return this._renderCustomLineNumbers(modelLineNumber);
|
||||
}
|
||||
|
||||
if (this._renderRelativeLineNumbers) {
|
||||
if (this._renderLineNumbers === RenderLineNumbersType.Relative) {
|
||||
let diff = Math.abs(this._lastCursorModelPosition.lineNumber - modelLineNumber);
|
||||
if (diff === 0) {
|
||||
return '<span class="relative-current-line-number">' + modelLineNumber + '</span>';
|
||||
@@ -114,11 +112,21 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
return String(diff);
|
||||
}
|
||||
|
||||
if (this._renderLineNumbers === RenderLineNumbersType.Interval) {
|
||||
if (this._lastCursorModelPosition.lineNumber === modelLineNumber) {
|
||||
return String(modelLineNumber);
|
||||
}
|
||||
if (modelLineNumber % 10 === 0) {
|
||||
return String(modelLineNumber);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
return String(modelLineNumber);
|
||||
}
|
||||
|
||||
public prepareRender(ctx: RenderingContext): void {
|
||||
if (!this._renderLineNumbers) {
|
||||
if (this._renderLineNumbers === RenderLineNumbersType.Off) {
|
||||
this._renderResult = null;
|
||||
return;
|
||||
}
|
||||
@@ -133,6 +141,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
let lineIndex = lineNumber - visibleStartLineNumber;
|
||||
|
||||
let renderLineNumber = this._getLineRenderLineNumber(lineNumber);
|
||||
|
||||
if (renderLineNumber) {
|
||||
output[lineIndex] = (
|
||||
common
|
||||
@@ -166,4 +175,4 @@ registerThemingParticipant((theme, collector) => {
|
||||
if (lineNumbers) {
|
||||
collector.addRule(`.monaco-editor .line-numbers { color: ${lineNumbers}; }`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
|
||||
import { Constants } from 'vs/editor/common/core/uint';
|
||||
|
||||
class FloatHorizontalRange {
|
||||
_floatHorizontalRangeBrand: void;
|
||||
@@ -133,6 +134,18 @@ export class RangeUtil {
|
||||
let startElement = domNode.children[startChildIndex].firstChild;
|
||||
let endElement = domNode.children[endChildIndex].firstChild;
|
||||
|
||||
if (!startElement || !endElement) {
|
||||
// When having an empty <span> (without any text content), try to move to the previous <span>
|
||||
if (!startElement && startOffset === 0 && startChildIndex > 0) {
|
||||
startElement = domNode.children[startChildIndex - 1].firstChild;
|
||||
startOffset = Constants.MAX_SAFE_SMALL_INTEGER;
|
||||
}
|
||||
if (!endElement && endOffset === 0 && endChildIndex > 0) {
|
||||
endElement = domNode.children[endChildIndex - 1].firstChild;
|
||||
endOffset = Constants.MAX_SAFE_SMALL_INTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!startElement || !endElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
|
||||
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
|
||||
import { ThemeType, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
|
||||
import { IStringBuilder } from 'vs/editor/common/core/stringBuilder';
|
||||
import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
|
||||
|
||||
const canUseFastRenderedViewLine = (function () {
|
||||
if (platform.isNative) {
|
||||
@@ -108,7 +109,7 @@ export class ViewLineOptions {
|
||||
|
||||
export class ViewLine implements IVisibleLine {
|
||||
|
||||
public static CLASS_NAME = 'view-line';
|
||||
public static readonly CLASS_NAME = 'view-line';
|
||||
|
||||
private _options: ViewLineOptions;
|
||||
private _isMaybeInvalid: boolean;
|
||||
@@ -183,7 +184,7 @@ export class ViewLine implements IVisibleLine {
|
||||
let endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn);
|
||||
|
||||
if (startColumn < endColumn) {
|
||||
actualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', false));
|
||||
actualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', InlineDecorationType.Regular));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
|
||||
/**
|
||||
* Adds this ammount of pixels to the right of lines (no-one wants to type near the edge of the viewport)
|
||||
*/
|
||||
private static HORIZONTAL_EXTRA_PX = 30;
|
||||
private static readonly HORIZONTAL_EXTRA_PX = 30;
|
||||
|
||||
private readonly _linesContent: FastDomNode<HTMLElement>;
|
||||
private readonly _textRangeRestingSpot: HTMLElement;
|
||||
|
||||
@@ -13,7 +13,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
|
||||
export class Margin extends ViewPart {
|
||||
|
||||
public static CLASS_NAME = 'glyph-margin';
|
||||
public static readonly CLASS_NAME = 'glyph-margin';
|
||||
|
||||
private _domNode: FastDomNode<HTMLElement>;
|
||||
private _canUseLayerHinting: boolean;
|
||||
|
||||
@@ -290,7 +290,7 @@ class MinimapLayout {
|
||||
|
||||
class MinimapLine implements ILine {
|
||||
|
||||
public static INVALID = new MinimapLine(-1);
|
||||
public static readonly INVALID = new MinimapLine(-1);
|
||||
|
||||
dy: number;
|
||||
|
||||
@@ -439,8 +439,6 @@ export class Minimap extends ViewPart {
|
||||
private readonly _sliderMouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
|
||||
private readonly _sliderMouseDownListener: IDisposable;
|
||||
|
||||
private readonly _minimapCharRenderer: MinimapCharRenderer;
|
||||
|
||||
private _options: MinimapOptions;
|
||||
private _lastRenderData: RenderData;
|
||||
private _buffers: MinimapBuffers;
|
||||
@@ -482,8 +480,6 @@ export class Minimap extends ViewPart {
|
||||
|
||||
this._tokensColorTracker = MinimapTokensColorTracker.getInstance();
|
||||
|
||||
this._minimapCharRenderer = getOrCreateMinimapCharRenderer();
|
||||
|
||||
this._applyLayout();
|
||||
|
||||
this._mouseDownListener = dom.addStandardDisposableListener(this._canvas.domNode, 'mousedown', (e) => {
|
||||
@@ -734,7 +730,7 @@ export class Minimap extends ViewPart {
|
||||
useLighterFont,
|
||||
renderMinimap,
|
||||
this._tokensColorTracker,
|
||||
this._minimapCharRenderer,
|
||||
getOrCreateMinimapCharRenderer(),
|
||||
dy,
|
||||
tabSize,
|
||||
lineInfo.data[lineIndex]
|
||||
|
||||
@@ -258,6 +258,7 @@ export class DecorationsOverviewRuler extends ViewPart {
|
||||
for (let i = 0, len = e.selections.length; i < len; i++) {
|
||||
this._cursorPositions[i] = e.selections[i].getPosition();
|
||||
}
|
||||
this._cursorPositions.sort(Position.compare);
|
||||
return true;
|
||||
}
|
||||
public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {
|
||||
@@ -418,4 +419,3 @@ export class DecorationsOverviewRuler extends ViewPart {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ export class Rulers extends ViewPart {
|
||||
public domNode: FastDomNode<HTMLElement>;
|
||||
private _renderedRulers: FastDomNode<HTMLElement>[];
|
||||
private _rulers: number[];
|
||||
private _height: number;
|
||||
private _typicalHalfwidthCharacterWidth: number;
|
||||
|
||||
constructor(context: ViewContext) {
|
||||
@@ -31,7 +30,6 @@ export class Rulers extends ViewPart {
|
||||
this.domNode.setClassName('view-rulers');
|
||||
this._renderedRulers = [];
|
||||
this._rulers = this._context.configuration.editor.viewInfo.rulers;
|
||||
this._height = this._context.configuration.editor.layoutInfo.contentHeight;
|
||||
this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth;
|
||||
}
|
||||
|
||||
@@ -44,7 +42,6 @@ export class Rulers extends ViewPart {
|
||||
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
|
||||
if (e.viewInfo || e.layoutInfo || e.fontInfo) {
|
||||
this._rulers = this._context.configuration.editor.viewInfo.rulers;
|
||||
this._height = this._context.configuration.editor.layoutInfo.contentHeight;
|
||||
this._typicalHalfwidthCharacterWidth = this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -66,14 +66,14 @@ const isIEWithZoomingIssuesNearRoundedBorders = browser.isEdgeOrIE;
|
||||
|
||||
export class SelectionsOverlay extends DynamicViewOverlay {
|
||||
|
||||
private static SELECTION_CLASS_NAME = 'selected-text';
|
||||
private static SELECTION_TOP_LEFT = 'top-left-radius';
|
||||
private static SELECTION_BOTTOM_LEFT = 'bottom-left-radius';
|
||||
private static SELECTION_TOP_RIGHT = 'top-right-radius';
|
||||
private static SELECTION_BOTTOM_RIGHT = 'bottom-right-radius';
|
||||
private static EDITOR_BACKGROUND_CLASS_NAME = 'monaco-editor-background';
|
||||
private static readonly SELECTION_CLASS_NAME = 'selected-text';
|
||||
private static readonly SELECTION_TOP_LEFT = 'top-left-radius';
|
||||
private static readonly SELECTION_BOTTOM_LEFT = 'bottom-left-radius';
|
||||
private static readonly SELECTION_TOP_RIGHT = 'top-right-radius';
|
||||
private static readonly SELECTION_BOTTOM_RIGHT = 'bottom-right-radius';
|
||||
private static readonly EDITOR_BACKGROUND_CLASS_NAME = 'monaco-editor-background';
|
||||
|
||||
private static ROUNDED_PIECE_WIDTH = 10;
|
||||
private static readonly ROUNDED_PIECE_WIDTH = 10;
|
||||
|
||||
private _context: ViewContext;
|
||||
private _lineHeight: number;
|
||||
|
||||
@@ -192,10 +192,6 @@ export class ViewCursors extends ViewPart {
|
||||
|
||||
// --- end event handlers
|
||||
|
||||
public getPosition(): Position {
|
||||
return this._primaryCursor.getPosition();
|
||||
}
|
||||
|
||||
// ---- blinking logic
|
||||
|
||||
private _getCursorBlinking(): TextEditorCursorBlinkingStyle {
|
||||
@@ -365,4 +361,4 @@ registerThemingParticipant((theme, collector) => {
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,10 +22,6 @@ export interface IMyViewZone {
|
||||
marginDomNode: FastDomNode<HTMLElement>;
|
||||
}
|
||||
|
||||
export interface IMyRenderData {
|
||||
data: IViewWhitespaceViewportData[];
|
||||
}
|
||||
|
||||
interface IComputedViewZoneProps {
|
||||
afterViewLineNumber: number;
|
||||
heightInPx: number;
|
||||
|
||||
@@ -14,10 +14,9 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { CommonCodeEditor } from 'vs/editor/common/commonCodeEditor';
|
||||
import { CommonEditorConfiguration } from 'vs/editor/common/config/commonEditorConfig';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { EditorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { EditorAction, EditorExtensionsRegistry, IEditorContributionCtor } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { Configuration } from 'vs/editor/browser/config/configuration';
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { View, IOverlayWidgetData, IContentWidgetData } from 'vs/editor/browser/view/viewImpl';
|
||||
@@ -27,12 +26,12 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { InternalEditorAction } from 'vs/editor/common/editorAction';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { CoreEditorCommand } from 'vs/editor/common/controller/coreCommands';
|
||||
import { CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
|
||||
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoBorder, editorInfoForeground } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ClassName } from 'vs/editor/common/model/intervalTree';
|
||||
|
||||
export abstract class CodeEditorWidget extends CommonCodeEditor implements editorBrowser.ICodeEditor {
|
||||
|
||||
@@ -141,7 +140,7 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
|
||||
this._codeEditorService.addCodeEditor(this);
|
||||
}
|
||||
|
||||
protected abstract _getContributions(): editorBrowser.IEditorContributionCtor[];
|
||||
protected abstract _getContributions(): IEditorContributionCtor[];
|
||||
protected abstract _getActions(): EditorAction[];
|
||||
|
||||
protected _createConfiguration(options: IEditorOptions): CommonEditorConfiguration {
|
||||
@@ -169,14 +168,6 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
|
||||
return this._view.domNode.domNode;
|
||||
}
|
||||
|
||||
public getCompletelyVisibleLinesRangeInViewport(): Range {
|
||||
if (!this.hasView) {
|
||||
return null;
|
||||
}
|
||||
const viewRange = this.viewModel.getCompletelyVisibleViewRange();
|
||||
return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(viewRange);
|
||||
}
|
||||
|
||||
public delegateVerticalScrollbarMouseDown(browserEvent: IMouseEvent): void {
|
||||
if (!this.hasView) {
|
||||
return;
|
||||
@@ -292,36 +283,6 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
|
||||
}
|
||||
}
|
||||
|
||||
public getWhitespaces(): IEditorWhitespace[] {
|
||||
if (!this.hasView) {
|
||||
return [];
|
||||
}
|
||||
return this.viewModel.viewLayout.getWhitespaces();
|
||||
}
|
||||
|
||||
private _getVerticalOffsetForPosition(modelLineNumber: number, modelColumn: number): number {
|
||||
let modelPosition = this.model.validatePosition({
|
||||
lineNumber: modelLineNumber,
|
||||
column: modelColumn
|
||||
});
|
||||
let viewPosition = this.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
|
||||
return this.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
|
||||
}
|
||||
|
||||
public getTopForLineNumber(lineNumber: number): number {
|
||||
if (!this.hasView) {
|
||||
return -1;
|
||||
}
|
||||
return this._getVerticalOffsetForPosition(lineNumber, 1);
|
||||
}
|
||||
|
||||
public getTopForPosition(lineNumber: number, column: number): number {
|
||||
if (!this.hasView) {
|
||||
return -1;
|
||||
}
|
||||
return this._getVerticalOffsetForPosition(lineNumber, column);
|
||||
}
|
||||
|
||||
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget {
|
||||
if (!this.hasView) {
|
||||
return null;
|
||||
@@ -361,19 +322,6 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
|
||||
this._view.render(true, false);
|
||||
}
|
||||
|
||||
public setHiddenAreas(ranges: IRange[]): void {
|
||||
if (this.viewModel) {
|
||||
this.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)));
|
||||
}
|
||||
}
|
||||
|
||||
public setAriaActiveDescendant(id: string): void {
|
||||
if (!this.hasView) {
|
||||
return;
|
||||
}
|
||||
this._view.setAriaActiveDescendant(id);
|
||||
}
|
||||
|
||||
public applyFontInfo(target: HTMLElement): void {
|
||||
Configuration.applyFontInfoSlow(target, this._configuration.editor.fontInfo);
|
||||
}
|
||||
@@ -477,6 +425,18 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
|
||||
}
|
||||
|
||||
// END decorations
|
||||
|
||||
protected _triggerEditorCommand(source: string, handlerId: string, payload: any): boolean {
|
||||
const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
|
||||
if (command) {
|
||||
payload = payload || {};
|
||||
payload.source = source;
|
||||
TPromise.as(command.runEditorCommand(null, this, payload)).done(null, onUnexpectedError);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class CodeEditorWidgetFocusTracker extends Disposable {
|
||||
@@ -493,14 +453,14 @@ class CodeEditorWidgetFocusTracker extends Disposable {
|
||||
this._hasFocus = false;
|
||||
this._domFocusTracker = this._register(dom.trackFocus(domElement));
|
||||
|
||||
this._domFocusTracker.addFocusListener(() => {
|
||||
this._register(this._domFocusTracker.onDidFocus(() => {
|
||||
this._hasFocus = true;
|
||||
this._onChange.fire(void 0);
|
||||
});
|
||||
this._domFocusTracker.addBlurListener(() => {
|
||||
}));
|
||||
this._register(this._domFocusTracker.onDidBlur(() => {
|
||||
this._hasFocus = false;
|
||||
this._onChange.fire(void 0);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public hasFocus(): boolean {
|
||||
@@ -508,7 +468,7 @@ class CodeEditorWidgetFocusTracker extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' height='3' width='6'><g fill='`);
|
||||
const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' enable-background='new 0 0 6 3' height='3' width='6'><g fill='`);
|
||||
const squigglyEnd = encodeURIComponent(`'><polygon points='5.5,0 2.5,3 1.1,3 4.1,0'/><polygon points='4,0 6,2 6,0.6 5.4,0'/><polygon points='0,2 1,3 2.4,3 0,0.6'/></g></svg>`);
|
||||
|
||||
function getSquigglySVGData(color: Color) {
|
||||
@@ -518,28 +478,28 @@ function getSquigglySVGData(color: Color) {
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
let errorBorderColor = theme.getColor(editorErrorBorder);
|
||||
if (errorBorderColor) {
|
||||
collector.addRule(`.monaco-editor .errorsquiggly { border-bottom: 4px double ${errorBorderColor}; }`);
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { border-bottom: 4px double ${errorBorderColor}; }`);
|
||||
}
|
||||
let errorForeground = theme.getColor(editorErrorForeground);
|
||||
if (errorForeground) {
|
||||
collector.addRule(`.monaco-editor .errorsquiggly { background: url("data:image/svg+xml,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);
|
||||
}
|
||||
|
||||
let warningBorderColor = theme.getColor(editorWarningBorder);
|
||||
if (warningBorderColor) {
|
||||
collector.addRule(`.monaco-editor .warningsquiggly { border-bottom: 4px double ${warningBorderColor}; }`);
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { border-bottom: 4px double ${warningBorderColor}; }`);
|
||||
}
|
||||
let warningForeground = theme.getColor(editorWarningForeground);
|
||||
if (warningForeground) {
|
||||
collector.addRule(`.monaco-editor .warningsquiggly { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);
|
||||
}
|
||||
|
||||
let infoBorderColor = theme.getColor(editorInfoBorder);
|
||||
if (warningBorderColor) {
|
||||
collector.addRule(`.monaco-editor .infosquiggly { border-bottom: 4px double ${infoBorderColor}; }`);
|
||||
if (infoBorderColor) {
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { border-bottom: 4px double ${infoBorderColor}; }`);
|
||||
}
|
||||
let infoForeground = theme.getColor(editorInfoForeground);
|
||||
if (warningForeground) {
|
||||
collector.addRule(`.monaco-editor .infosquiggly { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);
|
||||
if (infoForeground) {
|
||||
collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml;utf8,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { ISashEvent, IVerticalSashLayoutProvider, Sash } from 'vs/base/browser/ui/sash/sash';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
||||
@@ -28,7 +28,7 @@ import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
|
||||
import { Configuration } from 'vs/editor/browser/config/configuration';
|
||||
import { Position, IPosition } from 'vs/editor/common/core/position';
|
||||
import { Selection, ISelection } from 'vs/editor/common/core/selection';
|
||||
import { InlineDecoration } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ColorId, MetadataConsts, FontStyle } from 'vs/editor/common/modes';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
@@ -137,9 +137,9 @@ let DIFF_EDITOR_ID = 0;
|
||||
|
||||
export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffEditor {
|
||||
|
||||
private static ONE_OVERVIEW_WIDTH = 15;
|
||||
public static ENTIRE_DIFF_OVERVIEW_WIDTH = 30;
|
||||
private static UPDATE_DIFF_DECORATIONS_DELAY = 200; // ms
|
||||
private static readonly ONE_OVERVIEW_WIDTH = 15;
|
||||
public static readonly ENTIRE_DIFF_OVERVIEW_WIDTH = 30;
|
||||
private static readonly UPDATE_DIFF_DECORATIONS_DELAY = 200; // ms
|
||||
|
||||
private readonly _onDidDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
@@ -462,10 +462,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
return instantiationService.createInstance(CodeEditor, container, options);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._codeEditorService.removeDiffEditor(this);
|
||||
|
||||
@@ -567,10 +563,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
}
|
||||
|
||||
public getValue(options: { preserveBOM: boolean; lineEnding: string; } = null): string {
|
||||
return this.modifiedEditor.getValue(options);
|
||||
}
|
||||
|
||||
public getModel(): editorCommon.IDiffEditorModel {
|
||||
return {
|
||||
original: this.originalEditor.getModel(),
|
||||
@@ -701,18 +693,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this.modifiedEditor.revealRangeAtTop(range, scrollType);
|
||||
}
|
||||
|
||||
public getActions(): editorCommon.IEditorAction[] {
|
||||
return this.modifiedEditor.getActions();
|
||||
}
|
||||
|
||||
public getSupportedActions(): editorCommon.IEditorAction[] {
|
||||
return this.modifiedEditor.getSupportedActions();
|
||||
}
|
||||
|
||||
public getAction(id: string): editorCommon.IEditorAction {
|
||||
return this.modifiedEditor.getAction(id);
|
||||
}
|
||||
|
||||
public saveViewState(): editorCommon.IDiffEditorViewState {
|
||||
let originalViewState = this.originalEditor.saveViewState();
|
||||
let modifiedViewState = this.modifiedEditor.saveViewState();
|
||||
@@ -919,7 +903,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
private _adjustOptionsForSubEditor(options: editorOptions.IDiffEditorOptions): editorOptions.IDiffEditorOptions {
|
||||
let clonedOptions: editorOptions.IDiffEditorOptions = objects.clone(options || {});
|
||||
let clonedOptions: editorOptions.IDiffEditorOptions = objects.deepClone(options || {});
|
||||
clonedOptions.inDiffEditor = true;
|
||||
clonedOptions.wordWrap = 'off';
|
||||
clonedOptions.wordWrapMinified = false;
|
||||
@@ -1131,7 +1115,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
return originalEquivalentLineNumber + lineChangeOriginalLength - lineChangeModifiedLength + delta;
|
||||
}
|
||||
|
||||
public getDiffLineInformationForOriginal(lineNumber: number): editorCommon.IDiffLineInformation {
|
||||
public getDiffLineInformationForOriginal(lineNumber: number): editorBrowser.IDiffLineInformation {
|
||||
if (!this._lineChanges) {
|
||||
// Cannot answer that which I don't know
|
||||
return null;
|
||||
@@ -1141,7 +1125,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
};
|
||||
}
|
||||
|
||||
public getDiffLineInformationForModified(lineNumber: number): editorCommon.IDiffLineInformation {
|
||||
public getDiffLineInformationForModified(lineNumber: number): editorBrowser.IDiffLineInformation {
|
||||
if (!this._lineChanges) {
|
||||
// Cannot answer that which I don't know
|
||||
return null;
|
||||
@@ -1516,10 +1500,10 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
|
||||
this._sash.disable();
|
||||
}
|
||||
|
||||
this._sash.addListener('start', () => this.onSashDragStart());
|
||||
this._sash.addListener('change', (e: ISashEvent) => this.onSashDrag(e));
|
||||
this._sash.addListener('end', () => this.onSashDragEnd());
|
||||
this._sash.addListener('reset', () => this.onSashReset());
|
||||
this._sash.onDidStart(() => this.onSashDragStart());
|
||||
this._sash.onDidChange((e: ISashEvent) => this.onSashDrag(e));
|
||||
this._sash.onDidEnd(() => this.onSashDragEnd());
|
||||
this._sash.onDidReset(() => this.onSashReset());
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -1938,7 +1922,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
|
||||
decorations.push(new InlineDecoration(
|
||||
new Range(charChange.originalStartLineNumber, charChange.originalStartColumn, charChange.originalEndLineNumber, charChange.originalEndColumn),
|
||||
'char-delete',
|
||||
false
|
||||
InlineDecorationType.Regular
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -2056,4 +2040,4 @@ registerThemingParticipant((theme, collector) => {
|
||||
if (shadow) {
|
||||
collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'vs/base/common/assert';
|
||||
import { EventEmitter } from 'vs/base/common/eventEmitter';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ICommonDiffEditor, ILineChange, ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { ILineChange, ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
|
||||
interface IDiffRange {
|
||||
rhs: boolean;
|
||||
@@ -32,73 +34,69 @@ var defaultOptions: Options = {
|
||||
/**
|
||||
* Create a new diff navigator for the provided diff editor.
|
||||
*/
|
||||
export class DiffNavigator extends EventEmitter {
|
||||
export class DiffNavigator {
|
||||
|
||||
public static Events = {
|
||||
UPDATED: 'navigation.updated'
|
||||
};
|
||||
private readonly _editor: IDiffEditor;
|
||||
private readonly _options: Options;
|
||||
private readonly _disposables: IDisposable[];
|
||||
private readonly _onDidUpdate = new Emitter<this>();
|
||||
|
||||
readonly onDidUpdate: Event<this> = this._onDidUpdate.event;
|
||||
|
||||
private editor: ICommonDiffEditor;
|
||||
private options: Options;
|
||||
private disposed: boolean;
|
||||
private toUnbind: IDisposable[];
|
||||
|
||||
private revealFirst: boolean;
|
||||
private nextIdx: number;
|
||||
private ranges: IDiffRange[];
|
||||
private ignoreSelectionChange: boolean;
|
||||
public revealFirst: boolean;
|
||||
|
||||
constructor(editor: ICommonDiffEditor, options: Options = {}) {
|
||||
super([
|
||||
DiffNavigator.Events.UPDATED
|
||||
]);
|
||||
this.editor = editor;
|
||||
this.options = objects.mixin(options, defaultOptions, false);
|
||||
constructor(editor: IDiffEditor, options: Options = {}) {
|
||||
this._editor = editor;
|
||||
this._options = objects.mixin(options, defaultOptions, false);
|
||||
|
||||
this.disposed = false;
|
||||
this.toUnbind = [];
|
||||
this._disposables = [];
|
||||
|
||||
this.nextIdx = -1;
|
||||
this.ranges = [];
|
||||
this.ignoreSelectionChange = false;
|
||||
this.revealFirst = this.options.alwaysRevealFirst;
|
||||
this.revealFirst = this._options.alwaysRevealFirst;
|
||||
|
||||
// hook up to diff editor for diff, disposal, and caret move
|
||||
this.toUnbind.push(this.editor.onDidDispose(() => this.dispose()));
|
||||
this.toUnbind.push(this.editor.onDidUpdateDiff(() => this.onDiffUpdated()));
|
||||
this._disposables.push(this._editor.onDidDispose(() => this.dispose()));
|
||||
this._disposables.push(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));
|
||||
|
||||
if (this.options.followsCaret) {
|
||||
this.toUnbind.push(this.editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
|
||||
if (this._options.followsCaret) {
|
||||
this._disposables.push(this._editor.getModifiedEditor().onDidChangeCursorPosition((e: ICursorPositionChangedEvent) => {
|
||||
if (this.ignoreSelectionChange) {
|
||||
return;
|
||||
}
|
||||
this.nextIdx = -1;
|
||||
}));
|
||||
}
|
||||
if (this.options.alwaysRevealFirst) {
|
||||
this.toUnbind.push(this.editor.getModifiedEditor().onDidChangeModel((e) => {
|
||||
if (this._options.alwaysRevealFirst) {
|
||||
this._disposables.push(this._editor.getModifiedEditor().onDidChangeModel((e) => {
|
||||
this.revealFirst = true;
|
||||
}));
|
||||
}
|
||||
|
||||
// init things
|
||||
this.init();
|
||||
this._init();
|
||||
}
|
||||
|
||||
private init(): void {
|
||||
var changes = this.editor.getLineChanges();
|
||||
private _init(): void {
|
||||
var changes = this._editor.getLineChanges();
|
||||
if (!changes) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private onDiffUpdated(): void {
|
||||
this.init();
|
||||
private _onDiffUpdated(): void {
|
||||
this._init();
|
||||
|
||||
this.compute(this.editor.getLineChanges());
|
||||
this._compute(this._editor.getLineChanges());
|
||||
if (this.revealFirst) {
|
||||
// Only reveal first on first non-null changes
|
||||
if (this.editor.getLineChanges() !== null) {
|
||||
if (this._editor.getLineChanges() !== null) {
|
||||
this.revealFirst = false;
|
||||
this.nextIdx = -1;
|
||||
this.next();
|
||||
@@ -106,7 +104,7 @@ export class DiffNavigator extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private compute(lineChanges: ILineChange[]): void {
|
||||
private _compute(lineChanges: ILineChange[]): void {
|
||||
|
||||
// new ranges
|
||||
this.ranges = [];
|
||||
@@ -115,7 +113,7 @@ export class DiffNavigator extends EventEmitter {
|
||||
// create ranges from changes
|
||||
lineChanges.forEach((lineChange) => {
|
||||
|
||||
if (!this.options.ignoreCharChanges && lineChange.charChanges) {
|
||||
if (!this._options.ignoreCharChanges && lineChange.charChanges) {
|
||||
|
||||
lineChange.charChanges.forEach((charChange) => {
|
||||
this.ranges.push({
|
||||
@@ -147,13 +145,12 @@ export class DiffNavigator extends EventEmitter {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
this.emit(DiffNavigator.Events.UPDATED, {});
|
||||
this._onDidUpdate.fire(this);
|
||||
}
|
||||
|
||||
private initIdx(fwd: boolean): void {
|
||||
private _initIdx(fwd: boolean): void {
|
||||
var found = false;
|
||||
var position = this.editor.getPosition();
|
||||
var position = this._editor.getPosition();
|
||||
for (var i = 0, len = this.ranges.length; i < len && !found; i++) {
|
||||
var range = this.ranges[i].range;
|
||||
if (position.isBeforeOrEqual(range.getStartPosition())) {
|
||||
@@ -170,7 +167,7 @@ export class DiffNavigator extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private move(fwd: boolean): void {
|
||||
private _move(fwd: boolean): void {
|
||||
assert.ok(!this.disposed, 'Illegal State - diff navigator has been disposed');
|
||||
|
||||
if (!this.canNavigate()) {
|
||||
@@ -178,7 +175,7 @@ export class DiffNavigator extends EventEmitter {
|
||||
}
|
||||
|
||||
if (this.nextIdx === -1) {
|
||||
this.initIdx(fwd);
|
||||
this._initIdx(fwd);
|
||||
|
||||
} else if (fwd) {
|
||||
this.nextIdx += 1;
|
||||
@@ -196,31 +193,30 @@ export class DiffNavigator extends EventEmitter {
|
||||
this.ignoreSelectionChange = true;
|
||||
try {
|
||||
var pos = info.range.getStartPosition();
|
||||
this.editor.setPosition(pos);
|
||||
this.editor.revealPositionInCenter(pos, ScrollType.Smooth);
|
||||
this._editor.setPosition(pos);
|
||||
this._editor.revealPositionInCenter(pos, ScrollType.Smooth);
|
||||
} finally {
|
||||
this.ignoreSelectionChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
public canNavigate(): boolean {
|
||||
canNavigate(): boolean {
|
||||
return this.ranges && this.ranges.length > 0;
|
||||
}
|
||||
|
||||
public next(): void {
|
||||
this.move(true);
|
||||
next(): void {
|
||||
this._move(true);
|
||||
}
|
||||
|
||||
public previous(): void {
|
||||
this.move(false);
|
||||
previous(): void {
|
||||
this._move(false);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.toUnbind = dispose(this.toUnbind);
|
||||
dispose(): void {
|
||||
dispose(this._disposables);
|
||||
this._disposables.length = 0;
|
||||
this._onDidUpdate.dispose();
|
||||
this.ranges = null;
|
||||
this.disposed = true;
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { editorAction, EditorAction, ServicesAccessor } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { registerEditorAction, EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
const DIFF_LINES_PADDING = 3;
|
||||
|
||||
@@ -763,7 +764,6 @@ registerThemingParticipant((theme, collector) => {
|
||||
}
|
||||
});
|
||||
|
||||
@editorAction
|
||||
class DiffReviewNext extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
@@ -778,7 +778,7 @@ class DiffReviewNext extends EditorAction {
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
const diffEditor = findFocusedDiffEditor(accessor);
|
||||
if (diffEditor) {
|
||||
diffEditor.diffReviewNext();
|
||||
@@ -786,7 +786,6 @@ class DiffReviewNext extends EditorAction {
|
||||
}
|
||||
}
|
||||
|
||||
@editorAction
|
||||
class DiffReviewPrev extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
@@ -801,7 +800,7 @@ class DiffReviewPrev extends EditorAction {
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: editorCommon.ICommonCodeEditor): void {
|
||||
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
|
||||
const diffEditor = findFocusedDiffEditor(accessor);
|
||||
if (diffEditor) {
|
||||
diffEditor.diffReviewPrev();
|
||||
@@ -820,3 +819,6 @@ function findFocusedDiffEditor(accessor: ServicesAccessor): DiffEditorWidget {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
registerEditorAction(DiffReviewNext);
|
||||
registerEditorAction(DiffReviewPrev);
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { CodeEditor } from 'vs/editor/browser/codeEditor';
|
||||
import { IConfigurationChangedEvent, IEditorOptions, IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -98,4 +98,4 @@ export class EmbeddedDiffEditorWidget extends DiffEditorWidget {
|
||||
objects.mixin(this._overwriteOptions, newOptions, true);
|
||||
super.updateOptions(this._overwriteOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user