mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Add a jump-to-file menu to the focused main view's diff
n / N step through the files of a multi-file diff one at a time, which is tedious when the diff spans many files. Add `f`, which pops up a menu listing every file in the diff — in the order they appear, as repo-relative paths — so you can jump straight to one. The menu title and the keybinding description are hard-coded English for now; this is a prototype. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
822b3be988
commit
42d8f9697c
|
|
@ -234,6 +234,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Go to next hunk | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Commit staged changes. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
|
|
@ -316,6 +317,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Go to next hunk | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Commit staged changes. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 次のハンクに移動 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | サイドパネルに戻る | |
|
||||
| `` c `` | コミット | ステージされた変更をコミットします。 |
|
||||
| `` w `` | pre-commitフックなしで変更をコミット | |
|
||||
|
|
@ -293,6 +294,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 次のハンクに移動 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | サイドパネルに戻る | |
|
||||
| `` c `` | コミット | ステージされた変更をコミットします。 |
|
||||
| `` w `` | pre-commitフックなしで変更をコミット | |
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 다음 hunk를 선택 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | 커밋 변경내용 | 스테이징된 변경 사항 커밋. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
|
|
@ -188,6 +189,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 다음 hunk를 선택 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | 커밋 변경내용 | 스테이징된 변경 사항 커밋. |
|
||||
| `` w `` | Commit changes without pre-commit hook | |
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Selecteer de volgende hunk | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit veranderingen | Commit gestagede wijzigingen. |
|
||||
| `` w `` | Commit veranderingen zonder pre-commit hook | |
|
||||
|
|
@ -316,6 +317,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Selecteer de volgende hunk | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit veranderingen | Commit gestagede wijzigingen. |
|
||||
| `` w `` | Commit veranderingen zonder pre-commit hook | |
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Idź do następnego fragmentu | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Zatwierdź zmiany zatwierdzone. |
|
||||
| `` w `` | Zatwierdź zmiany bez hooka pre-commit | |
|
||||
|
|
@ -211,6 +212,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Idź do następnego fragmentu | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Zatwierdź zmiany zatwierdzone. |
|
||||
| `` w `` | Zatwierdź zmiany bez hooka pre-commit | |
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Ir para o próximo trecho | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Submeter mudanças em staging |
|
||||
| `` w `` | Fazer commit de alterações sem pré-commit | |
|
||||
|
|
@ -325,6 +326,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Ir para o próximo trecho | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Commit | Submeter mudanças em staging |
|
||||
| `` w `` | Fazer commit de alterações sem pré-commit | |
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Выбрать следующую часть | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Сохранить изменения | Commit staged changes. |
|
||||
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
|
||||
|
|
@ -110,6 +111,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | Выбрать следующую часть | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | Exit back to side panel | |
|
||||
| `` c `` | Сохранить изменения | Commit staged changes. |
|
||||
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
|
||||
|
|
|
|||
|
|
@ -281,6 +281,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 选择下一个区块 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | 退出回到侧边面板 | |
|
||||
| `` c `` | 提交变更 | 提交暂存文件 |
|
||||
| `` w `` | 提交变更而无需预先提交钩子 | |
|
||||
|
|
@ -322,6 +323,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 选择下一个区块 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | 退出回到侧边面板 | |
|
||||
| `` c `` | 提交变更 | 提交暂存文件 |
|
||||
| `` w `` | 提交变更而无需预先提交钩子 | |
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 選擇下一段 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | 退出回到側邊面板 | |
|
||||
| `` c `` | 提交變更 | 提交暫存區變更 |
|
||||
| `` w `` | 沒有預提交 hook 就提交更改 | |
|
||||
|
|
@ -344,6 +345,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
| `` <right>, l `` | 選擇下一段 | |
|
||||
| `` N `` | Go to previous file | |
|
||||
| `` n `` | Go to next file | |
|
||||
| `` f `` | Jump to file | |
|
||||
| `` <esc> `` | 退出回到側邊面板 | |
|
||||
| `` c `` | 提交變更 | 提交暫存區變更 |
|
||||
| `` w `` | 沒有預提交 hook 就提交更改 | |
|
||||
|
|
|
|||
|
|
@ -455,3 +455,32 @@ func changeBlockStart(isChange []bool, from int, forward bool) (int, bool) {
|
|||
}
|
||||
return i, true
|
||||
}
|
||||
|
||||
// DiffFile is a file shown in a (possibly multi-file) diff: its absolute path and the
|
||||
// view line its section starts at — the row that next/previous-file navigation lands on.
|
||||
type DiffFile struct {
|
||||
Path string
|
||||
FirstViewLine int
|
||||
}
|
||||
|
||||
// FilesInDiff lists the files shown in view's diff, in display order, each paired with
|
||||
// the view line its section starts at. It is the jump-to-file menu's source: jumping to
|
||||
// a file goes to its FirstViewLine, computed the same way (backUpOverHeader) that
|
||||
// AdjacentFile lands on a file, so the menu and n/N agree on where each file begins. A
|
||||
// file whose start row isn't currently mapped to a view line (not loaded yet) is skipped.
|
||||
func (self *DiffLineHelper) FilesInDiff(view *gocui.View) []DiffFile {
|
||||
paths := self.filePaths(view)
|
||||
|
||||
var files []DiffFile
|
||||
prevPath := ""
|
||||
for i, path := range paths {
|
||||
if path == "" || path == prevPath {
|
||||
continue
|
||||
}
|
||||
prevPath = path
|
||||
if viewLine, ok := view.ViewLineForBufferLine(i); ok {
|
||||
files = append(files, DiffFile{Path: path, FirstViewLine: viewLine})
|
||||
}
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
|
|
@ -154,6 +156,13 @@ func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*ty
|
|||
DescriptionFunc: self.diffSelectionDescriptionText(self.c.Tr.NextFileInDiff),
|
||||
GetDisabledReason: self.diffSelectionDisabledReason,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(config.Keybinding{"f"}),
|
||||
Handler: self.openJumpToFileMenu,
|
||||
Description: "Jump to file",
|
||||
DescriptionFunc: self.diffSelectionDescriptionText("Jump to file"),
|
||||
GetDisabledReason: self.diffSelectionDisabledReason,
|
||||
},
|
||||
{
|
||||
Keys: opts.GetKeys(opts.Config.Universal.Return),
|
||||
Handler: self.escape,
|
||||
|
|
@ -747,6 +756,60 @@ func (self *MainViewController) placeNavigationTarget(target int) {
|
|||
self.c.Helpers().DiffLine.ShowSelectionAtLine(v, target, true)
|
||||
}
|
||||
|
||||
// openJumpToFileMenu pops up a menu listing the files in the focused main view's diff, in
|
||||
// the order they appear, as repo-relative paths; picking one jumps straight to it. It's a
|
||||
// complement to n / N for a diff that spans many files. A no-op when the main view holds
|
||||
// no diff (nothing to list).
|
||||
//
|
||||
// The diff loads lazily, so we read it to the end first — otherwise a file past the loaded
|
||||
// portion of a long diff would be missing from the menu (and have no view line to jump to).
|
||||
// Same as handleGotoBottom.
|
||||
func (self *MainViewController) openJumpToFileMenu() error {
|
||||
manager := self.c.GetViewBufferManagerForView(self.context.GetView())
|
||||
if manager == nil {
|
||||
return nil
|
||||
}
|
||||
manager.ReadToEnd(func() {
|
||||
self.c.OnUIThread(func() error {
|
||||
return self.showJumpToFileMenu()
|
||||
})
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MainViewController) showJumpToFileMenu() error {
|
||||
files := self.c.Helpers().DiffLine.FilesInDiff(self.context.GetView())
|
||||
if len(files) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
worktreePath := self.c.Git().RepoPaths.WorktreePath()
|
||||
menuItems := lo.Map(files, func(file helpers.DiffFile, index int) *types.MenuItem {
|
||||
label := file.Path
|
||||
if rel, err := filepath.Rel(worktreePath, file.Path); err == nil {
|
||||
label = rel
|
||||
}
|
||||
firstViewLine := file.FirstViewLine
|
||||
return &types.MenuItem{
|
||||
Label: label,
|
||||
OnPress: func() error { self.jumpToFile(firstViewLine); return nil },
|
||||
}
|
||||
})
|
||||
|
||||
// TODO: i18n-ize this title
|
||||
return self.c.Menu(types.CreateMenuOptions{Title: "Jump to file", Items: menuItems, HideCancel: true, FilterAsYouType: true})
|
||||
}
|
||||
|
||||
// jumpToFile moves the focused main view to the given view line exactly the way
|
||||
// next/previous-file navigation does (see navigate), so jumping from the menu and
|
||||
// stepping with n / N land identically — scrolling the file to the top with no selection,
|
||||
// or moving the selection (or hunk selection) to it when one is showing.
|
||||
func (self *MainViewController) jumpToFile(firstViewLine int) {
|
||||
self.navigate(func(*gocui.View, int, bool) (int, bool) {
|
||||
return firstViewLine, true
|
||||
}, true)
|
||||
}
|
||||
|
||||
// moveCursor moves the selection cursor by delta view lines (negative = up), with the
|
||||
// configured scroll-off margin, reading more content in first when moving down. The
|
||||
// range anchor is left untouched, so this extends or contracts a range and just moves
|
||||
|
|
|
|||
Loading…
Reference in a new issue