Skip to content

Commit 16c7361

Browse files
committed
feat(worktree): improve worktree subdirectory template and UI flow (#38)
- Replace `description` with `markdownDescription` for better rendering - Add support for `$REF_NAME` variable in worktree subdirectory template - Update localization files to include documentation for new variable - Adjust worktree creation flow to allow returning to branch selection - Add back button support in worktree directory input UI - Fix step numbering in quick pick UI during worktree creation - Modify `getSubDir` utility to accept and use `refName` in template substitution
1 parent 4ff9f93 commit 16c7361

8 files changed

Lines changed: 40 additions & 23 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@
952952
"default": "$BASE_NAME$INDEX",
953953
"pattern": "^[^/\\\\:*?\"<>|]+$",
954954
"patternErrorMessage": "%config.worktreeSubdirectoryTemplate.patternErrorMessage%",
955-
"description": "%config.worktreeSubdirectoryTemplate.description%"
955+
"markdownDescription": "%config.worktreeSubdirectoryTemplate.description%"
956956
},
957957
"git-worktree-manager.postCreateCmd": {
958958
"order": 13,

package.nls.ja.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"config.branchPick.showRenameBranch.description": "「ブランチを選択」の結果に「ブランチのリネーム」ボタンを表示",
102102
"config.treeView.toSCM.description": "ソース管理コンテナにビューを表示",
103103
"config.worktreePathTemplate.description": "ワークツリーパスのテンプレートです。使用可能な変数:$BASE_PATH(リポジトリのルート)",
104-
"config.worktreeSubdirectoryTemplate.description": "ワークツリーサブディレクトリ名のテンプレートです。使用可能な変数:$BASE_NAME(リポジトリフォルダ名)$INDEX(増分番号)。使用できない文字:/ \\ : * ? \" < > |",
104+
"config.worktreeSubdirectoryTemplate.description": "ワークツリーサブディレクトリ名のテンプレートです。使用可能な変数:\n\n- `$BASE_NAME`(リポジトリフォルダ名)\n- `$INDEX`(増分番号)。\n- `$REF_NAME` (参照名、ブランチ名やタグ名など)\n\n使用できない文字:/ \\ : * ? \" < > |",
105105
"config.worktreeSubdirectoryTemplate.patternErrorMessage": "テンプレートに次の文字は使用できません:/ \\ : * ? \" < > |",
106106
"config.postCreateCmd.description": "ワークツリー作成後に実行するコマンド。デフォルトでは、新しいワークツリーのディレクトリ内で実行されます。コマンドで使用できる変数:\n\n- `$BASE_PATH`:ワークツリーの完全パス\n- `$WORKTREE_PATH`:ワークツリーの完全パス\n- `$BASE_NAME`:ワークツリーのフォルダ名\n\n例:\n`git submodule update --init --recursive`",
107107
"config.worktreeDescriptionTemplate.description": "ワークツリーの説明テンプレートです。使用可能な変数:\n\n- `$FULL_PATH`:ワークツリーの完全パス\n- `$BASE_NAME`:ワークツリーのフォルダ名\n- `$RELATIVE_PATH`:相対パス(メインリポジトリのルートからの相対パス)",

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"config.branchPick.showRenameBranch.description": "Show the \"Rename Branch\" button on the results of \"Pick Branch\"",
102102
"config.treeView.toSCM.description": "Display views in the Source Control container",
103103
"config.worktreePathTemplate.description": "Template for the worktree path. Available variables: $BASE_PATH (repo root).",
104-
"config.worktreeSubdirectoryTemplate.description": "Template for worktree subdirectory names. Available variables: $BASE_NAME (repo folder name), $INDEX (incrementing number). Cannot contain characters: / \\ : * ? \" < > |",
104+
"config.worktreeSubdirectoryTemplate.description": "Template for worktree subdirectory names. Available variables:\n\n- `$BASE_NAME` (repo folder name)\n- `$INDEX` (incrementing number).\n- `$REF_NAME` (reference name, such as branch name, tag name)\n\nCannot contain characters: / \\ : * ? \" < > |",
105105
"config.worktreeSubdirectoryTemplate.patternErrorMessage": "Template cannot contain characters: / \\ : * ? \" < > |",
106106
"config.postCreateCmd.description": "Command to execute after creating a worktree. The default execution path is the directory of the newly created worktree. You can use the following variables in the command:\n\n- `$BASE_PATH`: The full path of the worktree.\n- `$WORKTREE_PATH`: The full path of the worktree.\n\nExample:\n`git submodule update --init --recursive`",
107107
"config.worktreeDescriptionTemplate.description": "Template for the worktree description. Available variables:\n\n- `$FULL_PATH`: The full path of the worktree.\n- `$BASE_NAME`: The folder name of the worktree.\n- `$RELATIVE_PATH`: The relative path (relative to the main repo directory).",

package.nls.zh-cn.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"config.branchPick.showRenameBranch.description": "\"挑选分支\" 列表中显示 \"重命名分支\" 按钮",
102102
"config.treeView.toSCM.description": "在源代码管理容器中显示视图",
103103
"config.worktreePathTemplate.description": "Worktree 路径的模板。可用的变量:$BASE_PATH(仓库根目录)",
104-
"config.worktreeSubdirectoryTemplate.description": "Worktree 子目录名称的模板。可用的变量:$BASE_NAME(仓库文件夹名称)$INDEX(递增数字)。不能包含字符:/ \\ : * ? \" < > |",
104+
"config.worktreeSubdirectoryTemplate.description": "Worktree 子目录名称的模板。可用的变量:\n\n- `$BASE_NAME`(仓库文件夹名称)\n- `$INDEX`(递增数字)。\n- `$REF_NAME` (引用名称,如分支名、标签名)\n\n不能包含字符:/ \\ : * ? \" < > |",
105105
"config.worktreeSubdirectoryTemplate.patternErrorMessage": "模板不能包含以下字符:/ \\ : * ? \" < > |",
106106
"config.postCreateCmd.description": "创建 Worktree 后执行的命令,默认执行路径是新创建的 Worktree 的目录内。你可以在命令中使用以下变量:\n\n- `$BASE_PATH`:仓库的完整路径。\n- `$WORKTREE_PATH`:Worktree 的完整路径。\n\n示例:\n`git submodule update --init --recursive`",
107107
"config.worktreeDescriptionTemplate.description": "Worktree 描述的模板。可用的变量:\n\n- `$FULL_PATH`:Worktree 的完整路径。\n- `$BASE_NAME`:Worktree 的文件夹名称。\n- `$RELATIVE_PATH`:相对路径(相对于主仓库目录)。",

package.nls.zh-tw.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"config.branchPick.showRenameBranch.description": "在「挑選分支」結果中顯示「重命名分支」按鈕",
102102
"config.treeView.toSCM.description": "在原始碼控制容器中顯示視圖",
103103
"config.worktreePathTemplate.description": "Worktree 路徑的模板。可用的變數:$BASE_PATH(倉庫根目錄)",
104-
"config.worktreeSubdirectoryTemplate.description": "Worktree 子目錄名稱的模板。可用的變數:$BASE_NAME(倉庫資料夾名稱)$INDEX(遞增數字)。不能包含字元:/ \\ : * ? \" < > |",
104+
"config.worktreeSubdirectoryTemplate.description": "Worktree 子目錄名稱的模板。可用的變數:\n\n- `$BASE_NAME`(倉庫資料夾名稱)\n- `$INDEX`(遞增數字)。\n- `$REF_NAME` (引用名稱,如分支名、標籤名)\n\n不能包含字元:/ \\ : * ? \" < > |",
105105
"config.worktreeSubdirectoryTemplate.patternErrorMessage": "範本不能包含以下字元:/ \\ : * ? \" < > |",
106106
"config.postCreateCmd.description": "建立 Worktree 後執行的命令。預設執行路徑是新建立的 Worktree 的目錄內。你可以在命令中使用以下變數:\n\n- `$BASE_PATH`:Worktree 的完整路徑。\n- `$WORKTREE_PATH`:Worktree 的完整路徑。\n\n範例:\n`git submodule update --init --recursive`",
107107
"config.worktreeDescriptionTemplate.description": "Worktree 描述的模板。可用的變數:\n\n- `$FULL_PATH`:Worktree 的完整路徑。\n- `$BASE_NAME`:Worktree 的資料夾名稱。\n- `$RELATIVE_PATH`:相對路徑(相對於主倉庫目錄)。",

src/core/command/addWorktreeCmd.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const pickBranchItem = async (dir: string, mainFolder: string) => {
1313
placeholder: vscode.l10n.t('Choose a branch to create a new worktree from'),
1414
mainFolder,
1515
cwd: dir,
16-
step: 2,
16+
step: 1,
1717
totalSteps: 2,
1818
showCreate: true,
1919
});
@@ -29,23 +29,32 @@ export const addWorktreeCmd = async (item?: IWorktreeLess) => {
2929
const mainFolder = await getMainFolder(gitFolder);
3030
if (!mainFolder) return false;
3131

32-
// 选择文件夹
33-
let folderPath = await inputWorktreeDir({ baseDir: mainFolder, step: 1, totalSteps: 2 });
34-
if (!folderPath) return;
35-
36-
// 选择ref
32+
// Select ref
3733
let branchItem = await pickBranchItem(gitFolder, mainFolder);
38-
// FIXME 改造quickPick
39-
// 没有选择ref时,返回选择文件夹
40-
while (branchItem === void 0) {
34+
if (!branchItem) return false;
35+
let refName = branchItem.branch || branchItem.hash;
36+
37+
// Select folder
38+
let folderPath = await inputWorktreeDir({
39+
baseDir: mainFolder,
40+
step: 2,
41+
totalSteps: 2,
42+
hasBackButton: true,
43+
refName,
44+
});
45+
while (folderPath === void 0) {
46+
// If no folder is selected, return to selecting ref
47+
branchItem = await pickBranchItem(gitFolder, mainFolder);
48+
if (!branchItem) return false;
49+
refName = branchItem.branch || branchItem.hash;
4150
folderPath = await inputWorktreeDir({
4251
baseDir: mainFolder,
4352
baseWorktreeDir: folderPath,
44-
step: 1,
53+
step: 2,
4554
totalSteps: 2,
55+
hasBackButton: true,
56+
refName,
4657
});
47-
if (!folderPath) return;
48-
branchItem = await pickBranchItem(gitFolder, mainFolder);
4958
}
5059

5160
if (!branchItem) return false;

src/core/ui/inputWorktreeDir.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,25 @@ interface InputWorktreeDirOptions {
3131
step?: number;
3232
totalSteps?: number;
3333
targetDirTip?: string;
34+
hasBackButton?: boolean;
35+
refName?: string;
3436
}
3537
export const inputWorktreeDir = async ({
3638
baseDir,
3739
baseWorktreeDir,
3840
step,
3941
totalSteps,
42+
hasBackButton,
4043
targetDirTip = vscode.l10n.t('Select the folder where you want to create the worktree'),
44+
refName = '',
4145
}: InputWorktreeDirOptions) => {
4246
let canClose = true;
4347
const { promise, resolve, reject } = withResolvers<string | undefined>();
4448
// Final path
4549
const workTreeDir = getBaseWorktreeDir(baseDir);
4650
const baseName = path.basename(baseDir);
47-
const dirReg = new RegExp(getSubDir(baseName, '(\\d+)'));
48-
let finalWorktreeDir = path.join(workTreeDir, getSubDir(baseName, 1));
51+
const dirReg = new RegExp(getSubDir(baseName, refName, '(\\d+)'));
52+
let finalWorktreeDir = path.join(workTreeDir, getSubDir(baseName, refName, 1));
4953
const inputBox = vscode.window.createInputBox();
5054
// When the passed baseWorktreeDir has a value and is different from workTreeDir, it indicates switching from a previously selected worktree
5155
if (baseWorktreeDir && !comparePath(workTreeDir, baseWorktreeDir)) {
@@ -58,7 +62,7 @@ export const inputWorktreeDir = async ({
5862
if (worktreeDirList.length) {
5963
worktreeDirList.sort((a, b) => Number(b.replace(dirReg, '$1')) - Number(a.replace(dirReg, '$1')));
6064
const index = worktreeDirList[0].match(dirReg)![1];
61-
finalWorktreeDir = path.join(workTreeDir, getSubDir(baseName, Number(index) + 1));
65+
finalWorktreeDir = path.join(workTreeDir, getSubDir(baseName, refName, Number(index) + 1));
6266
}
6367
}
6468
const selectDirBtn: vscode.QuickInputButton = {
@@ -68,10 +72,14 @@ export const inputWorktreeDir = async ({
6872
inputBox.title = vscode.l10n.t('Enter worktree directory');
6973
inputBox.value = finalWorktreeDir;
7074
inputBox.valueSelection = [workTreeDir.length + 1, finalWorktreeDir.length];
71-
inputBox.buttons = [selectDirBtn];
75+
inputBox.buttons = hasBackButton ? [selectDirBtn, vscode.QuickInputButtons.Back] : [selectDirBtn];
7276
inputBox.step = step;
7377
inputBox.totalSteps = totalSteps;
7478
const handleTriggerButton = async (event: vscode.QuickInputButton) => {
79+
if (event === vscode.QuickInputButtons.Back) {
80+
resolve(undefined);
81+
inputBox.dispose();
82+
}
7583
if (event !== selectDirBtn) return;
7684
canClose = false;
7785
inputBox.hide();

src/core/util/folder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const validateSubdirectoryTemplate = (template: string): boolean => {
5353
};
5454

5555
// get worktree subdirectory name with baseName and index
56-
export const getSubDir = (baseName: string, index: string | number) => {
56+
export const getSubDir = (baseName: string, refName: string, index: string | number) => {
5757
const template = Config.get('worktreeSubdirectoryTemplate', '$BASE_NAME$INDEX');
5858

5959
// Validate template
@@ -62,7 +62,7 @@ export const getSubDir = (baseName: string, index: string | number) => {
6262
return `worktree${String(index)}`;
6363
}
6464

65-
return template.replace('$BASE_NAME', baseName).replace('$INDEX', String(index));
65+
return template.replace('$BASE_NAME', baseName).replace('$REF_NAME', refName).replace('$INDEX', String(index));
6666
};
6767

6868
export const getBaseBundleDir = (baseDir: string) => `${baseDir}.repoBackup`;

0 commit comments

Comments
 (0)