Skip to content

Commit

Permalink
Fix #31496 - add new actions, "Find in Files With Selected Text" whic…
Browse files Browse the repository at this point in the history
…h are bound to editorFocus, to prevent the search viewlet from ever taking the editor text unless the editor is focused
  • Loading branch information
roblourens authored and egamma committed Oct 31, 2017
1 parent 1f5610a commit f228fef
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 19 deletions.
16 changes: 11 additions & 5 deletions src/vs/workbench/parts/search/browser/search.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import nls = require('vs/nls');
import { TPromise } from 'vs/base/common/winjs.base';
import { IAction, Action } from 'vs/base/common/actions';
import * as objects from 'vs/base/common/objects';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { explorerItemToFileResource } from 'vs/workbench/parts/files/common/files';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
Expand Down Expand Up @@ -262,10 +263,17 @@ Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new Vie
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
const category = nls.localize('search', "Search");

registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.OpenSearchViewletAction, Constants.VIEWLET_ID, nls.localize('showSearchViewlet', "Show Search"), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F },
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.OpenSearchViewletAction, Constants.VIEWLET_ID, searchActions.OpenSearchViewletAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F },
Constants.SearchViewletVisibleKey.toNegated()), 'View: Show Search', nls.localize('view', "View"));
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FindInFilesAction, Constants.FindInFilesActionId, nls.localize('findInFiles', "Find in Files"), { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F },
Constants.SearchInputBoxFocusedKey.toNegated()), 'Find in Files', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FindInFilesAction, Constants.FindInFilesActionId, searchActions.FindInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F },
ContextKeyExpr.and(Constants.SearchInputBoxFocusedKey.toNegated(), EditorContextKeys.focus.toNegated())), 'Find in Files', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ReplaceInFilesAction, searchActions.ReplaceInFilesAction.ID, searchActions.ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H },
EditorContextKeys.focus.toNegated()), 'Replace in Files', category);

registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FindInFilesWithSelectedTextAction, searchActions.FindInFilesWithSelectedTextAction.ID, searchActions.FindInFilesWithSelectedTextAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F },
EditorContextKeys.focus), 'Find in Files With Selected Text', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ReplaceInFilesWithSelectedTextAction, searchActions.ReplaceInFilesWithSelectedTextAction.ID, searchActions.ReplaceInFilesWithSelectedTextAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H },
EditorContextKeys.focus), 'Replace in Files With Selected Text', category);

KeybindingsRegistry.registerCommandAndKeybindingRule({
id: Constants.FocusActiveEditorCommandId,
Expand All @@ -278,8 +286,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusNextSearchResultAction, searchActions.FocusNextSearchResultAction.ID, searchActions.FocusNextSearchResultAction.LABEL, { primary: KeyCode.F4 }), 'Focus Next Search Result', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusPreviousSearchResultAction, searchActions.FocusPreviousSearchResultAction.ID, searchActions.FocusPreviousSearchResultAction.LABEL, { primary: KeyMod.Shift | KeyCode.F4 }), 'Focus Previous Search Result', category);

registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ReplaceInFilesAction, searchActions.ReplaceInFilesAction.ID, searchActions.ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H }), 'Replace in Files', category);

