Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new :FudeEditPR user command to edit an existing GitHub PR’s title/body from Neovim, reusing the existing two-pane PR float UI and integrating with gh pr view / gh pr edit.
Changes:
- Added
FudeEditPRcommand entrypoint andpr.edit()flow to load current PR content and submit updates. - Refactored
open_pr_float()to accept anoptstable (mode/footer/on_submit) so the same UI can support both create and edit. - Added
gh.get_pr_title_body()/gh.edit_pr()and corresponding tests + help docs.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/fude/pr_spec.lua | Adds test coverage for pr.edit() behavior and submit handling. |
| plugin/fude.lua | Registers new :FudeEditPR user command. |
| lua/fude/pr.lua | Refactors PR float to accept opts; adds M.edit() implementation using new gh helpers. |
| lua/fude/gh.lua | Adds gh wrappers to read PR title/body and edit PR content. |
| doc/fude.txt | Documents :FudeEditPR usage and keybindings. |
| CLAUDE.md | Updates module documentation to include PR editing capability. |
lua/fude/gh.lua
Outdated
| local args = { "pr", "view", "--json", "title,body" } | ||
| if pr_number then | ||
| table.insert(args, 3, tostring(pr_number)) | ||
| end | ||
| M.run_json(args, function(err, data) | ||
| if err then | ||
| return callback(err, nil) | ||
| end | ||
| callback(nil, { title = data.title or "", body = data.body or "" }) |
There was a problem hiding this comment.
pr_number == nil の場合に gh pr view を直接呼んでいますが、このリポジトリでは get_pr_info() 内で「detached HEAD だと gh pr view がハングする可能性がある」ために回避実装があります。編集機能でも同様の状況でハングし得るので、(1) get_pr_info() 相当の detached HEAD 検出を入れる、または (2) 先に PR number を解決してから pr view <number> を呼ぶ等、ハング回避の経路に寄せてください。
There was a problem hiding this comment.
dc5e351 で修正 — get_pr_title_body に detached HEAD 検出を追加し、M.edit() では get_pr_info で PR 番号を先に解決してから get_pr_title_body / edit_pr 両方に渡す方式にしました。
lua/fude/pr.lua
Outdated
| close_all() | ||
|
|
||
| -- Use custom submit handler if provided | ||
| if opts.on_submit then | ||
| opts.on_submit(parsed.title, parsed.body) | ||
| return | ||
| end | ||
|
|
||
| -- Default: create draft PR |
There was a problem hiding this comment.
submit() で close_all() を opts.on_submit 実行前に呼んでいるため、編集モードでは更新に失敗した場合でもフロートが閉じてしまい、ユーザーの入力内容をその場で再試行できません(下書き保存もされません)。mode == "edit" のときは成功後に閉じる/失敗時は閉じない、または失敗時に内容を退避(ドラフト保存等)するなど、エラー時の復旧手段を用意してください。
| close_all() | |
| -- Use custom submit handler if provided | |
| if opts.on_submit then | |
| opts.on_submit(parsed.title, parsed.body) | |
| return | |
| end | |
| -- Default: create draft PR | |
| -- Use custom submit handler if provided | |
| if opts.on_submit then | |
| -- 編集モードでは on_submit が成功した場合のみフロートを閉じる。 | |
| -- エラー時にはフロートを閉じず、ユーザーの入力内容をそのまま残す。 | |
| if mode == "edit" then | |
| local ok, err = pcall(opts.on_submit, parsed.title, parsed.body) | |
| if ok then | |
| close_all() | |
| else | |
| vim.notify( | |
| "fude.nvim: Failed to update PR: " .. tostring(err), | |
| vim.log.levels.ERROR | |
| ) | |
| end | |
| else | |
| -- 従来どおり、編集モード以外では先にフロートを閉じてからハンドラを呼び出す。 | |
| close_all() | |
| opts.on_submit(parsed.title, parsed.body) | |
| end | |
| return | |
| end | |
| -- Default: create draft PR | |
| -- 既存の挙動を維持するため、デフォルト経路では事前にフロートを閉じる。 | |
| close_all() |
There was a problem hiding this comment.
dc5e351 で修正 — edit モードでは close_all を on_submit の第3引数として渡し、M.edit() 側で gh.edit_pr 成功時のみ呼ぶようにしました。suggestion の pcall 方式は on_submit 内の処理が非同期のため採用せず、コールバック方式で実装しています。
lua/fude/pr.lua
Outdated
| local body_lines = vim.split(data.body or "", "\n", { plain = true }) | ||
| M.open_pr_float({ data.title }, body_lines, { | ||
| mode = "edit", | ||
| footer = " <CR> update | q cancel ", | ||
| on_submit = function(title, body) | ||
| vim.notify("fude.nvim: Updating PR...", vim.log.levels.INFO) | ||
| gh.edit_pr(pr_number, title, body, function(edit_err) |
There was a problem hiding this comment.
M.edit() で取得した data.body を vim.split して open_pr_float() に渡していますが、送信時は parse_pr_buffer() 側で vim.trim(table.concat(body_lines, "\n")) されるため、先頭/末尾の空行や末尾改行などがユーザー操作なしでも削除され得ます(編集コマンドとしては差分が出る原因になります)。編集モードでは body の trim を避ける(例: body は table.concat(body_lines, "\n") のみにする)など、既存本文の体裁を維持できるようにしてください。
There was a problem hiding this comment.
dc5e351 で修正 — parse_pr_buffer に trim_body オプション(デフォルト true)を追加し、edit モードでは trim_body = false で呼び出すようにしました。
lua/fude/pr.lua
Outdated
| --- @param body_lines string[]|nil initial body lines (default: {""}) | ||
| --- @param from_draft boolean|nil true when restoring from a saved draft | ||
| function M.open_pr_float(title_lines, body_lines, from_draft) | ||
| --- @param opts table|nil options: { mode: "create"|"edit", footer: string, on_submit: fun(title, body) } |
There was a problem hiding this comment.
opts の型注釈コメントに from_draft が含まれていませんが、実装では opts.from_draft を参照しています。opts の想定フィールド(from_draft を含む)と各型をコメントに反映して、呼び出し側が誤解しないようにしてください。
| --- @param opts table|nil options: { mode: "create"|"edit", footer: string, on_submit: fun(title, body) } | |
| --- @param opts table|nil options: { mode: "create"|"edit", footer: string, from_draft: boolean, on_submit: fun(title, body) } |
There was a problem hiding this comment.
dc5e351 で修正 — from_draft: boolean を型注釈に追加しました。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add detached HEAD detection to get_pr_title_body (gh.lua) - Resolve PR number upfront in M.edit() via get_pr_info to avoid detached HEAD issues with both get and edit operations - Keep float open on edit failure so user can retry - Preserve PR body formatting in edit mode (skip vim.trim) - Add from_draft to open_pr_float opts type annotation - Add tests for trim_body option and close_float behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
||
| if parsed.title == "" then | ||
| vim.notify("fude.nvim: PR title is required", vim.log.levels.WARN) | ||
| return | ||
| end | ||
|
|
There was a problem hiding this comment.
submit() で opts.on_submit 実行前に close_all() しているため、編集モードで更新が失敗してもフロートが閉じて入力内容をその場で再試行できません。mode == "edit" の場合は成功後に閉じる(例: on_submit に close_all を渡して成功時のみ呼ぶ)か、失敗時にフロートを維持するように制御を分けてください。
There was a problem hiding this comment.
dc5e351 で修正済みです — edit モードでは close_all を on_submit の第3引数として渡し、成功時のみ呼ぶ方式にしています。
| --- Uses state.pr_number when review mode is active, otherwise detects via gh pr view. | ||
| --- Resolves PR number upfront to avoid detached HEAD issues with both get/edit. |
There was a problem hiding this comment.
編集用途の M.edit() でも parse_pr_buffer() の vim.trim() が効くため、ユーザーが本文を変更していなくても先頭/末尾の空行や末尾改行が削除され、意図しない更新差分が発生します。編集モードでは body を trim しないオプション(例: trim_body = false)を open_pr_float/parse_pr_buffer に追加して、既存本文の体裁を維持できるようにしてください。
There was a problem hiding this comment.
dc5e351 で修正済みです — parse_pr_buffer に trim_body オプションを追加し、edit モードでは trim_body = false で呼び出しています。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
概要
既存PRのtitleとbodyを編集する
FudeEditPRコマンドを追加。変更内容
gh.lua:get_pr_title_body()とedit_pr()関数を追加pr.lua:open_pr_float()をリファクタリングしoptsパラメータを追加、edit()関数を追加plugin/fude.lua:FudeEditPRコマンドを追加tests/fude/pr_spec.lua:edit()のテストを追加doc/fude.txt::FudeEditPRコマンドのドキュメントを追加CLAUDE.md:pr.luaのモジュール説明を更新使用方法
gh pr viewでPRを自動検出して編集キーマップ
<Tab>: タイトル/本文間を移動<CR>: PRを更新q: キャンセル🤖 Generated with Claude Code