From 7bea41534b5f186f7147dc0b7f1b95d6b03249a3 Mon Sep 17 00:00:00 2001 From: Mauricio Trajano Date: Thu, 26 Dec 2024 23:34:08 -0500 Subject: [PATCH] Collapse/expand all files in tree Co-authored-by: Stefan Haller --- docs/Config.md | 2 + docs/keybindings/Keybindings_en.md | 4 ++ docs/keybindings/Keybindings_ja.md | 4 ++ docs/keybindings/Keybindings_ko.md | 4 ++ docs/keybindings/Keybindings_nl.md | 4 ++ docs/keybindings/Keybindings_pl.md | 4 ++ docs/keybindings/Keybindings_ru.md | 4 ++ docs/keybindings/Keybindings_zh-CN.md | 4 ++ docs/keybindings/Keybindings_zh-TW.md | 4 ++ pkg/config/user_config.go | 4 ++ .../controllers/commits_files_controller.go | 38 +++++++++++++++ pkg/gui/controllers/files_controller.go | 38 +++++++++++++++ pkg/gui/filetree/collapsed_paths.go | 5 ++ pkg/gui/filetree/commit_file_tree.go | 14 ++++++ .../filetree/commit_file_tree_view_model.go | 31 +++++++++++++ pkg/gui/filetree/file_tree.go | 16 +++++++ pkg/gui/filetree/file_tree_view_model.go | 31 +++++++++++++ pkg/i18n/english.go | 10 ++++ pkg/integration/tests/file/collapse_expand.go | 46 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + schema/config.json | 8 ++++ 21 files changed, 276 insertions(+) create mode 100644 pkg/integration/tests/file/collapse_expand.go diff --git a/docs/Config.md b/docs/Config.md index a23943f431e..5d034695bcd 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -571,6 +571,8 @@ keybinding: openMergeTool: M openStatusFilter: copyFileInfoToClipboard: "y" + collapseAll: '-' + expandAll: = branches: createPullRequest: o viewPullRequestOptions: O diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index 2e95d6dfdf9..449c4b6ec6d 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -65,6 +65,8 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Search the current view by text | | ## Commit summary @@ -147,6 +149,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Open external diff tool (git difftool) | | | `` M `` | Open external merge tool | Run `git mergetool`. | | `` f `` | Fetch | Fetch changes from remote. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Search the current view by text | | ## Local branches diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md index 198b9da50e4..0ccd6e7abe9 100644 --- a/docs/keybindings/Keybindings_ja.md +++ b/docs/keybindings/Keybindings_ja.md @@ -143,6 +143,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 検索を開始 | | ## コミットメッセージ @@ -218,6 +220,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Open external diff tool (git difftool) | | | `` M `` | Git mergetoolを開く | Run `git mergetool`. | | `` f `` | Fetch | Fetch changes from remote. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 検索を開始 | | ## ブランチ diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md index 40e072b242b..e5fb37782d3 100644 --- a/docs/keybindings/Keybindings_ko.md +++ b/docs/keybindings/Keybindings_ko.md @@ -308,6 +308,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` a `` | Toggle all files included in patch | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Enter file to add selected lines to the patch (or toggle directory collapsed) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 검색 시작 | | ## 커밋메시지 @@ -359,6 +361,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Open external diff tool (git difftool) | | | `` M `` | Git mergetool를 열기 | Run `git mergetool`. | | `` f `` | Fetch | Fetch changes from remote. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 검색 시작 | | ## 확인 패널 diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index 224df04afd4..5951320c072 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -79,6 +79,8 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Open external diff tool (git difftool) | | | `` M `` | Open external merge tool | Run `git mergetool`. | | `` f `` | Fetch | Fetch changes from remote. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Start met zoeken | | ## Bevestigingspaneel @@ -136,6 +138,8 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Enter bestand om geselecteerde regels toe te voegen aan de patch | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Start met zoeken | | ## Commits diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index 952cd083703..c22d151d3cf 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -229,6 +229,8 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | | `` M `` | Otwórz zewnętrzne narzędzie scalania | Uruchom `git mergetool`. | | `` f `` | Pobierz | Pobierz zmiany ze zdalnego serwera. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Szukaj w bieżącym widoku po tekście | | ## Pliki commita @@ -245,6 +247,8 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` a `` | Przełącz wszystkie pliki | Dodaj/usuń wszystkie pliki commita do niestandardowej łatki. Zobacz https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Wejdź do pliku / Przełącz zwiń katalog | Jeśli plik jest wybrany, wejdź do pliku, aby móc dodawać/usuwać poszczególne linie do niestandardowej łatki. Jeśli wybrany jest katalog, przełącz katalog. | | `` ` `` | Przełącz widok drzewa plików | Przełącz widok plików między płaskim a drzewem. Płaski układ pokazuje wszystkie ścieżki plików na jednej liście, układ drzewa grupuje pliki według katalogów. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Szukaj w bieżącym widoku po tekście | | ## Podsumowanie commita diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md index 5166123e3af..a9d977fcb8c 100644 --- a/docs/keybindings/Keybindings_ru.md +++ b/docs/keybindings/Keybindings_ru.md @@ -270,6 +270,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` a `` | Переключить все файлы, включённые в патч | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | Введите файл, чтобы добавить выбранные строки в патч (или свернуть каталог переключения) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Найти | | ## Статус @@ -353,6 +355,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Open external diff tool (git difftool) | | | `` M `` | Открыть внешний инструмент слияния (git mergetool) | Run `git mergetool`. | | `` f `` | Получить изменения | Fetch changes from remote. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | Найти | | ## Хранилище diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md index f275726cbb9..6cabb0a3a13 100644 --- a/docs/keybindings/Keybindings_zh-CN.md +++ b/docs/keybindings/Keybindings_zh-CN.md @@ -195,6 +195,8 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` a `` | 操作所有文件 | 添加或删除所有提交中的文件到自定义的补丁中。请参阅 https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches。 | | `` `` | 输入文件以将所选行添加到补丁中(或切换目录折叠) | 如果已选择一个文件,则Enter进入该文件,以便您可以向自定义补丁添加/删除单独的行。如果选择了目录,则切换目录。 | | `` ` `` | 切换文件树视图 | 在平铺部署与树布局之间切换文件视图。平铺布局在一个列表中展示所有文件路径,树布局则根据目录分组展示。 | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 开始搜索 | | ## 文件 @@ -225,6 +227,8 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` `` | 使用外部差异比较工具(git difftool) | | | `` M `` | 打开外部合并工具(git mergetool) | 执行 `git mergetool`. | | `` f `` | 抓取 | 从远程获取变更 | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 开始搜索 | | ## 构建补丁中 diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md index 40b122d00f5..c891f6bdcb2 100644 --- a/docs/keybindings/Keybindings_zh-TW.md +++ b/docs/keybindings/Keybindings_zh-TW.md @@ -219,6 +219,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` a `` | 切換所有檔案是否包含在補丁中 | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. | | `` `` | 輸入檔案以將選定的行添加至補丁(或切換目錄折疊) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. | | `` ` `` | 顯示檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 搜尋 | | ## 收藏 (Stash) @@ -320,6 +322,8 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | 開啟外部差異工具 (git difftool) | | | `` M `` | 開啟外部合併工具 | 執行 `git mergetool`。 | | `` f `` | 擷取 | 同步遠端異動 | +| `` - `` | Collapse all files | Collapse all directories in the files tree | +| `` = `` | Expand all files | Expand all directories in the file tree | | `` / `` | 搜尋 | | ## 狀態 diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index d005fdc85d2..3df5c5a9ba4 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -456,6 +456,8 @@ type KeybindingFilesConfig struct { OpenMergeTool string `yaml:"openMergeTool"` OpenStatusFilter string `yaml:"openStatusFilter"` CopyFileInfoToClipboard string `yaml:"copyFileInfoToClipboard"` + CollapseAll string `yaml:"collapseAll"` + ExpandAll string `yaml:"expandAll"` } type KeybindingBranchesConfig struct { @@ -898,6 +900,8 @@ func GetDefaultConfig() *UserConfig { OpenStatusFilter: "", ConfirmDiscard: "x", CopyFileInfoToClipboard: "y", + CollapseAll: "-", + ExpandAll: "=", }, Branches: KeybindingBranchesConfig{ CopyPullRequestURL: "", diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 462b9c3ee5a..61dfa1d8580 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -109,6 +109,20 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) [] Description: self.c.Tr.ToggleTreeView, Tooltip: self.c.Tr.ToggleTreeViewTooltip, }, + { + Key: opts.GetKey(opts.Config.Files.CollapseAll), + Handler: self.collapseAll, + Description: self.c.Tr.CollapseAll, + Tooltip: self.c.Tr.CollapseAllTooltip, + GetDisabledReason: self.require(self.isInTreeMode), + }, + { + Key: opts.GetKey(opts.Config.Files.ExpandAll), + Handler: self.expandAll, + Description: self.c.Tr.ExpandAll, + Tooltip: self.c.Tr.ExpandAllTooltip, + GetDisabledReason: self.require(self.isInTreeMode), + }, } return bindings @@ -401,6 +415,22 @@ func (self *CommitFilesController) toggleTreeView() error { return nil } +func (self *CommitFilesController) collapseAll() error { + self.context().CommitFileTreeViewModel.CollapseAll() + + self.c.PostRefreshUpdate(self.context()) + + return nil +} + +func (self *CommitFilesController) expandAll() error { + self.context().CommitFileTreeViewModel.ExpandAll() + + self.c.PostRefreshUpdate(self.context()) + + return nil +} + // NOTE: these functions are identical to those in files_controller.go (except for types) and // could also be cleaned up with some generics func normalisedSelectedCommitFileNodes(selectedNodes []*filetree.CommitFileNode) []*filetree.CommitFileNode { @@ -420,3 +450,11 @@ func isDescendentOfSelectedCommitFileNodes(node *filetree.CommitFileNode, select } return false } + +func (self *CommitFilesController) isInTreeMode() *types.DisabledReason { + if !self.context().CommitFileTreeViewModel.InTreeMode() { + return &types.DisabledReason{Text: self.c.Tr.DisabledInFlatView} + } + + return nil +} diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 11414789a84..ac72565ad8f 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -186,6 +186,20 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types Description: self.c.Tr.Fetch, Tooltip: self.c.Tr.FetchTooltip, }, + { + Key: opts.GetKey(opts.Config.Files.CollapseAll), + Handler: self.collapseAll, + Description: self.c.Tr.CollapseAll, + Tooltip: self.c.Tr.CollapseAllTooltip, + GetDisabledReason: self.require(self.isInTreeMode), + }, + { + Key: opts.GetKey(opts.Config.Files.ExpandAll), + Handler: self.expandAll, + Description: self.c.Tr.ExpandAll, + Tooltip: self.c.Tr.ExpandAllTooltip, + GetDisabledReason: self.require(self.isInTreeMode), + }, } } @@ -478,6 +492,22 @@ func (self *FilesController) enter() error { return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1}) } +func (self *FilesController) collapseAll() error { + self.context().FileTreeViewModel.CollapseAll() + + self.c.PostRefreshUpdate(self.context()) + + return nil +} + +func (self *FilesController) expandAll() error { + self.context().FileTreeViewModel.ExpandAll() + + self.c.PostRefreshUpdate(self.context()) + + return nil +} + func (self *FilesController) EnterFile(opts types.OnFocusOpts) error { node := self.context().GetSelected() if node == nil { @@ -1181,3 +1211,11 @@ func (self *FilesController) formattedPaths(nodes []*filetree.FileNode) string { return node.GetPath() })) } + +func (self *FilesController) isInTreeMode() *types.DisabledReason { + if !self.context().FileTreeViewModel.InTreeMode() { + return &types.DisabledReason{Text: self.c.Tr.DisabledInFlatView} + } + + return nil +} diff --git a/pkg/gui/filetree/collapsed_paths.go b/pkg/gui/filetree/collapsed_paths.go index 903999b37d0..e22435b7ffa 100644 --- a/pkg/gui/filetree/collapsed_paths.go +++ b/pkg/gui/filetree/collapsed_paths.go @@ -36,3 +36,8 @@ func (self *CollapsedPaths) ToggleCollapsed(path string) { self.collapsedPaths.Add(path) } } + +func (self *CollapsedPaths) ExpandAll() { + // Could be cleaner if Set had a Clear() method... + self.collapsedPaths.RemoveSlice(self.collapsedPaths.ToSlice()) +} diff --git a/pkg/gui/filetree/commit_file_tree.go b/pkg/gui/filetree/commit_file_tree.go index 2593828eea3..9c8e0bf5239 100644 --- a/pkg/gui/filetree/commit_file_tree.go +++ b/pkg/gui/filetree/commit_file_tree.go @@ -25,6 +25,20 @@ type CommitFileTree struct { collapsedPaths *CollapsedPaths } +func (self *CommitFileTree) CollapseAll() { + dirPaths := lo.FilterMap(self.GetAllItems(), func(file *CommitFileNode, index int) (string, bool) { + return file.Path, !file.IsFile() + }) + + for _, path := range dirPaths { + self.collapsedPaths.Collapse(path) + } +} + +func (self *CommitFileTree) ExpandAll() { + self.collapsedPaths.ExpandAll() +} + var _ ICommitFileTree = &CommitFileTree{} func NewCommitFileTree(getFiles func() []*models.CommitFile, log *logrus.Entry, showTree bool) *CommitFileTree { diff --git a/pkg/gui/filetree/commit_file_tree_view_model.go b/pkg/gui/filetree/commit_file_tree_view_model.go index cbbb2fbcf3c..81f1427b888 100644 --- a/pkg/gui/filetree/commit_file_tree_view_model.go +++ b/pkg/gui/filetree/commit_file_tree_view_model.go @@ -1,6 +1,7 @@ package filetree import ( + "strings" "sync" "github.com/jesseduffield/lazygit/pkg/commands/models" @@ -160,3 +161,33 @@ func (self *CommitFileTreeViewModel) ToggleShowTree() { self.SetSelection(index) } } + +func (self *CommitFileTreeViewModel) CollapseAll() { + selectedNode := self.GetSelected() + + self.ICommitFileTree.CollapseAll() + if selectedNode == nil { + return + } + + topLevelPath := strings.Split(selectedNode.Path, "/")[0] + index, found := self.GetIndexForPath(topLevelPath) + if found { + self.SetSelectedLineIdx(index) + } +} + +func (self *CommitFileTreeViewModel) ExpandAll() { + selectedNode := self.GetSelected() + + self.ICommitFileTree.ExpandAll() + + if selectedNode == nil { + return + } + + index, found := self.GetIndexForPath(selectedNode.Path) + if found { + self.SetSelectedLineIdx(index) + } +} diff --git a/pkg/gui/filetree/file_tree.go b/pkg/gui/filetree/file_tree.go index 12780e3ed3d..c7cf1c76c1e 100644 --- a/pkg/gui/filetree/file_tree.go +++ b/pkg/gui/filetree/file_tree.go @@ -31,6 +31,8 @@ type ITree[T any] interface { IsCollapsed(path string) bool ToggleCollapsed(path string) CollapsedPaths() *CollapsedPaths + CollapseAll() + ExpandAll() } type IFileTree interface { @@ -171,6 +173,20 @@ func (self *FileTree) ToggleCollapsed(path string) { self.collapsedPaths.ToggleCollapsed(path) } +func (self *FileTree) CollapseAll() { + dirPaths := lo.FilterMap(self.GetAllItems(), func(file *FileNode, index int) (string, bool) { + return file.Path, !file.IsFile() + }) + + for _, path := range dirPaths { + self.collapsedPaths.Collapse(path) + } +} + +func (self *FileTree) ExpandAll() { + self.collapsedPaths.ExpandAll() +} + func (self *FileTree) Tree() *FileNode { return NewFileNode(self.tree) } diff --git a/pkg/gui/filetree/file_tree_view_model.go b/pkg/gui/filetree/file_tree_view_model.go index 25b3d0edcbd..29f5638348b 100644 --- a/pkg/gui/filetree/file_tree_view_model.go +++ b/pkg/gui/filetree/file_tree_view_model.go @@ -1,6 +1,7 @@ package filetree import ( + "strings" "sync" "github.com/jesseduffield/lazygit/pkg/commands/models" @@ -190,3 +191,33 @@ func (self *FileTreeViewModel) ToggleShowTree() { self.SetSelectedLineIdx(index) } } + +func (self *FileTreeViewModel) CollapseAll() { + selectedNode := self.GetSelected() + + self.IFileTree.CollapseAll() + if selectedNode == nil { + return + } + + topLevelPath := strings.Split(selectedNode.Path, "/")[0] + index, found := self.GetIndexForPath(topLevelPath) + if found { + self.SetSelectedLineIdx(index) + } +} + +func (self *FileTreeViewModel) ExpandAll() { + selectedNode := self.GetSelected() + + self.IFileTree.ExpandAll() + + if selectedNode == nil { + return + } + + index, found := self.GetIndexForPath(selectedNode.Path) + if found { + self.SetSelectedLineIdx(index) + } +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index af280ffb504..8e8db94967c 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -256,6 +256,11 @@ type TranslationSet struct { NoBranchOnRemote string Fetch string FetchTooltip string + CollapseAll string + CollapseAllTooltip string + ExpandAll string + ExpandAllTooltip string + DisabledInFlatView string FileEnter string FileEnterTooltip string FileStagingRequirements string @@ -1258,6 +1263,11 @@ func EnglishTranslationSet() *TranslationSet { NoBranchOnRemote: `This branch doesn't exist on remote. You need to push it to remote first.`, Fetch: `Fetch`, FetchTooltip: "Fetch changes from remote.", + CollapseAll: "Collapse all files", + CollapseAllTooltip: "Collapse all directories in the files tree", + ExpandAll: "Expand all files", + ExpandAllTooltip: "Expand all directories in the file tree", + DisabledInFlatView: "Not available in flat view", FileEnter: `Stage lines / Collapse directory`, FileEnterTooltip: "If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it.", FileStagingRequirements: `Can only stage individual lines for tracked files`, diff --git a/pkg/integration/tests/file/collapse_expand.go b/pkg/integration/tests/file/collapse_expand.go new file mode 100644 index 00000000000..68efe323e79 --- /dev/null +++ b/pkg/integration/tests/file/collapse_expand.go @@ -0,0 +1,46 @@ +package file + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var CollapseExpand = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Collapsing and expanding all files in the file tree", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) { + }, + SetupRepo: func(shell *Shell) { + shell.CreateDir("dir") + shell.CreateFile("dir/file-one", "original content\n") + shell.CreateDir("dir2") + shell.CreateFile("dir2/file-two", "original content\n") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Files(). + IsFocused(). + Lines( + Contains("dir").IsSelected(), + Contains("??").Contains("file-one"), + Contains("dir2"), + Contains("??").Contains("file-two"), + ) + + t.Views().Files(). + Press(keys.Files.CollapseAll). + Lines( + Contains("dir"), + Contains("dir2"), + ) + + t.Views().Files(). + Press(keys.Files.ExpandAll). + Lines( + Contains("dir").IsSelected(), + Contains("??").Contains("file-one"), + Contains("dir2"), + Contains("??").Contains("file-two"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index d7ce5e20462..2e1eef023f2 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -164,6 +164,7 @@ var tests = []*components.IntegrationTest{ diff.DiffNonStickyRange, diff.IgnoreWhitespace, diff.RenameSimilarityThresholdChange, + file.CollapseExpand, file.CopyMenu, file.DirWithUntrackedFile, file.DiscardAllDirChanges, diff --git a/schema/config.json b/schema/config.json index 4caa2144861..8ce2c57389e 100644 --- a/schema/config.json +++ b/schema/config.json @@ -1463,6 +1463,14 @@ "copyFileInfoToClipboard": { "type": "string", "default": "y" + }, + "collapseAll": { + "type": "string", + "default": "-" + }, + "expandAll": { + "type": "string", + "default": "=" } }, "additionalProperties": false,