✨ feat(vscode): 代码阅读侧栏右键菜单加「在 Finder 中显示」,按系统换成文件资源管理器 / 打开所在的文件夹
This commit is contained in:
1 parent
430f98ade4
commit
5ce2e904f4
5 files changed
+121
-3
No files matched your search
@@ -189,6 +189,21 @@
|
||||
"title": "复制绝对路径",
|
||||
"category": "代码阅读"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFinder",
|
||||
"title": "在 Finder 中显示",
|
||||
"category": "代码阅读"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFileExplorer",
|
||||
"title": "在文件资源管理器中显示",
|
||||
"category": "代码阅读"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.openContainingFolder",
|
||||
"title": "打开所在的文件夹",
|
||||
"category": "代码阅读"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.addNote",
|
||||
"title": "添加注释",
|
||||
@@ -365,6 +380,21 @@
|
||||
"when": "view == superpowers.codeReader.files && viewItem =~ /^(file( unstaged)?|folder)( noted)?$/",
|
||||
"group": "copy@4"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFinder",
|
||||
"when": "view == superpowers.codeReader.files && isMac && viewItem =~ /^(file( unstaged)?|folder)( noted)?$/",
|
||||
"group": "fileManager"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFileExplorer",
|
||||
"when": "view == superpowers.codeReader.files && isWindows && viewItem =~ /^(file( unstaged)?|folder)( noted)?$/",
|
||||
"group": "fileManager"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.openContainingFolder",
|
||||
"when": "view == superpowers.codeReader.files && isLinux && viewItem =~ /^(file( unstaged)?|folder)( noted)?$/",
|
||||
"group": "fileManager"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.addNote",
|
||||
"when": "view == superpowers.codeReader.files && superpowers.codeReader.filter != review && viewItem =~ /^(file( unstaged)?|folder)$/",
|
||||
@@ -445,6 +475,18 @@
|
||||
"command": "superpowers.codeReader.copyAbsolutePath",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFinder",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.revealInFileExplorer",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.openContainingFolder",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "superpowers.codeReader.addNote",
|
||||
"when": "false"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { FileNode } from './fileTree'
|
||||
import { commands, Disposable } from 'vscode'
|
||||
|
||||
/**
|
||||
* 在系统的文件管理器里显示这一行,菜单上的字跟 VS Code 自带资源管理器一样按系统叫:
|
||||
* macOS「在 Finder 中显示」、Windows「在文件资源管理器中显示」、Linux「打开所在的文件夹」。
|
||||
* 做的事一样,分成三个命令只为菜单上写对字(package.json 按 `isMac` / `isWindows` / `isLinux` 挑)。
|
||||
*/
|
||||
const REVEAL_COMMANDS = [
|
||||
'superpowers.codeReader.revealInFinder',
|
||||
'superpowers.codeReader.revealInFileExplorer',
|
||||
'superpowers.codeReader.openContainingFolder',
|
||||
]
|
||||
|
||||
/** 交给 VS Code 自带的 `revealFileInOS`:文件是打开所在文件夹并选中它,文件夹是在上一层里选中它。 */
|
||||
async function revealInOS(node: FileNode | undefined): Promise<void> {
|
||||
if (!node)
|
||||
return // 只挂在侧栏的行上,别处调用没有目标
|
||||
await commands.executeCommand('revealFileInOS', node.uri)
|
||||
}
|
||||
|
||||
export function registerRevealCommands(): Disposable {
|
||||
return Disposable.from(...REVEAL_COMMANDS.map(id => commands.registerCommand(id, revealInOS)))
|
||||
}
|
||||
@@ -73,7 +73,7 @@ describe('侧栏行尾按钮', () => {
|
||||
})
|
||||
|
||||
it('分组行(「暂存的更改」「更改」)什么按钮、菜单都没有', () => {
|
||||
for (const group of ['inline', 'copy', 'notes'])
|
||||
for (const group of ['inline', 'copy', 'fileManager', 'notes'])
|
||||
expect(itemsFor('view/item/context', group, GROUP_CONTEXT)).toEqual([])
|
||||
expect(itemsFor(COPY_MENU, 'copy', GROUP_CONTEXT)).toEqual([])
|
||||
})
|
||||
@@ -136,6 +136,48 @@ describe('右键菜单的注释', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('右键菜单的「在系统文件管理器中显示」', () => {
|
||||
/** 菜单上的字跟着系统走,和 VS Code 自带资源管理器一样 */
|
||||
const REVEALS = [
|
||||
{ platform: 'isMac', command: 'superpowers.codeReader.revealInFinder', title: '在 Finder 中显示' },
|
||||
{ platform: 'isWindows', command: 'superpowers.codeReader.revealInFileExplorer', title: '在文件资源管理器中显示' },
|
||||
{ platform: 'isLinux', command: 'superpowers.codeReader.openContainingFolder', title: '打开所在的文件夹' },
|
||||
]
|
||||
const REVEAL_IDS = REVEALS.map(item => item.command)
|
||||
const whenOf = (command: string): string | undefined => menus['view/item/context'].find(item => item.command === command)?.when
|
||||
|
||||
it('文件、文件夹(含未提交、有注释)都有,工作区根没有;审查时也不藏', () => {
|
||||
for (const context of [file, folder, unstaged, noted(file), noted(folder), noted(unstaged)])
|
||||
expect(itemsFor('view/item/context', 'fileManager', context)).toEqual(REVEAL_IDS)
|
||||
expect(itemsFor('view/item/context', 'fileManager', root)).toEqual([])
|
||||
expect(REVEAL_IDS.some(id => whenOf(id)?.includes('filter'))).toBe(false)
|
||||
})
|
||||
|
||||
it('每个系统只出自己那一项,字和 VS Code 自带的一样', () => {
|
||||
for (const { platform, command, title } of REVEALS) {
|
||||
const when = whenOf(command)
|
||||
expect(when).toContain(`&& ${platform} &&`)
|
||||
for (const other of REVEALS.filter(item => item.platform !== platform))
|
||||
expect(when).not.toContain(other.platform)
|
||||
expect(commands.find(item => item.command === command)?.title).toBe(title)
|
||||
}
|
||||
})
|
||||
|
||||
it('自成一组,排在复制后面、注释前面(VS Code 按组名的字母序排组,组和组之间画分隔线)', () => {
|
||||
const groups = menus['view/item/context']
|
||||
.filter(item => item.when.includes('view == superpowers.codeReader.files') && item.group !== undefined && !item.group.startsWith('inline'))
|
||||
.map(item => item.group!.split('@')[0])
|
||||
expect([...new Set(groups)].sort((a, b) => a.localeCompare(b))).toEqual(['copy', 'fileManager', 'notes'])
|
||||
})
|
||||
|
||||
it('只在右键菜单里,不挂行尾按钮,命令面板里藏起来', () => {
|
||||
for (const id of REVEAL_IDS) {
|
||||
expect(menus['view/item/context'].filter(item => item.command === id)).toHaveLength(1)
|
||||
expect(menus.commandPalette.find(item => item.command === id)?.when).toBe('false')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('筛选(审查工单、未提交的更改)', () => {
|
||||
const FILTER = 'superpowers.codeReader.filter'
|
||||
const PICK = 'superpowers.codeReader.pickReviewIssue'
|
||||
|
||||
@@ -17,6 +17,7 @@ import { WorkspaceEntries } from './entries/workspaceEntries'
|
||||
import { registerCopyCommands } from './explorer/copyCommands'
|
||||
import { FileTreeProvider } from './explorer/fileTree'
|
||||
import { registerPathAsk } from './explorer/pathAskPanel'
|
||||
import { registerRevealCommands } from './explorer/revealCommands'
|
||||
import { RowDecorator } from './explorer/rowDecorator'
|
||||
import { TreeFilters } from './explorer/treeFilters'
|
||||
import { TreeLocator } from './explorer/treeLocator'
|
||||
@@ -71,7 +72,7 @@ async function openFile(uri: Uri, registry: CodeReaderRegistry): Promise<void> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 接入代码阅读:注册表、侧栏文件树(问路径、复制、文件注释、筛选:按审查工单只看 PR 改过的文件、只看未提交的更改)、预览编辑器(含问 AI)、编辑器右上角的「预览 / 编辑」切换。
|
||||
* 接入代码阅读:注册表、侧栏文件树(问路径、复制、在系统文件管理器里显示、文件注释、筛选:按审查工单只看 PR 改过的文件、只看未提交的更改)、预览编辑器(含问 AI)、编辑器右上角的「预览 / 编辑」切换。
|
||||
* 内置的语言插件、翻译插件、库规则和命令规则与其他扩展一样通过返回的 API 注册。
|
||||
*/
|
||||
export function registerCodeReader(context: ExtensionContext): CodeReaderApi {
|
||||
@@ -108,6 +109,7 @@ export function registerCodeReader(context: ExtensionContext): CodeReaderApi {
|
||||
indexes,
|
||||
registerNoteCommands(notes),
|
||||
registerCopyCommands(),
|
||||
registerRevealCommands(),
|
||||
registerPathAsk(
|
||||
async (uri) => {
|
||||
const languageId = await languageOf(uri)
|
||||
|
||||
Reference in new issue
Block a user