提交 51e471a6 编写于 作者: J Joao Moreno

Merge remote-tracking branch 'origin/master'

......@@ -24,14 +24,13 @@ const localize = nls.loadMessageBundle();
class CheckoutItem implements QuickPickItem {
protected get shortCommit(): string { return (this.ref.commit || '').substr(0, 8); }
protected get treeish(): string | undefined { return this.ref.name; }
get label(): string { return this.ref.name || this.shortCommit; }
get description(): string { return this.shortCommit; }
constructor(protected ref: Ref) { }
async run(repository: Repository): Promise<void> {
const ref = this.treeish;
const ref = this.ref.name;
if (!ref) {
return;
......@@ -54,13 +53,12 @@ class CheckoutRemoteHeadItem extends CheckoutItem {
return localize('remote branch at', "Remote branch at {0}", this.shortCommit);
}
protected get treeish(): string | undefined {
async run(repository: Repository): Promise<void> {
if (!this.ref.name) {
return;
}
const match = /^[^/]+\/(.*)$/.exec(this.ref.name);
return match ? match[1] : this.ref.name;
await repository.checkoutTracking(this.ref.name);
}
}
......
......@@ -913,9 +913,13 @@ export class Repository {
await this.run(['update-index', '--cacheinfo', mode, hash, path]);
}
async checkout(treeish: string, paths: string[]): Promise<void> {
async checkout(treeish: string, paths: string[], opts: { track?: boolean } = Object.create(null)): Promise<void> {
const args = ['checkout', '-q'];
if (opts.track) {
args.push('--track');
}
if (treeish) {
args.push(treeish);
}
......
......@@ -289,6 +289,7 @@ export const enum Operation {
SetBranchUpstream = 'SetBranchUpstream',
HashObject = 'HashObject',
Checkout = 'Checkout',
CheckoutTracking = 'CheckoutTracking',
Reset = 'Reset',
Remote = 'Remote',
Fetch = 'Fetch',
......@@ -877,6 +878,10 @@ export class Repository implements Disposable {
await this.run(Operation.Checkout, () => this.repository.checkout(treeish, []));
}
async checkoutTracking(treeish: string): Promise<void> {
await this.run(Operation.CheckoutTracking, () => this.repository.checkout(treeish, [], { track: true }));
}
async getCommit(ref: string): Promise<Commit> {
return await this.repository.getCommit(ref);
}
......
......@@ -11,26 +11,35 @@ 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';
import { Disposable } from 'vs/base/common/lifecycle';
export abstract class AbstractCodeEditorService implements ICodeEditorService {
export abstract class AbstractCodeEditorService extends Disposable implements ICodeEditorService {
_serviceBrand: any;
private readonly _onCodeEditorAdd: Emitter<ICodeEditor>;
private readonly _onCodeEditorRemove: Emitter<ICodeEditor>;
private _codeEditors: { [editorId: string]: ICodeEditor; };
private readonly _onCodeEditorAdd: Emitter<ICodeEditor> = this._register(new Emitter<ICodeEditor>());
public readonly onCodeEditorAdd: Event<ICodeEditor> = this._onCodeEditorAdd.event;
private readonly _onCodeEditorRemove: Emitter<ICodeEditor> = this._register(new Emitter<ICodeEditor>());
public readonly onCodeEditorRemove: Event<ICodeEditor> = this._onCodeEditorRemove.event;
private readonly _onDiffEditorAdd: Emitter<IDiffEditor> = this._register(new Emitter<IDiffEditor>());
public readonly onDiffEditorAdd: Event<IDiffEditor> = this._onDiffEditorAdd.event;
private readonly _onDiffEditorRemove: Emitter<IDiffEditor> = this._register(new Emitter<IDiffEditor>());
public readonly onDiffEditorRemove: Event<IDiffEditor> = this._onDiffEditorRemove.event;
private readonly _onDiffEditorAdd: Emitter<IDiffEditor>;
private readonly _onDiffEditorRemove: Emitter<IDiffEditor>;
private readonly _onDidChangeTransientModelProperty: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
public readonly onDidChangeTransientModelProperty: Event<ITextModel> = this._onDidChangeTransientModelProperty.event;
private _codeEditors: { [editorId: string]: ICodeEditor; };
private _diffEditors: { [editorId: string]: IDiffEditor; };
constructor() {
super();
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 {
......@@ -38,20 +47,12 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
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]);
}
......@@ -61,20 +62,12 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
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]);
}
......@@ -117,6 +110,7 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
}
w.set(key, value);
this._onDidChangeTransientModelProperty.fire(model);
}
public getTransientModelProperty(model: ITextModel, key: string): any {
......
......@@ -17,11 +17,14 @@ export const ICodeEditorService = createDecorator<ICodeEditorService>('codeEdito
export interface ICodeEditorService {
_serviceBrand: any;
onCodeEditorAdd: Event<ICodeEditor>;
onCodeEditorRemove: Event<ICodeEditor>;
readonly onCodeEditorAdd: Event<ICodeEditor>;
readonly onCodeEditorRemove: Event<ICodeEditor>;
readonly onDiffEditorAdd: Event<IDiffEditor>;
readonly onDiffEditorRemove: Event<IDiffEditor>;
readonly onDidChangeTransientModelProperty: Event<ITextModel>;
onDiffEditorAdd: Event<IDiffEditor>;
onDiffEditorRemove: Event<IDiffEditor>;
addCodeEditor(editor: ICodeEditor): void;
removeCodeEditor(editor: ICodeEditor): void;
......
......@@ -314,19 +314,31 @@ export class Transform extends Marker {
resolve(value: string): string {
const _this = this;
return value.replace(this.regexp, function () {
let ret = '';
for (const marker of _this._children) {
if (marker instanceof FormatString) {
let value = arguments.length - 2 > marker.index ? <string>arguments[marker.index] : '';
value = marker.resolve(value);
ret += value;
} else {
ret += marker.toString();
}
}
return ret;
let didMatch = false;
let ret = value.replace(this.regexp, function () {
didMatch = true;
return _this._replace(Array.prototype.slice.call(arguments, 0, -2));
});
// when the regex didn't match and when the transform has
// else branches, then run those
if (!didMatch && this._children.some(child => child instanceof FormatString && Boolean(child.elseValue))) {
ret = this._replace([]);
}
return ret;
}
private _replace(groups: string[]): string {
let ret = '';
for (const marker of this._children) {
if (marker instanceof FormatString) {
let value = groups[marker.index] || '';
value = marker.resolve(value);
ret += value;
} else {
ret += marker.toString();
}
}
return ret;
}
toString(): string {
......@@ -784,9 +796,10 @@ export class SnippetParser {
}
let value: string;
if (value = this._accept(TokenType.Backslash, true)) {
// \, or \|
// \, \|, or \\
value = this._accept(TokenType.Comma, true)
|| this._accept(TokenType.Pipe, true)
|| this._accept(TokenType.Backslash, true)
|| value;
} else {
value = this._accept(undefined, true);
......
......@@ -353,6 +353,12 @@ suite('SnippetParser', () => {
assertText('${1||}', '${1||}');
});
test('Backslash character escape in choice tabstop doesn\'t work #58494', function () {
const { placeholders } = new SnippetParser().parse('${1|\\,,},$,\\|,\\\\|}');
assert.equal(placeholders.length, 1);
assert.ok(placeholders[0].choice instanceof Choice);
});
test('Parser, only textmate', () => {
const p = new SnippetParser();
......
......@@ -159,7 +159,8 @@ suite('Snippet Variables Resolver', function () {
assertVariableResolve2('${foobarfoobar/(foo)/${1:+FAR}/g}', 'FARbarFARbar'); // global
assertVariableResolve2('${foobarfoobar/(foo)/${1:+FAR}/}', 'FARbarfoobar'); // first match
assertVariableResolve2('${foobarfoobar/(bazz)/${1:+FAR}/g}', 'foobarfoobar'); // no match
assertVariableResolve2('${foobarfoobar/(bazz)/${1:+FAR}/g}', 'foobarfoobar'); // no match, no else
// assertVariableResolve2('${foobarfoobar/(bazz)/${1:+FAR}/g}', ''); // no match
assertVariableResolve2('${foobarfoobar/(foo)/${2:+FAR}/g}', 'barbar'); // bad group reference
});
......@@ -292,4 +293,14 @@ suite('Snippet Variables Resolver', function () {
assertVariableResolve3(resolver, 'CURRENT_MONTH_NAME');
assertVariableResolve3(resolver, 'CURRENT_MONTH_NAME_SHORT');
});
test('creating snippet - format-condition doesn\'t work #53617', function () {
const snippet = new SnippetParser().parse('${TM_LINE_NUMBER/(10)/${1:?It is:It is not}/} line 10', true);
snippet.resolveVariables({ resolve() { return '10'; } });
assert.equal(snippet.toString(), 'It is line 10');
snippet.resolveVariables({ resolve() { return '11'; } });
assert.equal(snippet.toString(), 'It is not line 10');
});
});
......@@ -114,23 +114,6 @@ function toggleWordWrap(editor: ICodeEditor, state: IWordWrapState): IWordWrapSt
};
}
function applyWordWrapState(editor: ICodeEditor, state: IWordWrapState): void {
if (state.transientState) {
// toggle is on
editor.updateOptions({
wordWrap: state.transientState.forceWordWrap,
wordWrapMinified: state.transientState.forceWordWrapMinified
});
return;
}
// toggle is off
editor.updateOptions({
wordWrap: state.configuredWordWrap,
wordWrapMinified: state.configuredWordWrapMinified
});
}
const TOGGLE_WORD_WRAP_ID = 'editor.action.toggleWordWrap';
class ToggleWordWrapAction extends EditorAction {
......@@ -170,9 +153,8 @@ class ToggleWordWrapAction extends EditorAction {
// Compute the new state
const newState = toggleWordWrap(editor, currentState);
// Write the new state
// (this will cause an event and the controller will apply the state)
writeTransientState(model, newState.transientState, codeEditorService);
// Apply the new state
applyWordWrapState(editor, newState);
}
}
......@@ -192,6 +174,7 @@ class ToggleWordWrapController extends Disposable implements IEditorContribution
const isWordWrapMinified = this.contextKeyService.createKey(isWordWrapMinifiedKey, this._isWordWrapMinified(configuration));
const isDominatedByLongLines = this.contextKeyService.createKey(isDominatedByLongLinesKey, this._isDominatedByLongLines(configuration));
const inDiffEditor = this.contextKeyService.createKey(inDiffEditorKey, this._inDiffEditor(configuration));
let currentlyApplyingEditorConfig = false;
this._register(editor.onDidChangeConfiguration((e) => {
if (!e.wrappingInfo) {
......@@ -201,9 +184,21 @@ class ToggleWordWrapController extends Disposable implements IEditorContribution
isWordWrapMinified.set(this._isWordWrapMinified(configuration));
isDominatedByLongLines.set(this._isDominatedByLongLines(configuration));
inDiffEditor.set(this._inDiffEditor(configuration));
if (!currentlyApplyingEditorConfig) {
// I am not the cause of the word wrap getting changed
ensureWordWrapSettings();
}
}));
this._register(editor.onDidChangeModel((e) => {
ensureWordWrapSettings();
}));
this._register(codeEditorService.onDidChangeTransientModelProperty(() => {
ensureWordWrapSettings();
}));
const ensureWordWrapSettings = () => {
// Ensure correct word wrap settings
const newModel = this.editor.getModel();
if (!newModel) {
......@@ -223,8 +218,30 @@ class ToggleWordWrapController extends Disposable implements IEditorContribution
const desiredState = readWordWrapState(newModel, this.configurationService, this.codeEditorService);
// Apply the state
applyWordWrapState(editor, desiredState);
}));
try {
currentlyApplyingEditorConfig = true;
this._applyWordWrapState(desiredState);
} finally {
currentlyApplyingEditorConfig = false;
}
};
}
private _applyWordWrapState(state: IWordWrapState): void {
if (state.transientState) {
// toggle is on
this.editor.updateOptions({
wordWrap: state.transientState.forceWordWrap,
wordWrapMinified: state.transientState.forceWordWrapMinified
});
return;
}
// toggle is off
this.editor.updateOptions({
wordWrap: state.configuredWordWrap,
wordWrapMinified: state.configuredWordWrapMinified
});
}
private _isWordWrapMinified(config: InternalEditorOptions): boolean {
......
......@@ -947,6 +947,7 @@ export class TestCodeEditorService implements ICodeEditorService {
onCodeEditorRemove: Event<ICodeEditor> = Event.None;
onDiffEditorAdd: Event<IDiffEditor> = Event.None;
onDiffEditorRemove: Event<IDiffEditor> = Event.None;
onDidChangeTransientModelProperty: Event<ITextModel> = Event.None;
addCodeEditor(editor: ICodeEditor): void { }
removeCodeEditor(editor: ICodeEditor): void { }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册