KeybindingsRegistry.registerCommandAndKeybindingRule(objects.assign({
id: Constants.ToggleCaseSensitiveCommandId,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
Expand Down
67 changes: 61 additions & 6 deletions src/vs/workbench/parts/search/browser/searchActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ export class FocusPreviousInputAction extends Action {

export class OpenSearchViewletAction extends ToggleViewletAction {

public static LABEL = nls.localize('showSearchViewlet', "Show Search");

constructor(id: string, label: string, @IViewletService viewletService: IViewletService, @IWorkbenchEditorService editorService: IWorkbenchEditorService) {
super(id, label, Constants.VIEWLET_ID, viewletService, editorService);
}
Expand Down Expand Up @@ -255,30 +257,64 @@ export const FocusActiveEditorCommand = (accessor: ServicesAccessor) => {
return TPromise.as(true);
};

export interface IFindOrReplaceActionOpts {
selectWidgetText: boolean;
focusReplace: boolean;
expandSearchReplaceWidget: boolean;
takeEditorText?: boolean;
}

export abstract class FindOrReplaceInFilesAction extends Action {

constructor(id: string, label: string, private viewletService: IViewletService,
private expandSearchReplaceWidget: boolean, private selectWidgetText: boolean, private focusReplace: boolean) {
private options: IFindOrReplaceActionOpts) {
super(id, label);
}

public run(): TPromise<any> {
const viewlet = this.viewletService.getActiveViewlet();
const searchViewletWasOpen = viewlet && viewlet.getId() === Constants.VIEWLET_ID;
return this.viewletService.openViewlet(Constants.VIEWLET_ID, true).then((viewlet) => {
if (!searchViewletWasOpen || this.expandSearchReplaceWidget) {
if (this.options.takeEditorText) {
(<SearchViewlet>viewlet).takeEditorText();
}

if (!searchViewletWasOpen || this.options.expandSearchReplaceWidget) {
const searchAndReplaceWidget = (<SearchViewlet>viewlet).searchAndReplaceWidget;
searchAndReplaceWidget.toggleReplace(this.expandSearchReplaceWidget);
searchAndReplaceWidget.focus(this.selectWidgetText, this.focusReplace);
searchAndReplaceWidget.toggleReplace(this.options.expandSearchReplaceWidget);
searchAndReplaceWidget.focus(this.options.selectWidgetText, this.options.focusReplace);
}

return viewlet;
});
}
}

export class FindInFilesAction extends FindOrReplaceInFilesAction {

public static LABEL = nls.localize('findInFiles', "Find in Files");

constructor(id: string, label: string, @IViewletService viewletService: IViewletService) {
super(id, label, viewletService, /*expandSearchReplaceWidget=*/false, /*selectWidgetText=*/true, /*focusReplace=*/false);
super(id, label, viewletService, {
expandSearchReplaceWidget: false,
selectWidgetText: true,
focusReplace: false
});
}
}

export class FindInFilesWithSelectedTextAction extends FindOrReplaceInFilesAction {

public static ID = 'workbench.action.findInFilesWithSelectedText';
public static LABEL = nls.localize('findInFilesWithSelectedText', "Find in Files With Selected Text");

constructor(id: string, label: string, @IViewletService viewletService: IViewletService) {
super(id, label, viewletService, {
expandSearchReplaceWidget: false,
selectWidgetText: true,
focusReplace: false,
takeEditorText: true
});
}
}

Expand All @@ -288,7 +324,26 @@ export class ReplaceInFilesAction extends FindOrReplaceInFilesAction {
public static LABEL = nls.localize('replaceInFiles', "Replace in Files");

constructor(id: string, label: string, @IViewletService viewletService: IViewletService) {
super(id, label, viewletService, /*expandSearchReplaceWidget=*/true, /*selectWidgetText=*/false, /*focusReplace=*/true);
super(id, label, viewletService, {
expandSearchReplaceWidget: true,
selectWidgetText: false,
focusReplace: true
});
}
}

export class ReplaceInFilesWithSelectedTextAction extends FindOrReplaceInFilesAction {

public static ID = 'workbench.action.replaceInFilesWithSelectedText';
public static LABEL = nls.localize('replaceInFilesWithSelectedText', "Replace in Files With Selected Text");

constructor(id: string, label: string, @IViewletService viewletService: IViewletService) {
super(id, label, viewletService, {
expandSearchReplaceWidget: true,
selectWidgetText: false,
focusReplace: true,
takeEditorText: true
});
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/vs/workbench/parts/search/browser/searchViewlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,17 +655,16 @@ export class SearchViewlet extends Viewlet {
public focus(): void {
super.focus();

// If focus is inside the search viewlet, don't add the selected text to the search widget
if (!(document.activeElement.compareDocumentPosition(this.domNode.getHTMLElement()) & Node.DOCUMENT_POSITION_CONTAINS)) {
const selectedText = this.getSearchTextFromEditor();
if (selectedText) {
this.searchWidget.searchInput.setValue(selectedText);
}
}

this.searchWidget.focus();
}

public takeEditorText(): void {
const selectedText = this.getSearchTextFromEditor();
if (selectedText) {
this.searchWidget.searchInput.setValue(selectedText);
}
}

public focusNextInputBox(): void {
if (this.searchWidget.searchInputHasFocus()) {
if (this.searchWidget.isReplaceShown()) {
Expand Down

0 comments on commit f228fef

Please sign in to comment.