提交 56a6279a 编写于 作者: R Rob Lourens

Don't use getActions in search view

#92038
上级 856277c8
......@@ -258,6 +258,10 @@ export class FindInput extends Widget {
this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));
}
public get onDidChange(): Event<string> {
return this.inputBox.onDidChange;
}
public enable(): void {
this.domNode.classList.remove('disabled');
this.inputBox.enable();
......
......@@ -8,53 +8,53 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as platform from 'vs/base/common/platform';
import { dirname } from 'vs/base/common/resources';
import { assertIsDefined, assertType } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { ToggleCaseSensitiveKeybinding, TogglePreserveCaseKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/findModel';
import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess';
import * as nls from 'vs/nls';
import { ICommandAction, MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Action2, ICommandAction, MenuId, MenuRegistry, registerAction2, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IFileService } from 'vs/platform/files/common/files';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { IListService, WorkbenchListFocusContextKey, WorkbenchObjectTree } from 'vs/platform/list/browser/listService';
import { Extensions as QuickAccessExtensions, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { defaultQuickAccessContextKeyValue } from 'vs/workbench/browser/quickaccess';
import { CATEGORIES, Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { Extensions as ViewExtensions, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, IViewsService } from 'vs/workbench/common/views';
import { Extensions as ViewExtensions, IViewContainersRegistry, IViewDescriptorService, IViewsRegistry, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess';
import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet';
import { getMultiSelectedResources, IExplorerService } from 'vs/workbench/contrib/files/browser/files';
import { ExplorerFolderContext, ExplorerRootContext, FilesExplorerFocusCondition, VIEWLET_ID as VIEWLET_ID_FILES } from 'vs/workbench/contrib/files/common/files';
import { AnythingQuickAccessProvider } from 'vs/workbench/contrib/search/browser/anythingQuickAccess';
import { registerContributions as replaceContributions } from 'vs/workbench/contrib/search/browser/replaceContributions';
import { clearHistoryCommand, ClearSearchResultsAction, CloseReplaceAction, CollapseDeepestExpandedLevelAction, copyAllCommand, copyMatchCommand, copyPathCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, RefreshAction, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, togglePreserveCaseCommand, toggleRegexCommand, toggleWholeWordCommand, FindInFilesCommand, ToggleSearchOnTypeAction, ExpandAllAction } from 'vs/workbench/contrib/search/browser/searchActions';
import { cancelSearch, clearHistoryCommand, clearSearchResults, CloseReplaceAction, collapseDeepestExpandedLevel, copyAllCommand, copyMatchCommand, copyPathCommand, expandAll, FindInFilesCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, refreshSearch, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, togglePreserveCaseCommand, toggleRegexCommand, ToggleSearchOnTypeAction, toggleWholeWordCommand } from 'vs/workbench/contrib/search/browser/searchActions';
import { searchClearIcon, searchCollapseAllIcon, searchExpandAllIcon, searchRefreshIcon, searchStopIcon, searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { SearchView } from 'vs/workbench/contrib/search/browser/searchView';
import { registerContributions as searchWidgetContributions } from 'vs/workbench/contrib/search/browser/searchWidget';
import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess';
import * as Constants from 'vs/workbench/contrib/search/common/constants';
import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants';
import { getWorkspaceSymbols } from 'vs/workbench/contrib/search/common/search';
import { resolveResourcesForSearchIncludes } from 'vs/workbench/contrib/search/common/queryBuilder';
import { getWorkspaceSymbols, SearchStateKey, SearchUIState } from 'vs/workbench/contrib/search/common/search';
import { ISearchHistoryService, SearchHistoryService } from 'vs/workbench/contrib/search/common/searchHistoryService';
import { FileMatchOrMatch, ISearchWorkbenchService, RenderableMatch, SearchWorkbenchService, FileMatch, Match, FolderMatch } from 'vs/workbench/contrib/search/common/searchModel';
import { FileMatch, FileMatchOrMatch, FolderMatch, ISearchWorkbenchService, Match, RenderableMatch, SearchWorkbenchService } from 'vs/workbench/contrib/search/common/searchModel';
import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants';
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { VIEWLET_ID, VIEW_ID, SEARCH_EXCLUDE_CONFIG, SearchSortOrder, ISearchConfiguration } from 'vs/workbench/services/search/common/search';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ISearchConfiguration, SearchSortOrder, SEARCH_EXCLUDE_CONFIG, VIEWLET_ID, VIEW_ID } from 'vs/workbench/services/search/common/search';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet';
import { assertType, assertIsDefined } from 'vs/base/common/types';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess';
import { AnythingQuickAccessProvider } from 'vs/workbench/contrib/search/browser/anythingQuickAccess';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess';
import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess';
import { searchViewIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { resolveResourcesForSearchIncludes } from 'vs/workbench/contrib/search/common/queryBuilder';
registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true);
registerSingleton(ISearchHistoryService, SearchHistoryService, true);
......@@ -128,19 +128,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: Constants.CancelActionId,
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, WorkbenchListFocusContextKey),
primary: KeyCode.Escape,
handler: (accessor, args: any) => {
const searchView = getSearchView(accessor.get(IViewsService));
if (searchView) {
searchView.cancelSearch();
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: Constants.RemoveActionId,
weight: KeybindingWeight.WorkbenchContrib,
......@@ -373,6 +360,121 @@ CommandsRegistry.registerCommand({
}
});
registerAction2(class CancelSearchAction extends Action2 {
constructor() {
super({
id: 'search.action.cancel',
title: nls.localize('CancelSearchAction.label', "Cancel Search"),
icon: searchStopIcon,
category,
f1: true,
precondition: SearchStateKey.isEqualTo(SearchUIState.Idle).negate(),
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, WorkbenchListFocusContextKey),
primary: KeyCode.Escape,
},
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 0,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', VIEW_ID), SearchStateKey.isEqualTo(SearchUIState.SlowSearch)),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return cancelSearch(accessor);
}
});
registerAction2(class RefreshAction extends Action2 {
constructor() {
super({
id: 'search.action.refreshSearchResults',
title: nls.localize('RefreshAction.label', "Refresh"),
icon: searchRefreshIcon,
precondition: Constants.ViewHasSearchPatternKey,
category,
f1: true,
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 0,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', VIEW_ID), SearchStateKey.isEqualTo(SearchUIState.SlowSearch).negate()),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return refreshSearch(accessor);
}
});
registerAction2(class CollapseDeepestExpandedLevelAction extends Action2 {
constructor() {
super({
id: 'search.action.collapseSearchResults',
title: nls.localize('CollapseDeepestExpandedLevelAction.label', "Collapse All"),
category,
icon: searchCollapseAllIcon,
f1: true,
precondition: ContextKeyExpr.and(Constants.HasSearchResults, Constants.ViewHasSomeCollapsibleKey),
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 3,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', VIEW_ID), ContextKeyExpr.or(Constants.HasSearchResults.negate(), Constants.ViewHasSomeCollapsibleKey)),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return collapseDeepestExpandedLevel(accessor);
}
});
registerAction2(class ExpandAllAction extends Action2 {
constructor() {
super({
id: 'search.action.expandSearchResults',
title: nls.localize('ExpandAllAction.label', "Expand All"),
category,
icon: searchExpandAllIcon,
f1: true,
precondition: ContextKeyExpr.and(Constants.HasSearchResults, Constants.ViewHasSomeCollapsibleKey.toNegated()),
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 3,
when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', VIEW_ID), Constants.HasSearchResults, Constants.ViewHasSomeCollapsibleKey.toNegated()),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return expandAll(accessor);
}
});
registerAction2(class ClearSearchResultsAction extends Action2 {
constructor() {
super({
id: 'search.action.clearSearchResults',
title: nls.localize('ClearSearchResultsAction.label', "Clear Search Results"),
category,
icon: searchClearIcon,
f1: true,
precondition: ContextKeyExpr.or(Constants.HasSearchResults, Constants.ViewHasSearchPatternKey, Constants.ViewHasReplacePatternKey, Constants.ViewHasFilePatternKey),
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 1,
when: ContextKeyEqualsExpr.create('view', VIEW_ID),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return clearSearchResults(accessor);
}
});
const RevealInSideBarForSearchResultsCommand: ICommandAction = {
id: Constants.RevealInSideBarForSearchResults,
title: nls.localize('revealInSideBar', "Reveal in Side Bar")
......@@ -449,20 +551,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
handler: searchInFolderCommand
});
CommandsRegistry.registerCommand({
id: ClearSearchResultsAction.ID,
handler: (accessor, args: any) => {
accessor.get(IInstantiationService).createInstance(ClearSearchResultsAction, ClearSearchResultsAction.ID, '').run();
}
});
CommandsRegistry.registerCommand({
id: RefreshAction.ID,
handler: (accessor, args: any) => {
accessor.get(IInstantiationService).createInstance(RefreshAction, RefreshAction.ID, '').run();
}
});
const FIND_IN_WORKSPACE_ID = 'filesExplorer.findInWorkspace';
CommandsRegistry.registerCommand({
id: FIND_IN_WORKSPACE_ID,
......@@ -686,12 +774,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
}
});
registry.registerWorkbenchAction(SyncActionDescriptor.from(CollapseDeepestExpandedLevelAction), 'Search: Collapse All', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ExpandAllAction), 'Search: Expand All', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllSymbolsAction, { primary: KeyMod.CtrlCmd | KeyCode.KEY_T }), 'Go to Symbol in Workspace...');
registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSearchOnTypeAction), 'Search: Toggle Search on Type', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(RefreshAction), 'Search: Refresh', category.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ClearSearchResultsAction), 'Search: Clear Search Results', category.value);
// Register Quick Access Handler
const quickAccessRegistry = Registry.as<IQuickAccessRegistry>(QuickAccessExtensions.Quickaccess);
......
......@@ -4,34 +4,34 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { ITreeNavigator } from 'vs/base/browser/ui/tree/tree';
import { Action } from 'vs/base/common/actions';
import { createKeybinding, ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { isWindows, OS } from 'vs/base/common/platform';
import * as nls from 'vs/nls';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ILabelService } from 'vs/platform/label/common/label';
import { ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ILabelService } from 'vs/platform/label/common/label';
import { getSelectionKeyboardEvent, WorkbenchObjectTree } from 'vs/platform/list/browser/listService';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IViewsService } from 'vs/workbench/common/views';
import { searchRemoveIcon, searchReplaceAllIcon, searchReplaceIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { SearchView } from 'vs/workbench/contrib/search/browser/searchView';
import * as Constants from 'vs/workbench/contrib/search/common/constants';
import { IReplaceService } from 'vs/workbench/contrib/search/common/replace';
import { FolderMatch, FileMatch, FolderMatchWithResource, Match, RenderableMatch, searchMatchComparer, SearchResult } from 'vs/workbench/contrib/search/common/searchModel';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ISearchConfiguration, VIEW_ID, VIEWLET_ID } from 'vs/workbench/services/search/common/search';
import { ISearchHistoryService } from 'vs/workbench/contrib/search/common/searchHistoryService';
import { ITreeNavigator } from 'vs/base/browser/ui/tree/tree';
import { IViewsService } from 'vs/workbench/common/views';
import { SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
import { FileMatch, FolderMatch, FolderMatchWithResource, Match, RenderableMatch, searchMatchComparer, SearchResult } from 'vs/workbench/contrib/search/common/searchModel';
import { OpenEditorCommandId } from 'vs/workbench/contrib/searchEditor/browser/constants';
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
import { searchRefreshIcon, searchCollapseAllIcon, searchExpandAllIcon, searchClearIcon, searchReplaceAllIcon, searchReplaceIcon, searchRemoveIcon, searchStopIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/searchEditor.contribution';
import { OpenEditorCommandId } from 'vs/workbench/contrib/searchEditor/browser/constants';
import { SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ISearchConfiguration, VIEWLET_ID, VIEW_ID } from 'vs/workbench/services/search/common/search';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
export function isSearchViewFocused(viewsService: IViewsService): boolean {
const searchView = getSearchView(viewsService);
......@@ -289,227 +289,77 @@ export class ToggleSearchOnTypeAction extends Action {
}
}
export class RefreshAction extends Action {
static readonly ID: string = 'search.action.refreshSearchResults';
static LABEL: string = nls.localize('RefreshAction.label', "Refresh");
constructor(id: string, label: string,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, 'search-action ' + ThemeIcon.asClassName(searchRefreshIcon));
}
get enabled(): boolean {
const searchView = getSearchView(this.viewsService);
return !!searchView && searchView.hasSearchPattern();
export function expandAll(accessor: ServicesAccessor) {
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
const viewer = searchView.getControl();
viewer.expandAll();
viewer.domFocus();
viewer.focusFirst();
}
}
update(): void {
this._setEnabled(this.enabled);
export function clearSearchResults(accessor: ServicesAccessor) {
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
searchView.clearSearchResults();
}
}
run(): Promise<void> {
const searchView = getSearchView(this.viewsService);
if (searchView) {
searchView.triggerQueryChange({ preserveFocus: false });
}
return Promise.resolve();
export function cancelSearch(accessor: ServicesAccessor) {
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
searchView.cancelSearch();
}
}
export class CollapseDeepestExpandedLevelAction extends Action {
static readonly ID: string = 'search.action.collapseSearchResults';
static LABEL: string = nls.localize('CollapseDeepestExpandedLevelAction.label', "Collapse All");
constructor(id: string, label: string,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, 'search-action ' + ThemeIcon.asClassName(searchCollapseAllIcon));
this.update();
export function refreshSearch(accessor: ServicesAccessor) {
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
searchView.triggerQueryChange({ preserveFocus: false });
}
}
update(): void {
const searchView = getSearchView(this.viewsService);
this.enabled = !!searchView && searchView.hasSearchResults();
}
export function collapseDeepestExpandedLevel(accessor: ServicesAccessor) {
run(): Promise<void> {
const searchView = getSearchView(this.viewsService);
if (searchView) {
const viewer = searchView.getControl();
/**
* one level to collapse so collapse everything. If FolderMatch, check if there are visible grandchildren,
* i.e. if Matches are returned by the navigator, and if so, collapse to them, otherwise collapse all levels.
*/
const navigator = viewer.navigate();
let node = navigator.first();
let collapseFileMatchLevel = false;
if (node instanceof FolderMatch) {
while (node = navigator.next()) {
if (node instanceof Match) {
collapseFileMatchLevel = true;
break;
}
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
const viewer = searchView.getControl();
/**
* one level to collapse so collapse everything. If FolderMatch, check if there are visible grandchildren,
* i.e. if Matches are returned by the navigator, and if so, collapse to them, otherwise collapse all levels.
*/
const navigator = viewer.navigate();
let node = navigator.first();
let collapseFileMatchLevel = false;
if (node instanceof FolderMatch) {
while (node = navigator.next()) {
if (node instanceof Match) {
collapseFileMatchLevel = true;
break;
}
}
if (collapseFileMatchLevel) {
node = navigator.first();
do {
if (node instanceof FileMatch) {
viewer.collapse(node);
}
} while (node = navigator.next());
} else {
viewer.collapseAll();
}
viewer.domFocus();
viewer.focusFirst();
}
return Promise.resolve(undefined);
}
}
export class ExpandAllAction extends Action {
static readonly ID: string = 'search.action.expandSearchResults';
static LABEL: string = nls.localize('ExpandAllAction.label', "Expand All");
constructor(id: string, label: string,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, 'search-action ' + ThemeIcon.asClassName(searchExpandAllIcon));
this.update();
}
update(): void {
const searchView = getSearchView(this.viewsService);
this.enabled = !!searchView && searchView.hasSearchResults();
}
run(): Promise<void> {
const searchView = getSearchView(this.viewsService);
if (searchView) {
const viewer = searchView.getControl();
viewer.expandAll();
viewer.domFocus();
viewer.focusFirst();
}
return Promise.resolve(undefined);
}
}
export class ToggleCollapseAndExpandAction extends Action {
static readonly ID: string = 'search.action.collapseOrExpandSearchResults';
static LABEL: string = nls.localize('ToggleCollapseAndExpandAction.label', "Toggle Collapse and Expand");
// Cache to keep from crawling the tree too often.
private action: CollapseDeepestExpandedLevelAction | ExpandAllAction | undefined;
constructor(id: string, label: string,
private collapseAction: CollapseDeepestExpandedLevelAction,
private expandAction: ExpandAllAction,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, collapseAction.class);
this.update();
}
update(): void {
const searchView = getSearchView(this.viewsService);
this.enabled = !!searchView && searchView.hasSearchResults();
this.onTreeCollapseStateChange();
}
onTreeCollapseStateChange() {
this.action = undefined;
this.determineAction();
}
private determineAction(): CollapseDeepestExpandedLevelAction | ExpandAllAction {
if (this.action !== undefined) { return this.action; }
this.action = this.isSomeCollapsible() ? this.collapseAction : this.expandAction;
this.class = this.action.class;
return this.action;
}
private isSomeCollapsible(): boolean {
const searchView = getSearchView(this.viewsService);
if (searchView) {
const viewer = searchView.getControl();
const navigator = viewer.navigate();
let node = navigator.first();
if (collapseFileMatchLevel) {
node = navigator.first();
do {
if (!viewer.isCollapsed(node)) {
return true;
if (node instanceof FileMatch) {
viewer.collapse(node);
}
} while (node = navigator.next());
}
return false;
}
async run(): Promise<void> {
await this.determineAction().run();
}
}
export class ClearSearchResultsAction extends Action {
static readonly ID: string = 'search.action.clearSearchResults';
static LABEL: string = nls.localize('ClearSearchResultsAction.label', "Clear Search Results");
constructor(id: string, label: string,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, 'search-action ' + ThemeIcon.asClassName(searchClearIcon));
this.update();
}
update(): void {
const searchView = getSearchView(this.viewsService);
this.enabled = !!searchView && (!searchView.allSearchFieldsClear() || searchView.hasSearchResults() || !searchView.allFilePatternFieldsClear());
}
run(): Promise<void> {
const searchView = getSearchView(this.viewsService);
if (searchView) {
searchView.clearSearchResults();
}
return Promise.resolve();
}
}
export class CancelSearchAction extends Action {
static readonly ID: string = 'search.action.cancelSearch';
static LABEL: string = nls.localize('CancelSearchAction.label', "Cancel Search");
constructor(id: string, label: string,
@IViewsService private readonly viewsService: IViewsService
) {
super(id, label, 'search-action ' + ThemeIcon.asClassName(searchStopIcon));
this.update();
}
update(): void {
const searchView = getSearchView(this.viewsService);
this.enabled = !!searchView && searchView.isSlowSearch();
}
run(): Promise<void> {
const searchView = getSearchView(this.viewsService);
if (searchView) {
searchView.cancelSearch();
} else {
viewer.collapseAll();
}
return Promise.resolve(undefined);
viewer.domFocus();
viewer.focusFirst();
}
}
......
......@@ -11,7 +11,6 @@ export const FocusActiveEditorCommandId = 'search.action.focusActiveEditor';
export const FocusSearchFromResults = 'search.action.focusSearchFromResults';
export const OpenMatch = 'search.action.openResult';
export const OpenMatchToSide = 'search.action.openResultToSide';
export const CancelActionId = 'search.action.cancel';
export const RemoveActionId = 'search.action.remove';
export const CopyPathCommandId = 'search.action.copyPath';
export const CopyMatchCommandId = 'search.action.copyMatch';
......@@ -46,3 +45,7 @@ export const FileMatchOrFolderMatchWithResourceFocusKey = new RawContextKey<bool
export const FileFocusKey = new RawContextKey<boolean>('fileMatchFocus', false);
export const FolderFocusKey = new RawContextKey<boolean>('folderMatchFocus', false);
export const MatchFocusKey = new RawContextKey<boolean>('matchFocus', false);
export const ViewHasSearchPatternKey = new RawContextKey<boolean>('viewHasSearchPattern', false);
export const ViewHasReplacePatternKey = new RawContextKey<boolean>('viewHasReplacePattern', false);
export const ViewHasFilePatternKey = new RawContextKey<boolean>('viewHasFilePattern', false);
export const ViewHasSomeCollapsibleKey = new RawContextKey<boolean>('viewHasSomeCollapsibleResult', false);
......@@ -16,6 +16,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { IFileService } from 'vs/platform/files/common/files';
import { IRange } from 'vs/editor/common/core/range';
import { isNumber } from 'vs/base/common/types';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
export interface IWorkspaceSymbol {
name: string;
......@@ -164,3 +165,11 @@ export function extractRangeFromFilter(filter: string, unless?: string[]): IFilt
return undefined;
}
export enum SearchUIState {
Idle,
Searching,
SlowSearch
}
export const SearchStateKey = new RawContextKey<SearchUIState>('searchState', SearchUIState.Idle);
......@@ -12,7 +12,7 @@ import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKe
import { localize } from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
......@@ -24,14 +24,15 @@ import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchCo
import { ActiveEditorContext, Extensions as EditorInputExtensions, IEditorInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
import { IViewsService } from 'vs/workbench/common/views';
import { getSearchView } from 'vs/workbench/contrib/search/browser/searchActions';
import { searchRefreshIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { searchNewEditorIcon, searchRefreshIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import * as SearchConstants from 'vs/workbench/contrib/search/common/constants';
import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants';
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
import { createEditorFromSearchResult, modifySearchEditorContextLinesCommand, openNewSearchEditor, selectAllSearchEditorMatchesCommand, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions';
import { createEditorFromSearchResult, modifySearchEditorContextLinesCommand, openNewSearchEditor, openSearchEditor, selectAllSearchEditorMatchesCommand, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions';
import { getOrMakeSearchEditorInput, SearchConfiguration, SearchEditorInput, SEARCH_EDITOR_EXT } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
import { parseSavedSearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { VIEW_ID } from 'vs/workbench/services/search/common/search';
const OpenInEditorCommandId = 'search.action.openInEditor';
......@@ -506,4 +507,25 @@ registerAction2(class extends Action2 {
selectAllSearchEditorMatchesCommand(accessor);
}
});
registerAction2(class OpenSearchEditorAction extends Action2 {
constructor() {
super({
id: SearchEditorConstants.OpenNewEditorCommandId,
title: localize('search.openNewEditor', "Open New Search Editor"),
category,
icon: searchNewEditorIcon,
f1: true,
menu: [{
id: MenuId.ViewTitle,
group: 'navigation',
order: 2,
when: ContextKeyEqualsExpr.create('view', VIEW_ID),
}]
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
return openSearchEditor(accessor);
}
});
//#endregion
......@@ -3,34 +3,29 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Action } from 'vs/base/common/actions';
import { Schemas } from 'vs/base/common/network';
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import 'vs/css!./media/searchEditor';
import { ICodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { EditorsOrder } from 'vs/workbench/common/editor';
import { IViewsService } from 'vs/workbench/common/views';
import { getSearchView } from 'vs/workbench/contrib/search/browser/searchActions';
import { SearchResult } from 'vs/workbench/contrib/search/common/searchModel';
import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor';
import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/searchEditor.contribution';
import { getOrMakeSearchEditorInput, SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput';
import { serializeSearchResultForEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization';
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
import { searchNewEditorIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { Schemas } from 'vs/base/common/network';
import { withNullAsUndefined, assertIsDefined } from 'vs/base/common/types';
import { OpenNewEditorCommandId } from 'vs/workbench/contrib/searchEditor/browser/constants';
import { OpenSearchEditorArgs } from 'vs/workbench/contrib/searchEditor/browser/searchEditor.contribution';
import { EditorsOrder } from 'vs/workbench/common/editor';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IViewsService } from 'vs/workbench/common/views';
import { getSearchView } from 'vs/workbench/contrib/search/browser/searchActions';
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
export const toggleSearchEditorCaseSensitiveCommand = (accessor: ServicesAccessor) => {
const editorService = accessor.get(IEditorService);
......@@ -80,41 +75,23 @@ export const selectAllSearchEditorMatchesCommand = (accessor: ServicesAccessor)
}
};
// Handler for the action bar entry in the search view.
export class OpenSearchEditorAction extends Action {
static readonly ID: string = OpenNewEditorCommandId;
static readonly LABEL = localize('search.openNewEditor', "Open New Search Editor");
constructor(id: string, label: string,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IViewsService private readonly viewsService: IViewsService,
) {
super(id, label, ThemeIcon.asClassName(searchNewEditorIcon));
}
update() {
// pass
}
get enabled(): boolean {
return true;
}
async run() {
const searchView = getSearchView(this.viewsService);
if (searchView) {
await this.instantiationService.invokeFunction(openNewSearchEditor, {
filesToInclude: searchView.searchIncludePattern.getValue(),
filesToExclude: searchView.searchExcludePattern.getValue(),
isRegexp: searchView.searchAndReplaceWidget.searchInput.getRegex(),
isCaseSensitive: searchView.searchAndReplaceWidget.searchInput.getCaseSensitive(),
matchWholeWord: searchView.searchAndReplaceWidget.searchInput.getWholeWords(),
useExcludeSettingsAndIgnoreFiles: searchView.searchExcludePattern.useExcludesAndIgnoreFiles(),
showIncludesExcludes: !!(searchView.searchIncludePattern.getValue() || searchView.searchExcludePattern.getValue() || !searchView.searchExcludePattern.useExcludesAndIgnoreFiles())
});
} else {
await this.instantiationService.invokeFunction(openNewSearchEditor);
}
export async function openSearchEditor(accessor: ServicesAccessor): Promise<void> {
const viewsService = accessor.get(IViewsService);
const searchView = getSearchView(viewsService);
if (searchView) {
const instantiationService = searchView.getInstantiationService();
await instantiationService.invokeFunction(openNewSearchEditor, {
filesToInclude: searchView.searchIncludePattern.getValue(),
filesToExclude: searchView.searchExcludePattern.getValue(),
isRegexp: searchView.searchAndReplaceWidget.searchInput.getRegex(),
isCaseSensitive: searchView.searchAndReplaceWidget.searchInput.getCaseSensitive(),
matchWholeWord: searchView.searchAndReplaceWidget.searchInput.getWholeWords(),
useExcludeSettingsAndIgnoreFiles: searchView.searchExcludePattern.useExcludesAndIgnoreFiles(),
showIncludesExcludes: !!(searchView.searchIncludePattern.getValue() || searchView.searchExcludePattern.getValue() || !searchView.searchExcludePattern.useExcludesAndIgnoreFiles())
});
} else {
const instantiationService = accessor.get(IInstantiationService);
await instantiationService.invokeFunction(openNewSearchEditor);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册