Merge VS Code 1.26.1 (#2394)

* Squash merge commits for 1.26 (#1) (#2323)

* Polish tag search as per feedback (#55269)

* Polish tag search as per feedback

* Updated regex

* Allow users to opt-out of features that send online requests in the background (#55097)

* settings sweep #54690

* Minor css tweaks to enable eoverflow elipsis in more places (#55277)

* fix an issue with titlebarheight when not scaling with zoom

* Settings descriptions update #54690

* fixes #55209

* Settings editor - many padding fixes

* More space above level 2 label

* Fixing Cannot debug npm script using Yarn #55103

* Settings editor - show ellipsis when description overflows

* Settings editor - ... fix measuring around links, relayout

* Setting descriptions

* Settings editor - fix ... for some short lines, fix select container width

* Settings editor - overlay trees so scrollable shadow is full width

* Fix #54133 - missing extension settings after reload

* Settings color token description tweak

* Settings editor - disable overflow indicator temporarily, needs to be faster

* Added command to Run the selected npm script

* fixes #54452

* fixes #54929

* fixes #55248

* prefix command with extension name

* Contribute run selected to the context menu

* node-debug@1.26.6

* Allow terminal rendererType to be swapped out at runtime

Part of #53274
Fixes #55344

* Settings editor - fix not focusing search when restoring editor
setInput must be actually async. Will be fixed naturally when we aren't using winJS promises...

* Settings editor - TOC should only expand the section with a selected item

* Bump node-debug2

* Settings editor - Tree focus outlines

* Settings editor - don't blink the scrollbar when toc selection changes
And hide TOC correctly when the editor is narrow

* Settings editor - header rows should not be selectable

* fixes #54877

* change debug assignee to isi

* Settings sweep (#54690)

* workaround for #55051

* Settings sweep (#54690)

* settings sweep

#54690

* Don't try closing tags when you type > after another >

* Describe what implementation code lens does

Fixes #55370

* fix javadoc formatter setting description

* fixes #55325

* update to officical TS version

* Settings editor - Even more padding, use semibold instead of bold

* Fix #55357 - fix TOC twistie

* fixes #55288

* explorer: refresh on di change file system provider registration

fixes #53256

* Disable push to Linux repo to test standalone publisher

* New env var to notify log level to extensions #54001

* Disable snippets in extension search (when not in suggest dropdown) (#55281)

* Disable snippits in extension search (when not in suggest dropdown)

* Add monaco input contributions

* Fix bug preventing snippetSuggestions from taking effect in sub-editors

* Latest emmet helper to fix #52366

* Fix comment updates for threads within same file

* Allow extensions to log telemetry to log files #54001

* Pull latest css grammar

* files.exclude control - use same style for "add" vs "edit"

* files.exclude control - focus/keyboard behavior

* don't show menubar too early

* files.exclude - better styling

* Place cursor at end of extensions search box on autofill (#55254)

* Place cursor at end of extensions search box on autofill

* Use position instead of selection

* fix linux build issue (empty if block)

* Settings editor - fix extension category prefixes

* Settings editor - add simple ellipsis for first line that overflows, doesn't cover case when first line does not overflow but there is more text, TODO

* File/Text search provider docs

* Fixes #52655

* Include epoch (#55008)

* Fixes #53385

* Fixes #49480

*  VS Code Insiders (Users) not opening Fixes #55353

* Better handling of the case when the extension host fails to start

* Fixes #53966

*  Remove confusing Start from wordPartLeft commands ID

* vscode-xterm@3.6.0-beta12

Fixes #55488

* Initial size is set to infinity!! Fixes #55461

* Polish embeddedEditorBackground

* configuration service misses event

* Fix #55224 - fix duplicate results in multiroot workspace from splitting the diskseach query

* Select all not working in issue reporter on mac, fixes #55424

* Disable fuzzy matching for extensions autosuggest (#55498)

* Fix clipping of extensions search border in some third party themes (#55504)

* fixes #55538

* Fix bug causing an aria alert to not be shown the third time
 (and odd numbers thereafter)

* Settings editor - work around rendering glitch with webkit-line-clamp

* Settings editor - revert earlier '...' changes

* Settings editor - move enumDescription to its own div, because it disturbs -webkit-line-clamp for some reason

* Settings editor - better overflow indicator

* Don't show existing filters in autocomplete (#55495)

* Dont show existing filters in autocomplete

* Simplify

* Settings Editor: Add aria labels for input elements Fixes: #54836 (#55543)

* fixes #55223

* Update vscode-css-languageservice to 3.0.10-next.1

* Fix #55509 - settings navigation

* Fix #55519

* Fix #55520

* FIx #55524

* Fix #55556 - include wordSeparators in all search queries, so findTextInFiles can respect isWordMatch correctly

* oss updates for endgame

* Fix unit tests

* fixes #55522

* Avoid missing manifest error from bubbling up #54757

* Settings format crawl

* Search provider - Fix FileSearchProvider to return array, not progress

* Fix #55598

* Settings editor - fix NPE rendering settings with no description

* dont render inden guides in search box (#55600)

* fixes #55454

* More settings crawl

* Another change for #55598 - maxResults applies to FileSearch and TextSearch but not FileIndex

* Fix FileSearchProvider unit tests for progress change

* fixes #55561

* Settings description update for #54690

* Update setting descriptions for online services

* Minor edits

* fixes #55513

* fixes #55451

* Fix #55612 - fix findTextInFiles cancellation

* fixes #55539

* More setting description tweaks

* Setting to disable online experiments #54354

* fixes #55507

* fixes #55515

* Show online services action only in Insiders for now

* Settings editor - change toc behavior default to 'filter'

* Settings editor - nicer filter count style during search

* Fix #55617 - search viewlet icons

* Settings editor - better styling for element count indicator

* SearchProvider - fix NPE when searching extraFileResources

* Allow extends to work without json suffix

Fixes #16905

* Remove accessability options logic entirely

Follow up on #55451

* use latest version of DAP

* fixes #55490

* fixes #55122

* fixes #52332

* Avoid assumptions about git: URIs (fixes #36236)

* relative path for descriptions

* resourece: get rid of isFile context key

fixes #48275

* Register previous ids for compatibility (#53497)

* more tuning for #48275

* no need to always re-read "files explorer"

fixes #52003

* read out active composites properly

fixes #51967

* Update link colors for hc theme to meet color contrast ratio, fixes #55651

Also updated link color for `textLinkActiveForeground` to be the same as `textLinkForeground` as it wasn't properly updated

* detect 'winpty-agent.exe'; fixes #55672

* node-debug@1.26.7

* reset counter on new label

* Settings editor - fix multiple setting links in one description

* Settings editor - color code blocks in setting descriptions, fix #55532

* Settings editor - hover color in TOC

* Settings editor - fix navigation NPE

* Settings editor - fix text control width

* Settings editor - maybe fix #55684

* Fix bug causing cursor to not move on paste

* fixes #53582

* Use ctrlCmd instead of ctrl for go down from search box

* fixes #55264

* fixes #55456

* filter for spcaes before triggering search (#55611)

* Fix #55698 - don't lose filtered TOC counts when refreshing TOC

* fixes #55421

* fixes #28979

* fixes #55576

* only add check for updates to windows/linux help

* readonly files: append decoration to label

fixes #53022

* debug: do not show toolbar while initialising

fixes #55026

* Opening launch.json should not activate debug extensions

fixes #55029

* fixes #55435

* fixes #55434

* fixes #55439

* trigger menu only on altkey up

* Fix #50555 - fix settings editor memory leak

* Fix #55712 - no need to focus 'a' anymore when restoring control focus after tree render

* fixes #55335

* proper fix for readonly model

fixes #53022

* improve FoldingRangeKind spec (for #55686)

* Use class with static fields (fixes #55494)

* Fixes #53671

* fixes #54630

* [html] should disable ionic suggestions by default. Currently forces deprecated Ionic v1 suggestions in .html files while typing. Fixes #53324

* cleanup deps

* debug issues back to andre

* update electron for smoketest

* Fix #55757 - prevent settings tabs from overflowing

* Fix #53897 - revert setting menu defaults to old editor

* Add enum descriptions to `typescript.preferences.importModuleSpecifier`

* Fix #55767 - leaking style elements from settings editor

* Fix #55521 - prevent flashing when clicking in exclude control

* Update Git modified color for contrast ratio, fixes #53140

* Revert "Merge branch 'master' of github.com:Microsoft/vscode"

This reverts commit bf46b6bfbae0cab99c2863e1244a916181fa9fbc, reversing
changes made to e275a424483dfb4ed33b428c97d5e2c441d6b917.

* Revert "Revert "Merge branch 'master' of github.com:Microsoft/vscode""

This reverts commit 53949d963f39e40757557c6526332354a31d9154.

* don't ask to install an incomplete menu

* Fix NPE in terminal AccessibilityManager

Fixes #55744

* don't display fallback menu unless we've closed the last window

* fixes #55547

* Fix smoke tests for extension search box

* Update OSSREADME.json for Electron 2.0.5

* Update distro

Includes Chromium license changes

* fix #55455

* fix #55865

* fixes #55893

* Fix bug causing workspace recommendations to go away upon ignoring a recommendation (#55805)

* Fix bug causing workspace recommendations to go away upon ignoring a recommendation

* ONly show on @recommended or @recommended:workspace

* Make more consistant

* Fix #55911

* Understand json activity (#55926)

* Understand json file activity

* Refactoring

* adding composer.json

* Distro update for experiments

* use terminal.processId for auto-attach; fixes #55918

* Reject invalid URI with vscode.openFolder (for #55891)

* improve win32 setup system vs user detection

fixes #55840

fixes #55840

delay winreg import

related to #55840

show notification earlier

related to #55840

fix #55840

update inno setup message

related to #55840

* Fix #55593 - this code only operates on local paths, so use fsPath and Uri.file instead

* Bring back the old menu due to electron 2.0 issues (#55913)

* add the old menu back for native menus

* make menu labels match

* `vscode.openFolder`: treat missing URI schema gracefully (for #55891)

* delay EH reattach; fixes #55955

* Mark all json files under appSettingsHome as settings

* Use localized strings for telemetry opt-out

* Exception when saving file editor opened from remote file provider (fixes #55051)

* Remove terminal menu from stable

Fixes 56003

* VSCode Insiders crashes on open with TypeError: Cannot read property 'lastIndexOf' of undefined. Fixes #54933

* improve fix for #55891

* fix #55916

* Improve #55891

* increase EH debugging restart delay; fixes #55955

* Revert "Don't include non-resource entries in history quick pick"

This reverts commit 37209a838e9f7e9abe6dc53ed73cdf1e03b72060.

* Diff editor: horizontal scrollbar height is smaller (fixes #56062)

* improve openFolder uri fix (correctly treat backslashes)

* fixes #56116
repair ipc for native menubar keybindings

* Fix #56240 - Open the JSON settings editor instead of the UI editor

* Fix #55536

* uriDisplay: if no formatter is registered fall back to getPathlabel

fixes #56104

* VSCode hangs when opening python file. Fixes #56377

* VS Code Hangs When Opening Specific PowerShell File. Fixes #56430

* Fix #56433 - search extraFileResources even when no folders open

* Workaround #55649

* Fix in master #56371

* Fix tests #56371

* Fix in master #56317

* increase version to 1.26.1

* Fixes #56387: Handle SIGPIPE in extension host

* fixes #56185

* Fix merge issues (part 1)

* Fix build breaks (part 1)

* Build breaks (part 2)

* Build breaks (part 3)

* More build breaks (part 4)

* Fix build breaks (part 5)

* WIP

* Fix menus

* Render query result and message panels (#2363)

* Put back query editor hot exit changes

* Fix grid changes that broke profiler (#2365)

* Update APIs for saving query editor state

* Fix restore view state for profiler and edit data

* Updating custom default themes to support 4.5:1 contrast ratio

* Test updates

* Fix Extension Manager and Windows Setup

* Update license headers

* Add appveyor and travis files back

* Fix hidden modal dropdown issue
This commit is contained in:
Karl Burtram
2018-09-04 14:55:00 -07:00
committed by GitHub
parent 3763278366
commit 81329fa7fa
2638 changed files with 118456 additions and 64012 deletions

View File

@@ -1,39 +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 { 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/browser/services/codeEditorService';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
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';
import { INotificationService } from 'vs/platform/notification/common/notification';
export class CodeEditor extends CodeEditorWidget {
constructor(
domElement: HTMLElement,
options: IEditorOptions,
@IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@ICommandService commandService: ICommandService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService
) {
super(domElement, options, false, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService);
}
protected _getContributions(): IEditorContributionCtor[] {
return EditorExtensionsRegistry.getEditorContributions();
}
protected _getActions(): EditorAction[] {
return EditorExtensionsRegistry.getEditorActions();
}
}

View File

@@ -5,6 +5,7 @@
'use strict';
import * as nls from 'vs/nls';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
@@ -16,19 +17,19 @@ import { registerEditorCommand, ICommandOptions, EditorCommand, Command } from '
import { IColumnSelectResult, ColumnSelection } from 'vs/editor/common/controller/cursorColumnSelection';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import H = editorCommon.Handler;
import { ICodeEditorService, getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import * as types from 'vs/base/common/types';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { IEditorService } from 'vs/platform/editor/common/editor';
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { MenuId } from 'vs/platform/actions/common/actions';
const CORE_WEIGHT = KeybindingsRegistry.WEIGHT.editorCore();
const CORE_WEIGHT = KeybindingWeight.EditorCore;
export abstract class CoreEditorCommand extends EditorCommand {
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
@@ -704,10 +705,6 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly) {
return;
}
let newState: CursorState;
if (args.wholeLine) {
newState = CursorMoveCommands.line(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition);
@@ -769,10 +766,6 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly) {
return;
}
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
@@ -1251,9 +1244,6 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly) {
return;
}
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
@@ -1312,12 +1302,6 @@ export namespace CoreNavigationCommands {
}
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
if (context.config.readOnly) {
return;
}
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
@@ -1637,14 +1621,8 @@ function findFocusedEditor(accessor: ServicesAccessor): ICodeEditor {
return accessor.get(ICodeEditorService).getFocusedCodeEditor();
}
function getWorkbenchActiveEditor(accessor: ServicesAccessor): ICodeEditor {
const editorService = accessor.get(IEditorService);
let activeEditor = (<any>editorService).getActiveEditor && (<any>editorService).getActiveEditor();
return getCodeEditor(activeEditor);
}
function registerCommand(command: Command) {
KeybindingsRegistry.registerCommandAndKeybindingRule(command.toCommandAndKeybindingRule(CORE_WEIGHT));
command.register();
}
/**
@@ -1668,7 +1646,7 @@ class EditorOrNativeTextInputCommand extends Command {
let focusedEditor = findFocusedEditor(accessor);
// Only if editor text focus (i.e. not if editor has widget focus).
if (focusedEditor && focusedEditor.isFocused()) {
if (focusedEditor && focusedEditor.hasTextFocus()) {
return this._runEditorHandler(focusedEditor, args);
}
@@ -1679,8 +1657,8 @@ class EditorOrNativeTextInputCommand extends Command {
return;
}
// Redirecting to last active editor
let activeEditor = getWorkbenchActiveEditor(accessor);
// Redirecting to active editor
let activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
if (activeEditor) {
activeEditor.focus();
return this._runEditorHandler(activeEditor, args);
@@ -1728,11 +1706,17 @@ registerCommand(new EditorOrNativeTextInputCommand({
editorHandler: CoreNavigationCommands.SelectAll,
inputHandler: 'selectAll',
id: 'editor.action.selectAll',
precondition: null,
precondition: EditorContextKeys.textInputFocus,
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: null,
primary: KeyMod.CtrlCmd | KeyCode.KEY_A
},
menubarOpts: {
menuId: MenuId.MenubarSelectionMenu,
group: '1_basic',
title: nls.localize({ key: 'miSelectAll', comment: ['&& denotes a mnemonic'] }, "&&Select All"),
order: 1
}
}));
@@ -1745,6 +1729,12 @@ registerCommand(new EditorOrNativeTextInputCommand({
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyMod.CtrlCmd | KeyCode.KEY_Z
},
menubarOpts: {
menuId: MenuId.MenubarEditMenu,
group: '1_do',
title: nls.localize({ key: 'miUndo', comment: ['&& denotes a mnemonic'] }, "&&Undo"),
order: 1
}
}));
registerCommand(new EditorHandlerCommand('default:' + H.Undo, H.Undo));
@@ -1760,6 +1750,12 @@ registerCommand(new EditorOrNativeTextInputCommand({
primary: KeyMod.CtrlCmd | KeyCode.KEY_Y,
secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z],
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z }
},
menubarOpts: {
menuId: MenuId.MenubarEditMenu,
group: '1_do',
title: nls.localize({ key: 'miRedo', comment: ['&& denotes a mnemonic'] }, "&&Redo"),
order: 2
}
}));
registerCommand(new EditorHandlerCommand('default:' + H.Redo, H.Redo));

View File

@@ -28,6 +28,7 @@ export interface IViewZoneData {
export interface IMarginData {
isAfterLines: boolean;
glyphMarginLeft: number;
glyphMarginWidth: number;
lineNumbersWidth: number;
offsetX: number;
@@ -602,6 +603,7 @@ export class MouseTargetFactory {
let offset = Math.abs(request.pos.x - request.editorPos.x);
const detail: IMarginData = {
isAfterLines: res.isAfterLines,
glyphMarginLeft: ctx.layoutInfo.glyphMarginLeft,
glyphMarginWidth: ctx.layoutInfo.glyphMarginWidth,
lineNumbersWidth: ctx.layoutInfo.lineNumbersWidth,
offsetX: offset

View File

@@ -126,7 +126,8 @@ export class TextAreaInput extends Disposable {
this._nextCommand = ReadFromTextArea.Type;
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keydown', (e: IKeyboardEvent) => {
if (this._isDoingComposition && e.keyCode === KeyCode.KEY_IN_COMPOSITION) {
if (this._isDoingComposition &&
(e.keyCode === KeyCode.KEY_IN_COMPOSITION || e.keyCode === KeyCode.Backspace)) {
// Stop propagation for keyDown events if the IME is processing key input
e.stopPropagation();
}
@@ -204,15 +205,6 @@ export class TextAreaInput extends Disposable {
this._register(dom.addDisposableListener(textArea.domNode, 'compositionupdate', (e: CompositionEvent) => {
this._lastTextAreaEvent = TextAreaInputEventType.compositionupdate;
if (browser.isChromev56) {
// See https://github.com/Microsoft/monaco-editor/issues/320
// where compositionupdate .data is broken in Chrome v55 and v56
// See https://bugs.chromium.org/p/chromium/issues/detail?id=677050#c9
// The textArea doesn't get the composition update yet, the value of textarea is still obsolete
// so we can't correct e at this moment.
return;
}
if (compositionDataInValid(e.locale)) {
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false);
this._textAreaState = newState;
@@ -265,17 +257,6 @@ export class TextAreaInput extends Disposable {
this._textArea.setIgnoreSelectionChangeTime('received input event');
if (this._isDoingComposition) {
// See https://github.com/Microsoft/monaco-editor/issues/320
if (browser.isChromev56) {
const [newState, typeInput] = deduceComposition(this._textArea.getValue());
this._textAreaState = newState;
this._onType.fire(typeInput);
let e: ICompositionData = {
data: typeInput.text
};
this._onCompositionUpdate.fire(e);
}
return;
}
@@ -286,7 +267,6 @@ export class TextAreaInput extends Disposable {
}
this._textAreaState = newState;
// console.log('==> DEDUCED INPUT: ' + JSON.stringify(typeInput));
if (this._nextCommand === ReadFromTextArea.Type) {
if (typeInput.text !== '') {
this._onType.fire(typeInput);
@@ -501,7 +481,7 @@ export class TextAreaInput extends Disposable {
}
let copyHTML: string = null;
if (!browser.isEdgeOrIE && (copyPlainText.length < 65536 || CopyOptions.forceCopyWithSyntaxHighlighting)) {
if (browser.hasClipboardSupport() && (copyPlainText.length < 65536 || CopyOptions.forceCopyWithSyntaxHighlighting)) {
copyHTML = this._host.getHTMLToCopy();
}
ClipboardEventUtils.setTextData(e, copyPlainText, copyHTML);

View File

@@ -121,7 +121,7 @@ export class TextAreaState {
// See https://github.com/Microsoft/vscode/issues/42251
// where typing always happens at offset 0 in the textarea
// when using a custom title area in OSX and moving the window
if (strings.endsWith(currentValue, previousValue)) {
if (!strings.startsWith(currentValue, previousValue) && strings.endsWith(currentValue, previousValue)) {
// Looks like something was typed at offset 0
// ==> pretend we placed the cursor at offset 0 to begin with...
previousSelectionStart = 0;

View File

@@ -53,6 +53,11 @@ export interface IViewZone {
* If neither `heightInPx` nor `heightInLines` is specified, a default of `heightInLines` = 1 will be chosen.
*/
heightInPx?: number;
/**
* The minimum width in px of the view zone.
* If this is set, the editor will ensure that the scroll width is >= than this value.
*/
minWidthInPx?: number;
/**
* The dom node of the view zone
*/
@@ -360,12 +365,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
onDidChangeModelDecorations(listener: (e: IModelDecorationsChangedEvent) => void): IDisposable;
/**
* An event emitted when the text inside this editor gained focus (i.e. cursor blinking).
* An event emitted when the text inside this editor gained focus (i.e. cursor starts blinking).
* @event
*/
onDidFocusEditorText(listener: () => void): IDisposable;
/**
* An event emitted when the text inside this editor lost focus.
* An event emitted when the text inside this editor lost focus (i.e. cursor stops blinking).
* @event
*/
onDidBlurEditorText(listener: () => void): IDisposable;
@@ -373,12 +378,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
* An event emitted when the text inside this editor or an editor widget gained focus.
* @event
*/
onDidFocusEditor(listener: () => void): IDisposable;
onDidFocusEditorWidget(listener: () => void): IDisposable;
/**
* An event emitted when the text inside this editor or an editor widget lost focus.
* @event
*/
onDidBlurEditor(listener: () => void): IDisposable;
onDidBlurEditorWidget(listener: () => void): IDisposable;
/**
* An event emitted before interpreting typed characters (on the keyboard).
* @event
@@ -472,7 +477,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
restoreViewState(state: editorCommon.ICodeEditorViewState): void;
/**
* Returns true if this editor or one of its widgets has keyboard focus.
* Returns true if the text inside this editor or an editor widget has focus.
*/
hasWidgetFocus(): boolean;
@@ -573,9 +578,9 @@ export interface ICodeEditor extends editorCommon.IEditor {
* 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.
* @param endCursorState Cursor state after the edits were applied.
*/
executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursoState?: Selection[]): boolean;
executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: Selection[]): boolean;
/**
* Execute multiple (concommitent) commands on the editor.
@@ -834,3 +839,18 @@ export function isDiffEditor(thing: any): thing is IDiffEditor {
return false;
}
}
/**
*@internal
*/
export function getCodeEditor(thing: any): ICodeEditor {
if (isCodeEditor(thing)) {
return thing;
}
if (isDiffEditor(thing)) {
return thing.getModifiedEditor();
}
return null;
}

View File

@@ -14,13 +14,11 @@ import { GlobalMouseMoveMonitor } from 'vs/base/browser/globalMouseMoveMonitor';
*/
export class PageCoordinates {
_pageCoordinatesBrand: void;
public readonly x: number;
public readonly y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
constructor(
public readonly x: number,
public readonly y: number
) { }
public toClientCoordinates(): ClientCoordinates {
return new ClientCoordinates(this.x - dom.StandardWindow.scrollX, this.y - dom.StandardWindow.scrollY);
@@ -37,13 +35,10 @@ export class PageCoordinates {
export class ClientCoordinates {
_clientCoordinatesBrand: void;
public readonly clientX: number;
public readonly clientY: number;
constructor(clientX: number, clientY: number) {
this.clientX = clientX;
this.clientY = clientY;
}
constructor(
public readonly clientX: number,
public readonly clientY: number
) { }
public toPageCoordinates(): PageCoordinates {
return new PageCoordinates(this.clientX + dom.StandardWindow.scrollX, this.clientY + dom.StandardWindow.scrollY);
@@ -56,17 +51,12 @@ export class ClientCoordinates {
export class EditorPagePosition {
_editorPagePositionBrand: void;
public readonly x: number;
public readonly y: number;
public readonly width: number;
public readonly height: number;
constructor(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
constructor(
public readonly x: number,
public readonly y: number,
public readonly width: number,
public readonly height: number
) { }
}
export function createEditorPagePosition(editorViewDomNode: HTMLElement): EditorPagePosition {

View File

@@ -9,18 +9,18 @@ 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 { KeybindingsRegistry, 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 { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService, getCodeEditor } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel } from 'vs/editor/common/model';
import { IPosition } from 'vs/base/browser/ui/contextview/contextview';
export type ServicesAccessor = ServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, editorCommon.IEditorContribution>;
@@ -29,53 +29,83 @@ export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, editor
export interface ICommandKeybindingsOptions extends IKeybindings {
kbExpr?: ContextKeyExpr;
weight?: number;
weight: number;
}
export interface ICommandMenubarOptions {
menuId: MenuId;
group: string;
order: number;
when?: ContextKeyExpr;
title: string;
}
export interface ICommandOptions {
id: string;
precondition: ContextKeyExpr;
kbOpts?: ICommandKeybindingsOptions;
description?: ICommandHandlerDescription;
menubarOpts?: ICommandMenubarOptions;
}
export abstract class Command {
public readonly id: string;
public readonly precondition: ContextKeyExpr;
private readonly _kbOpts: ICommandKeybindingsOptions;
private readonly _menubarOpts: ICommandMenubarOptions;
private readonly _description: ICommandHandlerDescription;
constructor(opts: ICommandOptions) {
this.id = opts.id;
this.precondition = opts.precondition;
this._kbOpts = opts.kbOpts;
this._menubarOpts = opts.menubarOpts;
this._description = opts.description;
}
public toCommandAndKeybindingRule(defaultWeight: number): ICommandAndKeybindingRule {
const kbOpts = this._kbOpts || { primary: 0 };
public register(): void {
let kbWhen = kbOpts.kbExpr;
if (this.precondition) {
if (kbWhen) {
kbWhen = ContextKeyExpr.and(kbWhen, this.precondition);
} else {
kbWhen = this.precondition;
}
if (this._menubarOpts) {
MenuRegistry.appendMenuItem(this._menubarOpts.menuId, {
group: this._menubarOpts.group,
command: {
id: this.id,
title: this._menubarOpts.title,
// precondition: this.precondition
},
when: this._menubarOpts.when,
order: this._menubarOpts.order
});
}
const weight = (typeof kbOpts.weight === 'number' ? kbOpts.weight : defaultWeight);
if (this._kbOpts) {
let kbWhen = this._kbOpts.kbExpr;
if (this.precondition) {
if (kbWhen) {
kbWhen = ContextKeyExpr.and(kbWhen, this.precondition);
} else {
kbWhen = this.precondition;
}
}
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
};
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: this._kbOpts.weight,
when: kbWhen,
primary: this._kbOpts.primary,
secondary: this._kbOpts.secondary,
win: this._kbOpts.win,
linux: this._kbOpts.linux,
mac: this._kbOpts.mac,
description: this._description
});
} else {
CommandsRegistry.registerCommand({
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
description: this._description
});
}
}
public abstract runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void>;
@@ -85,12 +115,6 @@ export abstract class 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;
}
@@ -124,14 +148,8 @@ export abstract class EditorCommand extends Command {
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);
}
// Find the editor with text focus or active
let editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
if (!editor) {
// well, at least we tried...
return;
@@ -156,8 +174,8 @@ export abstract class EditorCommand extends Command {
//#region EditorAction
export interface IEditorCommandMenuOptions {
group?: string;
order?: number;
group: string;
order: number;
when?: ContextKeyExpr;
}
export interface IActionOptions extends ICommandOptions {
@@ -178,20 +196,21 @@ export abstract class EditorAction extends EditorCommand {
this.menuOpts = opts.menuOpts;
}
public toMenuItem(): IMenuItem {
if (!this.menuOpts) {
return null;
public register(): void {
if (this.menuOpts) {
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
command: {
id: this.id,
title: this.label
},
when: ContextKeyExpr.and(this.precondition, this.menuOpts.when),
group: this.menuOpts.group,
order: this.menuOpts.order
});
}
return {
command: {
id: this.id,
title: this.label
},
when: ContextKeyExpr.and(this.precondition, this.menuOpts.when),
group: this.menuOpts.group,
order: this.menuOpts.order
};
super.register();
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void> {
@@ -223,8 +242,14 @@ export function registerLanguageCommand(id: string, handler: (accessor: Services
CommandsRegistry.registerCommand(id, (accessor, args) => handler(accessor, args || {}));
}
export function registerDefaultLanguageCommand(id: string, handler: (model: ITextModel, position: Position, args: { [n: string]: any }) => any) {
registerLanguageCommand(id, function (accessor, args) {
interface IDefaultArgs {
resource: URI;
position: IPosition;
[name: string]: any;
}
export function registerDefaultLanguageCommand(id: string, handler: (model: ITextModel, position: Position, args: IDefaultArgs) => any) {
registerLanguageCommand(id, function (accessor, args: IDefaultArgs) {
const { resource, position } = args;
if (!(resource instanceof URI)) {
@@ -301,14 +326,7 @@ class EditorContributionRegistry {
}
public registerEditorAction(action: EditorAction) {
let menuItem = action.toMenuItem();
if (menuItem) {
MenuRegistry.appendMenuItem(MenuId.EditorContext, menuItem);
}
KeybindingsRegistry.registerCommandAndKeybindingRule(action.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
action.register();
this.editorActions.push(action);
}
@@ -321,7 +339,7 @@ class EditorContributionRegistry {
}
public registerEditorCommand(editorCommand: EditorCommand) {
KeybindingsRegistry.registerCommandAndKeybindingRule(editorCommand.toCommandAndKeybindingRule(KeybindingsRegistry.WEIGHT.editorContrib()));
editorCommand.register();
this.editorCommands[editorCommand.id] = editorCommand;
}

View File

@@ -9,6 +9,8 @@ import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
export abstract class AbstractCodeEditorService implements ICodeEditorService {
@@ -84,7 +86,7 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
for (let i = 0; i < editors.length; i++) {
let editor = editors[i];
if (editor.isFocused()) {
if (editor.hasTextFocus()) {
// bingo!
return editor;
}
@@ -130,6 +132,9 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
_removeWatcher(w: ModelTransientSettingWatcher): void {
delete this._transientWatchers[w.uri];
}
abstract getActiveCodeEditor(): ICodeEditor;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
}
export class ModelTransientSettingWatcher {

View File

@@ -1,381 +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 * as nls from 'vs/nls';
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, FileChangeType } from 'vs/platform/files/common/files';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { IIdentifiedSingleEditOperation, ITextModel, EndOfLineSequence } from 'vs/editor/common/model';
import { IProgressRunner, emptyProgressRunner, IProgress } from 'vs/platform/progress/common/progress';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { ResourceTextEdit, ResourceFileEdit, isResourceFileEdit, isResourceTextEdit } from 'vs/editor/common/modes';
import { getPathLabel } from 'vs/base/common/labels';
abstract class IRecording {
static start(fileService: IFileService): IRecording {
const _changes = new Set<string>();
let stop: IDisposable;
if (fileService) {
// watch only when there is a fileservice available
stop = fileService.onFileChanges(event => {
for (const change of event.changes) {
if (change.type === FileChangeType.UPDATED) {
_changes.add(change.resource.toString());
}
}
});
}
return {
stop() { return dispose(stop); },
hasChanged(resource) { return _changes.has(resource.toString()); }
};
}
abstract stop(): void;
abstract hasChanged(resource: URI): boolean;
}
class EditTask implements IDisposable {
private _initialSelections: Selection[];
private _endCursorSelection: Selection;
private get _model(): ITextModel { 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 = [];
}
dispose() {
if (this._model) {
this._modelReference.dispose();
this._modelReference = null;
}
}
addEdit(resourceEdit: ResourceTextEdit): void {
for (const edit of resourceEdit.edits) {
if (typeof edit.eol === 'number') {
// honor eol-change
this._newEol = edit.eol;
}
if (edit.range || edit.text) {
// 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.text));
}
}
}
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];
}
getEndCursorSelection(): Selection {
return this._endCursorSelection;
}
}
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 _edits = new Map<string, ResourceTextEdit[]>();
private _tasks: EditTask[];
private _sourceModel: URI;
private _sourceSelections: Selection[];
private _sourceModelTask: SourceModelEditTask;
private _progress: IProgress<void>;
constructor(
textModelResolverService: ITextModelService,
editor: ICodeEditor,
edits: ResourceTextEdit[],
progress: IProgress<void>
) {
this._textModelResolverService = textModelResolverService;
this._sourceModel = editor ? editor.getModel().uri : undefined;
this._sourceSelections = editor ? editor.getSelections() : undefined;
this._sourceModelTask = undefined;
this._progress = progress;
edits.forEach(this.addEdit, this);
}
dispose(): void {
this._tasks = dispose(this._tasks);
}
addEdit(edit: ResourceTextEdit): void {
let array = this._edits.get(edit.resource.toString());
if (!array) {
array = [];
this._edits.set(edit.resource.toString(), array);
}
array.push(edit);
}
async prepare(): TPromise<BulkEditModel> {
if (this._tasks) {
throw new Error('illegal state - already prepared');
}
this._tasks = [];
const promises: TPromise<any>[] = [];
this._edits.forEach((value, key) => {
const promise = this._textModelResolverService.createModelReference(URI.parse(key)).then(ref => {
const model = ref.object;
if (!model || !model.textEditorModel) {
throw new Error(`Cannot load file ${key}`);
}
let task: EditTask;
if (this._sourceModel && model.textEditorModel.uri.toString() === this._sourceModel.toString()) {
this._sourceModelTask = new SourceModelEditTask(ref, this._sourceSelections);
task = this._sourceModelTask;
} else {
task = new EditTask(ref);
}
value.forEach(edit => task.addEdit(edit));
this._tasks.push(task);
this._progress.report(undefined);
});
promises.push(promise);
});
await TPromise.join(promises);
return this;
}
apply(): Selection {
for (const task of this._tasks) {
task.apply();
this._progress.report(undefined);
}
return this._sourceModelTask
? this._sourceModelTask.getEndCursorSelection()
: undefined;
}
}
export type Edit = ResourceFileEdit | ResourceTextEdit;
export class BulkEdit {
static perform(edits: Edit[], textModelService: ITextModelService, fileService: IFileService, editor: ICodeEditor): TPromise<any> {
const edit = new BulkEdit(editor, null, textModelService, fileService);
edit.add(edits);
return edit.perform();
}
private _edits: Edit[] = [];
private _editor: ICodeEditor;
private _progress: IProgressRunner;
constructor(
editor: ICodeEditor,
progress: IProgressRunner,
@ITextModelService private readonly _textModelService: ITextModelService,
@optional(IFileService) private _fileService: IFileService
) {
this._editor = editor;
this._progress = progress || emptyProgressRunner;
}
add(edits: Edit[] | Edit): void {
if (Array.isArray(edits)) {
this._edits.push(...edits);
} else {
this._edits.push(edits);
}
}
ariaMessage(): string {
const editCount = this._edits.reduce((prev, cur) => isResourceFileEdit(cur) ? prev : prev + cur.edits.length, 0);
const resourceCount = this._edits.length;
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);
}
}
async perform(): TPromise<Selection> {
let seen = new Set<string>();
let total = 0;
const groups: Edit[][] = [];
let group: Edit[];
for (const edit of this._edits) {
if (!group
|| (isResourceFileEdit(group[0]) && !isResourceFileEdit(edit))
|| (isResourceTextEdit(group[0]) && !isResourceTextEdit(edit))
) {
group = [];
groups.push(group);
}
group.push(edit);
if (isResourceFileEdit(edit)) {
total += 1;
} else if (!seen.has(edit.resource.toString())) {
seen.add(edit.resource.toString());
total += 2;
}
}
// define total work and progress callback
// for child operations
this._progress.total(total);
let progress: IProgress<void> = { report: _ => this._progress.worked(1) };
// do it. return the last selection computed
// by a text change (can be undefined then)
let res: Selection = undefined;
for (const group of groups) {
if (isResourceFileEdit(group[0])) {
await this._performFileEdits(<ResourceFileEdit[]>group, progress);
} else {
res = await this._performTextEdits(<ResourceTextEdit[]>group, progress) || res;
}
}
return res;
}
private async _performFileEdits(edits: ResourceFileEdit[], progress: IProgress<void>) {
for (const edit of edits) {
progress.report(undefined);
if (edit.newUri && edit.oldUri) {
await this._fileService.moveFile(edit.oldUri, edit.newUri, false);
} else if (!edit.newUri && edit.oldUri) {
await this._fileService.del(edit.oldUri, true);
} else if (edit.newUri && !edit.oldUri) {
await this._fileService.createFile(edit.newUri, undefined, { overwrite: false });
}
}
}
private async _performTextEdits(edits: ResourceTextEdit[], progress: IProgress<void>): TPromise<Selection> {
const recording = IRecording.start(this._fileService);
const model = new BulkEditModel(this._textModelService, this._editor, edits, progress);
await model.prepare();
const conflicts = edits
.filter(edit => recording.hasChanged(edit.resource))
.map(edit => getPathLabel(edit.resource));
recording.stop();
if (conflicts.length > 0) {
model.dispose();
throw new Error(nls.localize('conflict', "These files have changed in the meantime: {0}", conflicts.join(', ')));
}
const selection = await model.apply();
model.dispose();
return selection;
}
}

View File

@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* 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 { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { WorkspaceEdit } from 'vs/editor/common/modes';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from '../editorBrowser';
import { IProgressRunner } from 'vs/platform/progress/common/progress';
export const IBulkEditService = createDecorator<IBulkEditService>('IWorkspaceEditService');
export interface IBulkEditOptions {
editor?: ICodeEditor;
progress?: IProgressRunner;
}
export interface IBulkEditResult {
ariaSummary: string;
}
export interface IBulkEditService {
_serviceBrand: any;
apply(edit: WorkspaceEdit, options: IBulkEditOptions): TPromise<IBulkEditResult>;
}

View File

@@ -8,8 +8,9 @@ import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model';
import { IEditor } from 'vs/platform/editor/common/editor';
import { ICodeEditor, IDiffEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
export const ICodeEditorService = createDecorator<ICodeEditorService>('codeEditorService');
@@ -41,40 +42,7 @@ export interface ICodeEditorService {
setTransientModelProperty(model: ITextModel, key: string, value: any): void;
getTransientModelProperty(model: ITextModel, 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;
getActiveCodeEditor(): ICodeEditor;
openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
}

View File

@@ -12,8 +12,11 @@ import { IModelDecorationOptions, IModelDecorationOverviewRulerOptions, Overview
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';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
export class CodeEditorServiceImpl extends AbstractCodeEditorService {
export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
private _styleSheet: HTMLStyleElement;
private _decorationOptionProviders: { [key: string]: IModelDecorationOptionsProvider };
@@ -65,6 +68,8 @@ export class CodeEditorServiceImpl extends AbstractCodeEditorService {
return provider.getOptions(this, writable);
}
abstract getActiveCodeEditor(): ICodeEditor;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
}
interface IModelDecorationOptionsProvider extends IDisposable {
@@ -205,9 +210,9 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
}
const _CSS_MAP = {
const _CSS_MAP: { [prop: string]: string; } = {
color: 'color:{0} !important;',
opacity: 'opacity:{0};',
opacity: 'opacity:{0}; will-change: opacity;', // TODO@Ben: 'will-change: opacity' is a workaround for https://github.com/Microsoft/vscode/issues/52196
backgroundColor: 'background-color:{0};',
outline: 'outline:{0};',

View File

@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* 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 URI from 'vs/base/common/uri';
import * as dom from 'vs/base/browser/dom';
import { parse } from 'vs/base/common/marshalling';
import { Schemas } from 'vs/base/common/network';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { normalize } from 'vs/base/common/paths';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
export class OpenerService implements IOpenerService {
_serviceBrand: any;
constructor(
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@ICommandService private readonly _commandService: ICommandService,
@optional(ITelemetryService) private _telemetryService: ITelemetryService = NullTelemetryService
) {
//
}
open(resource: URI, options?: { openToSide?: boolean }): TPromise<any> {
/* __GDPR__
"openerService" : {
"scheme" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._telemetryService.publicLog('openerService', { scheme: resource.scheme });
const { scheme, path, query, fragment } = resource;
let promise: TPromise<any> = TPromise.wrap(void 0);
if (scheme === Schemas.http || scheme === Schemas.https || scheme === Schemas.mailto) {
// open http or default mail application
dom.windowOpenNoOpener(resource.toString(true));
} else if (scheme === 'command' && CommandsRegistry.getCommand(path)) {
// execute as command
let args: any = [];
try {
args = parse(query);
if (!Array.isArray(args)) {
args = [args];
}
} catch (e) {
//
}
promise = this._commandService.executeCommand(path, ...args);
} else {
let selection: {
startLineNumber: number;
startColumn: number;
};
const match = /^L?(\d+)(?:,(\d+))?/.exec(fragment);
if (match) {
// support file:///some/file.js#73,84
// support file:///some/file.js#L73
selection = {
startLineNumber: parseInt(match[1]),
startColumn: match[2] ? parseInt(match[2]) : 1
};
// remove fragment
resource = resource.with({ fragment: '' });
}
if (!resource.scheme) {
// we cannot handle those
return TPromise.as(undefined);
} else if (resource.scheme === Schemas.file) {
resource = resource.with({ path: normalize(resource.path) }); // workaround for non-normalized paths (https://github.com/Microsoft/vscode/issues/12954)
}
promise = this._editorService.openCodeEditor({ resource, options: { selection, } }, this._editorService.getFocusedCodeEditor(), options && options.openToSide);
}
return promise;
}
}

View File

@@ -11,7 +11,7 @@ import { IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { IConfiguration } from 'vs/editor/common/editorCommon';
export interface ExecCoreEditorCommandFunc {
(editorCommand: CoreEditorCommand, args: any): void;
@@ -47,14 +47,14 @@ export interface ICommandDelegate {
export class ViewController {
private readonly configuration: Configuration;
private readonly configuration: IConfiguration;
private readonly viewModel: IViewModel;
private readonly _execCoreEditorCommandFunc: ExecCoreEditorCommandFunc;
private readonly outgoingEvents: ViewOutgoingEvents;
private readonly commandDelegate: ICommandDelegate;
constructor(
configuration: Configuration,
configuration: IConfiguration,
viewModel: IViewModel,
execCommandFunc: ExecCoreEditorCommandFunc,
outgoingEvents: ViewOutgoingEvents,

View File

@@ -10,7 +10,7 @@ import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { Range } from 'vs/editor/common/core/range';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { TextAreaHandler, ITextAreaHandlerHelper } from 'vs/editor/browser/controller/textAreaHandler';
import { PointerHandler } from 'vs/editor/browser/controller/pointerHandler';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
@@ -93,7 +93,7 @@ export class View extends ViewEventHandler {
constructor(
commandDelegate: ICommandDelegate,
configuration: Configuration,
configuration: IConfiguration,
themeService: IThemeService,
model: IViewModel,
cursor: Cursor,

View File

@@ -22,6 +22,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
private _spaceWidth: number;
private _renderResult: string[];
private _enabled: boolean;
private _activeIndentEnabled: boolean;
constructor(context: ViewContext) {
super();
@@ -30,6 +31,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
this._lineHeight = this._context.configuration.editor.lineHeight;
this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth;
this._enabled = this._context.configuration.editor.viewInfo.renderIndentGuides;
this._activeIndentEnabled = this._context.configuration.editor.viewInfo.highlightActiveIndentGuide;
this._renderResult = null;
this._context.addEventHandler(this);
@@ -53,6 +55,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
}
if (e.viewInfo) {
this._enabled = this._context.configuration.editor.viewInfo.renderIndentGuides;
this._activeIndentEnabled = this._context.configuration.editor.viewInfo.highlightActiveIndentGuide;
}
return true;
}
@@ -105,6 +108,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
const visibleEndLineNumber = ctx.visibleRange.endLineNumber;
const tabSize = this._context.model.getTabSize();
const tabWidth = tabSize * this._spaceWidth;
const scrollWidth = ctx.scrollWidth;
const lineHeight = this._lineHeight;
const indentGuideWidth = tabWidth;
@@ -113,7 +117,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
let activeIndentStartLineNumber = 0;
let activeIndentEndLineNumber = 0;
let activeIndentLevel = 0;
if (this._primaryLineNumber) {
if (this._activeIndentEnabled && this._primaryLineNumber) {
const activeIndentInfo = this._context.model.getActiveIndentGuide(this._primaryLineNumber, visibleStartLineNumber, visibleEndLineNumber);
activeIndentStartLineNumber = activeIndentInfo.startLineNumber;
activeIndentEndLineNumber = activeIndentInfo.endLineNumber;
@@ -133,6 +137,9 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
let className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr');
result += `<div class="${className}" style="left:${left}px;height:${lineHeight}px;width:${indentGuideWidth}px"></div>`;
left += tabWidth;
if (left > scrollWidth) {
break;
}
}
output[lineIndex] = result;

View File

@@ -191,6 +191,7 @@ export class ViewLine implements IVisibleLine {
let renderLineInput = new RenderLineInput(
options.useMonospaceOptimizations,
lineData.content,
lineData.continuesWithWrappedLine,
lineData.isBasicASCII,
lineData.containsRTL,
lineData.minColumn - 1,
@@ -230,7 +231,7 @@ export class ViewLine implements IVisibleLine {
// Another rounding error has been observed on Linux in VSCode, where <span> width
// rounding errors add up to an observable large number...
// ---
// Also see another example of rounding errors on Windows in
// Also see another example of rounding errors on Windows in
// https://github.com/Microsoft/vscode/issues/33178
renderedViewLine = new FastRenderedViewLine(
this._renderedViewLine ? this._renderedViewLine.domNode : null,

View File

@@ -271,6 +271,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return this._visibleLines.onTokensChanged(e);
}
public onZonesChanged(e: viewEvents.ViewZonesChangedEvent): boolean {
this._context.viewLayout.onMaxLineWidthChanged(this._maxLineWidth);
return this._visibleLines.onZonesChanged(e);
}
public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean {

View File

@@ -913,6 +913,11 @@ export class Minimap extends ViewPart {
minimapCharRenderer.x1BlockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont);
}
dx += charWidth;
if (dx > maxDx) {
// hit edge of minimap
return;
}
}
}
}

View File

@@ -25,6 +25,7 @@ export interface IMyViewZone {
interface IComputedViewZoneProps {
afterViewLineNumber: number;
heightInPx: number;
minWidthInPx: number;
}
export class ViewZones extends ViewPart {
@@ -138,7 +139,8 @@ export class ViewZones extends ViewPart {
if (zone.afterLineNumber === 0) {
return {
afterViewLineNumber: 0,
heightInPx: this._heightInPixels(zone)
heightInPx: this._heightInPixels(zone),
minWidthInPx: this._minWidthInPixels(zone)
};
}
@@ -177,13 +179,14 @@ export class ViewZones extends ViewPart {
let isVisible = this._context.model.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition);
return {
afterViewLineNumber: viewPosition.lineNumber,
heightInPx: (isVisible ? this._heightInPixels(zone) : 0)
heightInPx: (isVisible ? this._heightInPixels(zone) : 0),
minWidthInPx: this._minWidthInPixels(zone)
};
}
public addZone(zone: IViewZone): number {
let props = this._computeWhitespaceProps(zone);
let whitespaceId = this._context.viewLayout.addWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx);
let whitespaceId = this._context.viewLayout.addWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);
let myZone: IMyViewZone = {
whitespaceId: whitespaceId,
@@ -275,6 +278,13 @@ export class ViewZones extends ViewPart {
return this._lineHeight;
}
private _minWidthInPixels(zone: IViewZone): number {
if (typeof zone.minWidthInPx === 'number') {
return zone.minWidthInPx;
}
return 0;
}
private _safeCallOnComputedHeight(zone: IViewZone, height: number): void {
if (typeof zone.onComputedHeight === 'function') {
try {

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ISashEvent, IVerticalSashLayoutProvider, Sash } from 'vs/base/browser/ui/sash/sash';
import { ISashEvent, IVerticalSashLayoutProvider, Sash, SashState } 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/browser/services/codeEditorService';
@@ -22,18 +22,16 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { renderViewLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { CodeEditor } from 'vs/editor/browser/codeEditor';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
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, InlineDecorationType, ViewLineRenderingData } 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';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { registerThemingParticipant, IThemeService, ITheme, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { scrollbarShadow, diffInserted, diffRemoved, defaultInsertColor, defaultRemoveColor, diffInsertedOutline, diffRemovedOutline } from 'vs/platform/theme/common/colorRegistry';
import { scrollbarShadow, diffInserted, diffRemoved, defaultInsertColor, defaultRemoveColor, diffInsertedOutline, diffRemovedOutline, diffBorder } from 'vs/platform/theme/common/colorRegistry';
import { Color } from 'vs/base/common/color';
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
@@ -87,7 +85,7 @@ class VisualEditorState {
return allViewZones.filter((z) => !this._zonesMap[String(z.id)]);
}
public clean(editor: CodeEditor): void {
public clean(editor: CodeEditorWidget): void {
// (1) View zones
if (this._zones.length > 0) {
editor.changeViewZones((viewChangeAccessor: editorBrowser.IViewZoneChangeAccessor) => {
@@ -103,7 +101,7 @@ class VisualEditorState {
this._decorations = editor.deltaDecorations(this._decorations, []);
}
public apply(editor: CodeEditor, overviewRuler: editorBrowser.IOverviewRuler, newDecorations: IEditorDiffDecorationsWithZones, restoreScrollState: boolean): void {
public apply(editor: CodeEditorWidget, overviewRuler: editorBrowser.IOverviewRuler, newDecorations: IEditorDiffDecorationsWithZones, restoreScrollState: boolean): void {
const scrollState = restoreScrollState ? StableEditorScrollState.capture(editor) : null;
@@ -162,12 +160,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
private _reviewHeight: number;
private readonly _measureDomElementToken: number;
private originalEditor: CodeEditor;
private originalEditor: CodeEditorWidget;
private _originalDomNode: HTMLElement;
private _originalEditorState: VisualEditorState;
private _originalOverviewRuler: editorBrowser.IOverviewRuler;
private modifiedEditor: CodeEditor;
private modifiedEditor: CodeEditorWidget;
private _modifiedDomNode: HTMLElement;
private _modifiedEditorState: VisualEditorState;
private _modifiedOverviewRuler: editorBrowser.IOverviewRuler;
@@ -470,8 +468,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
}));
}
protected _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: editorOptions.IEditorOptions): CodeEditor {
return instantiationService.createInstance(CodeEditor, container, options);
protected _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: editorOptions.IEditorOptions): CodeEditorWidget {
return instantiationService.createInstance(CodeEditorWidget, container, options, {});
}
public dispose(): void {
@@ -486,10 +484,14 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._cleanViewZonesAndDecorations();
this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode());
this._originalOverviewRuler.dispose();
this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode());
this._modifiedOverviewRuler.dispose();
if (this._originalOverviewRuler) {
this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode());
this._originalOverviewRuler.dispose();
}
if (this._modifiedOverviewRuler) {
this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode());
this._modifiedOverviewRuler.dispose();
}
this._overviewDomElement.removeChild(this._overviewViewportDomElement.domNode);
this._containerDomElement.removeChild(this._overviewDomElement);
@@ -751,8 +753,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this.modifiedEditor.focus();
}
public isFocused(): boolean {
return this.originalEditor.isFocused() || this.modifiedEditor.isFocused();
public hasTextFocus(): boolean {
return this.originalEditor.hasTextFocus() || this.modifiedEditor.hasTextFocus();
}
public onVisible(): void {
@@ -1175,7 +1177,7 @@ interface IDataSource {
getModifiedEditor(): editorBrowser.ICodeEditor;
}
class DiffEditorWidgetStyle extends Disposable {
abstract class DiffEditorWidgetStyle extends Disposable implements IDiffEditorWidgetStyle {
_dataSource: IDataSource;
_insertColor: Color;
@@ -1223,17 +1225,12 @@ class DiffEditorWidgetStyle extends Disposable {
};
}
_getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean): IEditorsZones {
return null;
}
protected abstract _getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean): IEditorsZones;
protected abstract _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations;
protected abstract _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations;
_getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
return null;
}
_getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
return null;
}
public abstract setEnableSplitViewResizing(enableSplitViewResizing: boolean): void;
public abstract layout(): number;
}
interface IMyViewZone extends editorBrowser.IViewZone {
@@ -1526,7 +1523,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
this._sash = this._register(new Sash(this._dataSource.getContainerDomNode(), this));
if (this._disableSash) {
this._sash.disable();
this._sash.state = SashState.Disabled;
}
this._sash.onDidStart(() => this.onSashDragStart());
@@ -1535,20 +1532,11 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
this._sash.onDidReset(() => this.onSashReset());
}
public dispose(): void {
super.dispose();
}
public setEnableSplitViewResizing(enableSplitViewResizing: boolean): void {
let newDisableSash = (enableSplitViewResizing === false);
if (this._disableSash !== newDisableSash) {
this._disableSash = newDisableSash;
if (this._disableSash) {
this._sash.disable();
} else {
this._sash.enable();
}
this._sash.state = this._disableSash ? SashState.Disabled : SashState.Enabled;
}
}
@@ -1617,12 +1605,12 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
return this._dataSource.getHeight();
}
_getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorsZones {
protected _getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorsZones {
let c = new SideBySideViewZonesComputer(lineChanges, originalForeignVZ, modifiedForeignVZ);
return c.getViewZones();
}
_getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
protected _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._removeColor.toString();
let result: IEditorDiffDecorations = {
@@ -1682,7 +1670,7 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd
return result;
}
_getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
protected _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._insertColor.toString();
let result: IEditorDiffDecorations = {
@@ -1749,7 +1737,7 @@ class SideBySideViewZonesComputer extends ViewZonesComputer {
super(lineChanges, originalForeignVZ, modifiedForeignVZ);
}
_produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
if (lineChangeModifiedLength > lineChangeOriginalLength) {
return {
afterLineNumber: Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber),
@@ -1760,7 +1748,7 @@ class SideBySideViewZonesComputer extends ViewZonesComputer {
return null;
}
_produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
if (lineChangeOriginalLength > lineChangeModifiedLength) {
return {
afterLineNumber: Math.max(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber),
@@ -1789,20 +1777,16 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
}));
}
public dispose(): void {
super.dispose();
}
public setEnableSplitViewResizing(enableSplitViewResizing: boolean): void {
// Nothing to do..
}
_getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean): IEditorsZones {
protected _getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean): IEditorsZones {
let computer = new InlineViewZonesComputer(lineChanges, originalForeignVZ, modifiedForeignVZ, originalEditor, modifiedEditor, renderIndicators);
return computer.getViewZones();
}
_getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
protected _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._removeColor.toString();
let result: IEditorDiffDecorations = {
@@ -1831,7 +1815,7 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor
return result;
}
_getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
protected _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
const overviewZoneColor = this._insertColor.toString();
let result: IEditorDiffDecorations = {
@@ -1913,7 +1897,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
this.renderIndicators = renderIndicators;
}
_produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
let marginDomNode = document.createElement('div');
marginDomNode.className = 'inline-added-margin-view-zone';
Configuration.applyFontInfoSlow(marginDomNode, this.modifiedEditorConfiguration.fontInfo);
@@ -1926,7 +1910,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
};
}
_produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
let decorations: InlineDecoration[] = [];
if (lineChange.charChanges) {
for (let j = 0, lengthJ = lineChange.charChanges.length; j < lengthJ; j++) {
@@ -1945,8 +1929,10 @@ class InlineViewZonesComputer extends ViewZonesComputer {
let marginHTML: string[] = [];
let lineDecorationsWidth = this.modifiedEditorConfiguration.layoutInfo.decorationsWidth;
let lineHeight = this.modifiedEditorConfiguration.lineHeight;
const typicalHalfwidthCharacterWidth = this.modifiedEditorConfiguration.fontInfo.typicalHalfwidthCharacterWidth;
let maxCharsPerLine = 0;
for (let lineNumber = lineChange.originalStartLineNumber; lineNumber <= lineChange.originalEndLineNumber; lineNumber++) {
this.renderOriginalLine(lineNumber - lineChange.originalStartLineNumber, this.originalModel, this.modifiedEditorConfiguration, this.modifiedEditorTabSize, lineNumber, decorations, sb);
maxCharsPerLine = Math.max(maxCharsPerLine, this._renderOriginalLine(lineNumber - lineChange.originalStartLineNumber, this.originalModel, this.modifiedEditorConfiguration, this.modifiedEditorTabSize, lineNumber, decorations, sb));
if (this.renderIndicators) {
let index = lineNumber - lineChange.originalStartLineNumber;
@@ -1955,6 +1941,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
]);
}
}
maxCharsPerLine += this.modifiedEditorConfiguration.viewInfo.scrollBeyondLastColumn;
let domNode = document.createElement('div');
domNode.className = 'view-lines line-delete';
@@ -1970,27 +1957,17 @@ class InlineViewZonesComputer extends ViewZonesComputer {
shouldNotShrink: true,
afterLineNumber: (lineChange.modifiedEndLineNumber === 0 ? lineChange.modifiedStartLineNumber : lineChange.modifiedStartLineNumber - 1),
heightInLines: lineChangeOriginalLength,
minWidthInPx: (maxCharsPerLine * typicalHalfwidthCharacterWidth),
domNode: domNode,
marginDomNode: marginDomNode
};
}
private renderOriginalLine(count: number, originalModel: ITextModel, config: editorOptions.InternalEditorOptions, tabSize: number, lineNumber: number, decorations: InlineDecoration[], sb: IStringBuilder): void {
let lineContent = originalModel.getLineContent(lineNumber);
private _renderOriginalLine(count: number, originalModel: ITextModel, config: editorOptions.InternalEditorOptions, tabSize: number, lineNumber: number, decorations: InlineDecoration[], sb: IStringBuilder): number {
const lineTokens = originalModel.getLineTokens(lineNumber);
const lineContent = lineTokens.getLineContent();
let actualDecorations = LineDecoration.filter(decorations, lineNumber, 1, lineContent.length + 1);
const defaultMetadata = (
(FontStyle.None << MetadataConsts.FONT_STYLE_OFFSET)
| (ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)
| (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET)
) >>> 0;
const tokens = new Uint32Array(2);
tokens[0] = lineContent.length;
tokens[1] = defaultMetadata;
const lineTokens = new LineTokens(tokens, lineContent);
const actualDecorations = LineDecoration.filter(decorations, lineNumber, 1, lineContent.length + 1);
sb.appendASCIIString('<div class="view-line');
if (decorations.length === 0) {
@@ -2003,9 +1980,10 @@ class InlineViewZonesComputer extends ViewZonesComputer {
const isBasicASCII = ViewLineRenderingData.isBasicASCII(lineContent, originalModel.mightContainNonBasicASCII());
const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, originalModel.mightContainRTL());
renderViewLine(new RenderLineInput(
const output = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
lineContent,
false,
isBasicASCII,
containsRTL,
0,
@@ -2020,6 +1998,9 @@ class InlineViewZonesComputer extends ViewZonesComputer {
), sb);
sb.appendASCIIString('</div>');
const absoluteOffsets = output.characterMapping.getAbsoluteOffsets();
return absoluteOffsets.length > 0 ? absoluteOffsets[absoluteOffsets.length - 1] : 0;
}
}
@@ -2066,4 +2047,9 @@ registerThemingParticipant((theme, collector) => {
if (shadow) {
collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`);
}
let border = theme.getColor(diffBorder);
if (border) {
collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { border-left: 1px solid ${border}; }`);
}
});

View File

@@ -99,7 +99,7 @@ export class DiffNavigator {
if (this._editor.getLineChanges() !== null) {
this.revealFirst = false;
this.nextIdx = -1;
this.next();
this.next(ScrollType.Immediate);
}
}
}
@@ -167,7 +167,7 @@ export class DiffNavigator {
}
}
private _move(fwd: boolean): void {
private _move(fwd: boolean, scrollType: ScrollType): void {
assert.ok(!this.disposed, 'Illegal State - diff navigator has been disposed');
if (!this.canNavigate()) {
@@ -194,7 +194,7 @@ export class DiffNavigator {
try {
let pos = info.range.getStartPosition();
this._editor.setPosition(pos);
this._editor.revealPositionInCenter(pos, ScrollType.Smooth);
this._editor.revealPositionInCenter(pos, scrollType);
} finally {
this.ignoreSelectionChange = false;
}
@@ -204,12 +204,12 @@ export class DiffNavigator {
return this.ranges && this.ranges.length > 0;
}
next(): void {
this._move(true);
next(scrollType: ScrollType = ScrollType.Smooth): void {
this._move(true, scrollType);
}
previous(): void {
this._move(false);
previous(scrollType: ScrollType = ScrollType.Smooth): void {
this._move(false, scrollType);
}
dispose(): void {

View File

@@ -30,6 +30,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
const DIFF_LINES_PADDING = 3;
@@ -124,12 +125,12 @@ export class DiffReview extends Disposable {
}
this._render();
}));
this._register(diffEditor.getOriginalEditor().onDidFocusEditor(() => {
this._register(diffEditor.getOriginalEditor().onDidFocusEditorWidget(() => {
if (this._isVisible) {
this.hide();
}
}));
this._register(diffEditor.getModifiedEditor().onDidFocusEditor(() => {
this._register(diffEditor.getModifiedEditor().onDidFocusEditorWidget(() => {
if (this._isVisible) {
this.hide();
}
@@ -769,6 +770,7 @@ export class DiffReview extends Disposable {
const r = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
lineContent,
false,
isBasicASCII,
containsRTL,
0,
@@ -809,7 +811,8 @@ class DiffReviewNext extends EditorAction {
precondition: ContextKeyExpr.has('isInDiffEditor'),
kbOpts: {
kbExpr: null,
primary: KeyCode.F7
primary: KeyCode.F7,
weight: KeybindingWeight.EditorContrib
}
});
}
@@ -831,7 +834,8 @@ class DiffReviewPrev extends EditorAction {
precondition: ContextKeyExpr.has('isInDiffEditor'),
kbOpts: {
kbExpr: null,
primary: KeyMod.Shift | KeyCode.F7
primary: KeyMod.Shift | KeyCode.F7,
weight: KeybindingWeight.EditorContrib
}
});
}

View File

@@ -10,14 +10,14 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CodeEditor } from 'vs/editor/browser/codeEditor';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IConfigurationChangedEvent, IEditorOptions, IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { INotificationService } from 'vs/platform/notification/common/notification';
export class EmbeddedCodeEditorWidget extends CodeEditor {
export class EmbeddedCodeEditorWidget extends CodeEditorWidget {
private _parentEditor: ICodeEditor;
private _overwriteOptions: IEditorOptions;
@@ -33,7 +33,7 @@ export class EmbeddedCodeEditorWidget extends CodeEditor {
@IThemeService themeService: IThemeService,
@INotificationService notificationService: INotificationService
) {
super(domElement, parentEditor.getRawConfiguration(), instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService);
super(domElement, parentEditor.getRawConfiguration(), {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService);
this._parentEditor = parentEditor;
this._overwriteOptions = options;