提交 c8a6ce93 编写于 作者: R Rob Lourens

Fix #42120 - Implement Copy

上级 1dcb420e
...@@ -18,7 +18,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi ...@@ -18,7 +18,7 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
import { ResolvedKeybinding, createKeybinding } from 'vs/base/common/keyCodes'; import { ResolvedKeybinding, createKeybinding } from 'vs/base/common/keyCodes';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { OS } from 'vs/base/common/platform'; import { OS, isWindows } from 'vs/base/common/platform';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { VIEW_ID } from 'vs/platform/search/common/search'; import { VIEW_ID } from 'vs/platform/search/common/search';
...@@ -635,10 +635,62 @@ export class ReplaceAction extends AbstractSearchAndReplaceAction { ...@@ -635,10 +635,62 @@ export class ReplaceAction extends AbstractSearchAndReplaceAction {
} }
} }
function fileMatchUriToString(fileMatch: FileMatch): string {
const resource = fileMatch.resource();
return resource.scheme === Schemas.file ? getPathLabel(resource) : resource.toString();
}
export const copyPathCommand: ICommandHandler = (accessor, fileMatch: FileMatch) => { export const copyPathCommand: ICommandHandler = (accessor, fileMatch: FileMatch) => {
const clipboardService = accessor.get(IClipboardService); const clipboardService = accessor.get(IClipboardService);
const resource = fileMatch.resource(); const text = fileMatchUriToString(fileMatch);
const text = resource.scheme === Schemas.file ? getPathLabel(resource) : resource.toString();
clipboardService.writeText(text); clipboardService.writeText(text);
}; };
function matchToString(match: Match): string {
return `${match.range().startLineNumber},${match.range().startColumn}: ${match.text()}`;
}
const lineDelimiter = isWindows ? '\r\n' : '\n';
function fileMatchToString(fileMatch: FileMatch, maxMatches: number): { text: string, count: number } {
const matchTextRows = fileMatch.matches()
.slice(0, maxMatches)
.map(matchToString)
.map(matchText => ' ' + matchText);
return {
text: `${fileMatchUriToString(fileMatch)}${lineDelimiter}${matchTextRows.join(lineDelimiter)}`,
count: matchTextRows.length
};
}
function folderMatchToString(folderMatch: FolderMatch, maxMatches: number): string {
const fileResults: string[] = [];
let numMatches = 0;
for (let i = 0; i < folderMatch.fileCount() && numMatches < maxMatches; i++) {
const fileResult = fileMatchToString(folderMatch.matches()[i], maxMatches - numMatches);
numMatches += fileResult.count;
fileResults.push(fileResult.text);
}
return fileResults.join(lineDelimiter + lineDelimiter);
}
const maxClipboardMatches = 1e4;
export const copyMatchCommand: ICommandHandler = (accessor, match: RenderableMatch) => {
const clipboardService = accessor.get(IClipboardService);
let text: string;
if (match instanceof Match) {
text = matchToString(match);
} else if (match instanceof FileMatch) {
text = fileMatchToString(match, maxClipboardMatches).text;
} else if (match instanceof FolderMatch) {
text = folderMatchToString(match, maxClipboardMatches);
}
if (text) {
clipboardService.writeText(text);
}
};
...@@ -53,7 +53,7 @@ import { getMultiSelectedResources } from 'vs/workbench/parts/files/browser/file ...@@ -53,7 +53,7 @@ import { getMultiSelectedResources } from 'vs/workbench/parts/files/browser/file
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand } from 'vs/workbench/parts/search/browser/searchActions'; import { openSearchView, getSearchView, ReplaceAllInFolderAction, ReplaceAllAction, CloseReplaceAction, FocusNextInputAction, FocusPreviousInputAction, FocusNextSearchResultAction, FocusPreviousSearchResultAction, ReplaceInFilesAction, FindInFilesAction, FocusActiveEditorCommand, toggleCaseSensitiveCommand, ShowNextSearchTermAction, ShowPreviousSearchTermAction, toggleRegexCommand, ShowPreviousSearchIncludeAction, ShowNextSearchIncludeAction, CollapseDeepestExpandedLevelAction, toggleWholeWordCommand, RemoveAction, ReplaceAction, ClearSearchResultsAction, copyPathCommand, copyMatchCommand } from 'vs/workbench/parts/search/browser/searchActions';
import { VIEW_ID, ISearchConfigurationProperties } from 'vs/platform/search/common/search'; import { VIEW_ID, ISearchConfigurationProperties } from 'vs/platform/search/common/search';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
...@@ -235,6 +235,24 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, { ...@@ -235,6 +235,24 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, {
order: 2 order: 2
}); });
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: Constants.CopyMatchCommandId,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: Constants.FileMatchOrMatchFocusKey,
primary: KeyMod.CtrlCmd | KeyCode.KEY_C,
handler: copyMatchCommand
});
MenuRegistry.appendMenuItem(MenuId.SearchContext, {
command: {
id: Constants.CopyMatchCommandId,
title: nls.localize('copyMatchLabel', "Copy")
},
when: Constants.FileMatchOrMatchFocusKey,
group: 'search_2',
order: 3
});
KeybindingsRegistry.registerCommandAndKeybindingRule({ KeybindingsRegistry.registerCommandAndKeybindingRule({
id: Constants.CopyPathCommandId, id: Constants.CopyPathCommandId,
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
...@@ -252,8 +270,8 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, { ...@@ -252,8 +270,8 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, {
title: nls.localize('copyPathLabel', "Copy Path") title: nls.localize('copyPathLabel', "Copy Path")
}, },
when: Constants.FileFocusKey, when: Constants.FileFocusKey,
group: 'search', group: 'search_2',
order: 3 order: 4
}); });
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
...@@ -274,7 +292,7 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, { ...@@ -274,7 +292,7 @@ MenuRegistry.appendMenuItem(MenuId.SearchContext, {
title: toggleSearchViewPositionLabel title: toggleSearchViewPositionLabel
}, },
when: Constants.SearchViewVisibleKey, when: Constants.SearchViewVisibleKey,
group: 'search_2', group: 'search_9',
order: 1 order: 1
}); });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册