Allow git to open notebook files (#7403)

* Allow git to open notebook files

* pr feedback
This commit is contained in:
Chris LaFreniere
2019-10-04 15:34:19 -07:00
committed by GitHub
parent 44bc7a89df
commit 0b2a2ad0ed
2 changed files with 31 additions and 23 deletions

View File

@@ -28,6 +28,7 @@ import { NotebookChangeType } from 'sql/workbench/parts/notebook/common/models/c
import { Deferred } from 'sql/base/common/promise'; import { Deferred } from 'sql/base/common/promise';
import { NotebookTextFileModel } from 'sql/workbench/parts/notebook/browser/models/notebookTextFileModel'; import { NotebookTextFileModel } from 'sql/workbench/parts/notebook/browser/models/notebookTextFileModel';
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
export type ModeViewSaveHandler = (handle: number) => Thenable<boolean>; export type ModeViewSaveHandler = (handle: number) => Thenable<boolean>;
@@ -38,7 +39,7 @@ export class NotebookEditorModel extends EditorModel {
private readonly _onDidChangeDirty: Emitter<void> = this._register(new Emitter<void>()); private readonly _onDidChangeDirty: Emitter<void> = this._register(new Emitter<void>());
private _lastEditFullReplacement: boolean; private _lastEditFullReplacement: boolean;
constructor(public readonly notebookUri: URI, constructor(public readonly notebookUri: URI,
private textEditorModel: TextFileEditorModel | UntitledEditorModel, private textEditorModel: TextFileEditorModel | UntitledEditorModel | ResourceEditorModel,
@INotebookService private notebookService: INotebookService, @INotebookService private notebookService: INotebookService,
@ITextFileService private textFileService: ITextFileService, @ITextFileService private textFileService: ITextFileService,
@ITextResourcePropertiesService private textResourcePropertiesService: ITextResourcePropertiesService @ITextResourcePropertiesService private textResourcePropertiesService: ITextResourcePropertiesService
@@ -63,18 +64,23 @@ export class NotebookEditorModel extends EditorModel {
}, err => undefined); }, err => undefined);
} }
})); }));
if (this.textEditorModel instanceof UntitledEditorModel) { if (this.textEditorModel instanceof UntitledEditorModel) {
this._register(this.textEditorModel.onDidChangeDirty(e => this.setDirty(this.textEditorModel.isDirty()))); this._register(this.textEditorModel.onDidChangeDirty(e => {
} else { let dirty = this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
this._register(this.textEditorModel.onDidStateChange(change => { this.setDirty(dirty);
this.setDirty(this.textEditorModel.isDirty());
if (change === StateChange.SAVED) {
this.sendNotebookSerializationStateChange();
}
})); }));
} else {
if (this.textEditorModel instanceof TextFileEditorModel) {
this._register(this.textEditorModel.onDidStateChange(change => {
let dirty = this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
this.setDirty(dirty);
if (change === StateChange.SAVED) {
this.sendNotebookSerializationStateChange();
}
}));
}
} }
this._dirty = this.textEditorModel.isDirty(); this._dirty = this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
} }
public get contentString(): string { public get contentString(): string {
@@ -87,7 +93,7 @@ export class NotebookEditorModel extends EditorModel {
} }
isDirty(): boolean { isDirty(): boolean {
return this.textEditorModel.isDirty(); return this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
} }
public setDirty(dirty: boolean): void { public setDirty(dirty: boolean): void {

View File

@@ -7,8 +7,10 @@ import { Range, IRange } from 'vs/editor/common/core/range';
import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { FindMatch } from 'vs/editor/common/model'; import { FindMatch } from 'vs/editor/common/model';
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
import { NotebookContentChange, INotebookModel } from 'sql/workbench/parts/notebook/browser/models/modelInterfaces'; import { NotebookContentChange, INotebookModel } from 'sql/workbench/parts/notebook/browser/models/modelInterfaces';
import { NotebookChangeType } from 'sql/workbench/parts/notebook/common/models/contracts'; import { NotebookChangeType } from 'sql/workbench/parts/notebook/common/models/contracts';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
export class NotebookTextFileModel { export class NotebookTextFileModel {
// save active cell's line/column in editor model for the beginning of the source property // save active cell's line/column in editor model for the beginning of the source property
@@ -33,7 +35,7 @@ export class NotebookTextFileModel {
} }
} }
public transformAndApplyEditForSourceUpdate(contentChange: NotebookContentChange, textEditorModel: TextFileEditorModel | UntitledEditorModel): boolean { public transformAndApplyEditForSourceUpdate(contentChange: NotebookContentChange, textEditorModel: BaseTextEditorModel): boolean {
let cellGuidRange = this.getCellNodeByGuid(textEditorModel, contentChange.cells[0].cellGuid); let cellGuidRange = this.getCellNodeByGuid(textEditorModel, contentChange.cells[0].cellGuid);
// convert the range to leverage offsets in the json // convert the range to leverage offsets in the json
@@ -109,7 +111,7 @@ export class NotebookTextFileModel {
return false; return false;
} }
public transformAndApplyEditForOutputUpdate(contentChange: NotebookContentChange, textEditorModel: TextFileEditorModel | UntitledEditorModel): boolean { public transformAndApplyEditForOutputUpdate(contentChange: NotebookContentChange, textEditorModel: BaseTextEditorModel): boolean {
if (Array.isArray(contentChange.cells[0].outputs) && contentChange.cells[0].outputs.length > 0) { if (Array.isArray(contentChange.cells[0].outputs) && contentChange.cells[0].outputs.length > 0) {
let newOutput = JSON.stringify(contentChange.cells[0].outputs[contentChange.cells[0].outputs.length - 1], undefined, ' '); let newOutput = JSON.stringify(contentChange.cells[0].outputs[contentChange.cells[0].outputs.length - 1], undefined, ' ');
if (contentChange.cells[0].outputs.length > 1) { if (contentChange.cells[0].outputs.length > 1) {
@@ -136,7 +138,7 @@ export class NotebookTextFileModel {
return false; return false;
} }
public transformAndApplyEditForCellUpdated(contentChange: NotebookContentChange, textEditorModel: TextFileEditorModel | UntitledEditorModel): boolean { public transformAndApplyEditForCellUpdated(contentChange: NotebookContentChange, textEditorModel: BaseTextEditorModel): boolean {
let executionCountMatch = this.getExecutionCountRange(textEditorModel, contentChange.cells[0].cellGuid); let executionCountMatch = this.getExecutionCountRange(textEditorModel, contentChange.cells[0].cellGuid);
if (executionCountMatch && executionCountMatch.range) { if (executionCountMatch && executionCountMatch.range) {
// Execution count can be between 0 and n characters long // Execution count can be between 0 and n characters long
@@ -161,7 +163,7 @@ export class NotebookTextFileModel {
return true; return true;
} }
public transformAndApplyEditForClearOutput(contentChange: NotebookContentChange, textEditorModel: TextFileEditorModel | UntitledEditorModel): boolean { public transformAndApplyEditForClearOutput(contentChange: NotebookContentChange, textEditorModel: BaseTextEditorModel): boolean {
if (!textEditorModel || !contentChange || !contentChange.cells || !contentChange.cells[0] || !contentChange.cells[0].cellGuid) { if (!textEditorModel || !contentChange || !contentChange.cells || !contentChange.cells[0] || !contentChange.cells[0].cellGuid) {
return false; return false;
} }
@@ -178,7 +180,7 @@ export class NotebookTextFileModel {
return false; return false;
} }
public replaceEntireTextEditorModel(notebookModel: INotebookModel, type: NotebookChangeType, textEditorModel: TextFileEditorModel | UntitledEditorModel) { public replaceEntireTextEditorModel(notebookModel: INotebookModel, type: NotebookChangeType, textEditorModel: BaseTextEditorModel) {
let content = JSON.stringify(notebookModel.toJSON(type), undefined, ' '); let content = JSON.stringify(notebookModel.toJSON(type), undefined, ' ');
let model = textEditorModel.textEditorModel; let model = textEditorModel.textEditorModel;
let endLine = model.getLineCount(); let endLine = model.getLineCount();
@@ -190,7 +192,7 @@ export class NotebookTextFileModel {
} }
// Find the beginning of a cell's source in the text editor model // Find the beginning of a cell's source in the text editor model
private updateSourceBeginRange(textEditorModel: TextFileEditorModel | UntitledEditorModel, cellGuid: string): void { private updateSourceBeginRange(textEditorModel: BaseTextEditorModel, cellGuid: string): void {
if (!cellGuid) { if (!cellGuid) {
return; return;
} }
@@ -210,7 +212,7 @@ export class NotebookTextFileModel {
} }
// Find the beginning of a cell's outputs in the text editor model // Find the beginning of a cell's outputs in the text editor model
private updateOutputBeginRange(textEditorModel: TextFileEditorModel | UntitledEditorModel, cellGuid: string): void { private updateOutputBeginRange(textEditorModel: BaseTextEditorModel, cellGuid: string): void {
if (!cellGuid) { if (!cellGuid) {
return undefined; return undefined;
} }
@@ -230,7 +232,7 @@ export class NotebookTextFileModel {
// Find the end of a cell's outputs in the text editor model // Find the end of a cell's outputs in the text editor model
// This will be used as a starting point for any future outputs // This will be used as a starting point for any future outputs
private getEndOfOutputs(textEditorModel: TextFileEditorModel | UntitledEditorModel, cellGuid: string) { private getEndOfOutputs(textEditorModel: BaseTextEditorModel, cellGuid: string) {
let outputsBegin; let outputsBegin;
if (this._activeCellGuid === cellGuid) { if (this._activeCellGuid === cellGuid) {
outputsBegin = this._outputBeginRange; outputsBegin = this._outputBeginRange;
@@ -272,7 +274,7 @@ export class NotebookTextFileModel {
} }
// Determine what text needs to be replaced when execution counts are updated // Determine what text needs to be replaced when execution counts are updated
private getExecutionCountRange(textEditorModel: TextFileEditorModel | UntitledEditorModel, cellGuid: string) { private getExecutionCountRange(textEditorModel: BaseTextEditorModel, cellGuid: string) {
let endOutputRange = this.getEndOfOutputs(textEditorModel, cellGuid); let endOutputRange = this.getEndOfOutputs(textEditorModel, cellGuid);
if (endOutputRange && endOutputRange.endLineNumber) { if (endOutputRange && endOutputRange.endLineNumber) {
return textEditorModel.textEditorModel.findNextMatch('"execution_count": ', { lineNumber: endOutputRange.endLineNumber, column: endOutputRange.endColumn }, false, true, undefined, true); return textEditorModel.textEditorModel.findNextMatch('"execution_count": ', { lineNumber: endOutputRange.endLineNumber, column: endOutputRange.endColumn }, false, true, undefined, true);
@@ -282,14 +284,14 @@ export class NotebookTextFileModel {
// Find a cell's location, given its cellGuid // Find a cell's location, given its cellGuid
// If it doesn't exist (e.g. it's not the active cell), attempt to find it // If it doesn't exist (e.g. it's not the active cell), attempt to find it
private getCellNodeByGuid(textEditorModel: TextFileEditorModel | UntitledEditorModel, guid: string) { private getCellNodeByGuid(textEditorModel: BaseTextEditorModel, guid: string) {
if (this._activeCellGuid !== guid || !this._sourceBeginRange) { if (this._activeCellGuid !== guid || !this._sourceBeginRange) {
this.updateSourceBeginRange(textEditorModel, guid); this.updateSourceBeginRange(textEditorModel, guid);
} }
return this._sourceBeginRange; return this._sourceBeginRange;
} }
private getOutputNodeByGuid(textEditorModel: TextFileEditorModel | UntitledEditorModel, guid: string) { private getOutputNodeByGuid(textEditorModel: BaseTextEditorModel, guid: string) {
if (this._activeCellGuid !== guid) { if (this._activeCellGuid !== guid) {
this.updateOutputBeginRange(textEditorModel, guid); this.updateOutputBeginRange(textEditorModel, guid);
} }
@@ -302,7 +304,7 @@ function areRangePropertiesPopulated(range: Range) {
return range && range.startLineNumber !== 0 && range.startColumn !== 0 && range.endLineNumber !== 0 && range.endColumn !== 0; return range && range.startLineNumber !== 0 && range.startColumn !== 0 && range.endLineNumber !== 0 && range.endColumn !== 0;
} }
function findOrSetCellGuidMatch(textEditorModel: TextFileEditorModel | UntitledEditorModel, cellGuid: string): FindMatch[] { function findOrSetCellGuidMatch(textEditorModel: BaseTextEditorModel, cellGuid: string): FindMatch[] {
if (!textEditorModel || !cellGuid) { if (!textEditorModel || !cellGuid) {
return undefined; return undefined;
} }