Enable markup search hybrid mode (#177542)

* Enable markup search hybrid mode

* Experiment turning all cells into editing mode on replace

* Prepare for minimal find markdown mode

* Add settings for controlling the initial state for find in markdown cells

* Validate initial state
This commit is contained in:
Peng Lyu 2023-04-14 10:48:51 -07:00 committed by GitHub
parent a24f964ea1
commit 76781a1a1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 90 additions and 25 deletions

View file

@ -126,4 +126,8 @@
"application.experimental.rendererProfiling": true,
"editor.experimental.asyncTokenization": true,
"editor.experimental.asyncTokenizationVerification": true,
"notebook.experimental.findInMarkdownMode": {
"source": true,
"preview": true
}
}

View file

@ -26,8 +26,7 @@ export class NotebookFindFilters extends Disposable {
set markupInput(value: boolean) {
if (this._markupInput !== value) {
this._markupInput = value;
this._markupPreview = !value;
this._onDidChange.fire({ markupInput: value, markupPreview: this._markupPreview });
this._onDidChange.fire({ markupInput: value });
}
}
@ -40,8 +39,7 @@ export class NotebookFindFilters extends Disposable {
set markupPreview(value: boolean) {
if (this._markupPreview !== value) {
this._markupPreview = value;
this._markupInput = !value;
this._onDidChange.fire({ markupPreview: value, markupInput: this._markupInput });
this._onDidChange.fire({ markupPreview: value });
}
}
private _codeInput: boolean = true;
@ -70,6 +68,12 @@ export class NotebookFindFilters extends Disposable {
}
}
private readonly _initialMarkupInput: boolean;
private readonly _initialMarkupPreview: boolean;
private readonly _initialCodeInput: boolean;
private readonly _initialCodeOutput: boolean;
constructor(
markupInput: boolean,
markupPreview: boolean,
@ -82,6 +86,20 @@ export class NotebookFindFilters extends Disposable {
this._markupPreview = markupPreview;
this._codeInput = codeInput;
this._codeOutput = codeOutput;
this._initialMarkupInput = markupInput;
this._initialMarkupPreview = markupPreview;
this._initialCodeInput = codeInput;
this._initialCodeOutput = codeOutput;
}
isModified(): boolean {
return (
this._markupInput !== this._initialMarkupInput
|| this._markupPreview !== this._initialMarkupPreview
|| this._codeInput !== this._initialCodeInput
|| this._codeOutput !== this._initialCodeOutput
);
}
update(v: NotebookFindFilters) {

View file

@ -39,6 +39,7 @@ import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookB
import { defaultInputBoxStyles, defaultProgressBarStyles, defaultToggleStyles } from 'vs/platform/theme/browser/defaultStyles';
import { IToggleStyles } from 'vs/base/browser/ui/toggle/toggle';
import { Disposable } from 'vs/base/common/lifecycle';
import { NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
@ -57,7 +58,7 @@ const NOTEBOOK_FIND_FILTERS = nls.localize('notebook.find.filter.filterAction',
const NOTEBOOK_FIND_IN_MARKUP_INPUT = nls.localize('notebook.find.filter.findInMarkupInput', "Markdown Source");
const NOTEBOOK_FIND_IN_MARKUP_PREVIEW = nls.localize('notebook.find.filter.findInMarkupPreview', "Rendered Markdown");
const NOTEBOOK_FIND_IN_CODE_INPUT = nls.localize('notebook.find.filter.findInCodeInput', "Code Cell Source");
const NOTEBOOK_FIND_IN_CODE_OUTPUT = nls.localize('notebook.find.filter.findInCodeOutput', "Cell Output");
const NOTEBOOK_FIND_IN_CODE_OUTPUT = nls.localize('notebook.find.filter.findInCodeOutput', "Code Cell Output");
const NOTEBOOK_FIND_WIDGET_INITIAL_WIDTH = 318;
const NOTEBOOK_FIND_WIDGET_INITIAL_HORIZONTAL_PADDING = 4;
@ -305,7 +306,9 @@ export abstract class SimpleFindReplaceWidget extends Widget {
) {
super();
this._filters = new NotebookFindFilters(true, false, true, true);
const findInMarkdownMode = this._configurationService.getValue<{ source: boolean; preview: boolean }>(NotebookSetting.experimentalFindInMarkdownMode) ?? { source: true, preview: false };
this._filters = new NotebookFindFilters(findInMarkdownMode.source, findInMarkdownMode.preview, true, true);
this._state.change({ filters: this._filters }, false);
this._filters.onDidChange(() => {

View file

@ -112,7 +112,7 @@ class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEdi
this._replaceAllBtn.setEnabled(matches.length > 0 && matches.find(match => match.webviewMatches.length > 0) === undefined);
if (e.filters) {
this._findInput.updateFilterState((this._state.filters?.markupPreview ?? false) || (this._state.filters?.codeOutput !== true));
this._findInput.updateFilterState(this._state.filters?.isModified() ?? false);
}
}));

View file

@ -911,6 +911,25 @@ configurationRegistry.registerConfiguration({
type: 'boolean',
tags: ['notebookLayout'],
default: false
},
[NotebookSetting.experimentalFindInMarkdownMode]: {
markdownDescription: nls.localize('notebook.experimental.findInMarkdownMode', "Customize the Find Widget behavior for searching within markdown cells. When both are enabled, the Find Widget will search either the content or preview based on the current state of the markdown cell. Toggle the boolean values to control the Find Widget's scope for each mode as needed."),
type: 'object',
properties: {
source: {
type: 'boolean',
default: true
},
preview: {
type: 'boolean',
default: false
}
},
default: {
source: true,
preview: false
},
tags: ['notebookLayout']
}
}
});

View file

@ -2440,24 +2440,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
if (!options.includeMarkupPreview && !options.includeOutput) {
this._webview?.findStop();
return findMatches.filter(match =>
(match.cell.cellKind === CellKind.Code && options.includeCodeInput) ||
(match.cell.cellKind === CellKind.Markup && options.includeMarkupInput)
);
return findMatches;
}
// search in webview enabled
const matchMap: { [key: string]: CellFindMatchWithIndex } = {};
findMatches.forEach(match => {
if (match.cell.cellKind === CellKind.Code && options.includeCodeInput) {
matchMap[match.cell.id] = match;
}
if (match.cell.cellKind === CellKind.Markup && options.includeMarkupInput) {
matchMap[match.cell.id] = match;
}
matchMap[match.cell.id] = match;
});
if (this._webview) {
@ -2480,14 +2470,26 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
// attach webview matches to model find matches
webviewMatches.forEach(match => {
if (!options.includeMarkupPreview && match.type === 'preview') {
// skip outputs if not included
const cell = this._notebookViewModel!.viewCells.find(cell => cell.id === match.cellId);
if (!cell) {
return;
}
if (!options.includeOutput && match.type === 'output') {
// skip outputs if not included
return;
if (match.type === 'preview') {
// markup preview
if (cell.getEditState() === CellEditState.Preview && !options.includeMarkupPreview) {
return;
}
if (cell.getEditState() === CellEditState.Editing && options.includeMarkupInput) {
return;
}
} else {
if (!options.includeOutput) {
// skip outputs if not included
return;
}
}
const exisitingMatch = matchMap[match.cellId];

View file

@ -922,7 +922,25 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
}
});
return matches;
// filter based on options and editing state
return matches.filter(match => {
if (match.cell.cellKind === CellKind.Code) {
// code cell, we only include its match if include input is enabled
return options.includeCodeInput;
}
// markup cell, it depends on the editing state
if (match.cell.getEditState() === CellEditState.Editing) {
// editing, even if we includeMarkupPreview
return options.includeMarkupInput;
} else {
// cell in preview mode, we should only include it if includeMarkupPreview is false but includeMarkupInput is true
// if includeMarkupPreview is true, then we should include the webview match result other than this
return !options.includeMarkupPreview && options.includeMarkupInput;
}
}
);
}
replaceOne(cell: ICellViewModel, range: Range, text: string): Promise<void> {

View file

@ -944,6 +944,7 @@ export const NotebookSetting = {
outputFontSize: 'notebook.output.fontSize',
outputFontFamilyDeprecated: 'notebook.outputFontFamily',
outputFontFamily: 'notebook.output.fontFamily',
experimentalFindInMarkdownMode: 'notebook.experimental.findInMarkdownMode',
logging: 'notebook.logging',
} as const;