feat(vscode): PyCharm 启动命令可配置(支持 ~/绝对路径),抽 expandTilde 复用

GUI 启动的 VS Code 扩展进程 PATH 常不含 JetBrains 启动器,裸 pycharm 易 ENOENT。
新增设置 pycharmCommand(默认 pycharm),贯穿 store/settings handler/messages/
KanbanPanel 与 webview,「钩子」分组在选 PyCharm 时显示「PyCharm 启动命令」输入框。
handleOpenWorktree 用该命令并经 expandTilde 展开 ~。expandTilde 从 resolveWorktreePath
抽出共用。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 05:29:19 +08:00
co-authored by Claude Opus 4.7
parent cacc60eb0e
commit 02b0aca891
10 changed files with 84 additions and 9 deletions
@@ -25,6 +25,7 @@ interface SubmitValues {
autoBuildBranch: string
worktreeDirectory: string
worktreeOpenWith: 'vscode' | 'pycharm'
pycharmCommand: string
worktreePostCreateScript: string
worktreePreRemoveScript: string
implTabPreCreateScript: string
@@ -63,6 +64,7 @@ export interface SettingsModalProps {
initialAutoBuildBranch: string
initialWorktreeDirectory: string
initialWorktreeOpenWith: 'vscode' | 'pycharm'
initialPycharmCommand: string
initialWorktreePostCreateScript: string
initialWorktreePreRemoveScript: string
initialImplTabPreCreateScript: string
@@ -134,6 +136,7 @@ export function SettingsModal({
initialAutoBuildBranch,
initialWorktreeDirectory,
initialWorktreeOpenWith,
initialPycharmCommand,
initialWorktreePostCreateScript,
initialWorktreePreRemoveScript,
initialImplTabPreCreateScript,
@@ -159,6 +162,7 @@ export function SettingsModal({
const [autoBuildBranch, setAutoBuildBranch] = useState(initialAutoBuildBranch)
const [worktreeDirectory, setWorktreeDirectory] = useState(initialWorktreeDirectory)
const [worktreeOpenWith, setWorktreeOpenWith] = useState(initialWorktreeOpenWith)
const [pycharmCommand, setPycharmCommand] = useState(initialPycharmCommand)
const [worktreePostCreateScript, setWorktreePostCreateScript] = useState(initialWorktreePostCreateScript)
const [worktreePreRemoveScript, setWorktreePreRemoveScript] = useState(initialWorktreePreRemoveScript)
const [implTabPreCreateScript, setImplTabPreCreateScript] = useState(initialImplTabPreCreateScript)
@@ -263,6 +267,8 @@ export function SettingsModal({
// worktree 目录模板:trim 后留空 = 用默认模板(getSettings 读时回退)
worktreeDirectory: worktreeDirectory.trim(),
worktreeOpenWith,
// pycharm 启动命令:trim 后留空 = 用默认 `pycharm`getSettings 读时回退)
pycharmCommand: pycharmCommand.trim(),
// 钩子路径保持原样 trim(前后空格无意义;空串 = 用默认 .spx/*.sh
worktreePostCreateScript: worktreePostCreateScript.trim(),
worktreePreRemoveScript: worktreePreRemoveScript.trim(),
@@ -669,6 +675,35 @@ export function SettingsModal({
</select>
</Field>
{worktreeOpenWith === 'pycharm' && (
<Field
label="PyCharm 启动命令"
hint={(
<>
{' '}
<code>~</code>
{' '}
{' '}
<code>~/.local/share/JetBrains/Toolbox/scripts/pycharm</code>
GUI VS Code
{' '}
<code>pycharm</code>
</>
)}
>
<input
type="text"
value={pycharmCommand}
onChange={e => setPycharmCommand(e.target.value)}
placeholder="pycharm"
className={inputClass}
/>
</Field>
)}
<Field
label="worktree 创建后脚本"
hint={(