diff --git a/README.md b/README.md
index 21f0e4f..4483908 100644
--- a/README.md
+++ b/README.md
@@ -176,17 +176,18 @@ You can override the CI config path with the `--ci-config` option.
Key Binding | Description
-------------------------------------------|---------------------------------------------------------
Ctrl + C | Exit
-Tab or Ctrl + Space | Switch between the layer and filetree views
+Tab | Switch between the layer and filetree views
Ctrl + F | Filter files
+PageUp | Scroll up a page
+PageDown | Scroll down a page
Ctrl + A | Layer view: see aggregated image modifications
Ctrl + L | Layer view: see current layer modifications
Space | Filetree view: collapse/uncollapse a directory
+Ctrl + Space | Filetree view: collapse/uncollapse all directories
Ctrl + A | Filetree view: show/hide added files
Ctrl + R | Filetree view: show/hide removed files
Ctrl + M | Filetree view: show/hide modified files
Ctrl + U | Filetree view: show/hide unmodified files
-PageUp | Filetree view: scroll up a page
-PageDown | Filetree view: scroll down a page
## UI Configuration
diff --git a/cmd/root.go b/cmd/root.go
index 01ff50e..ad8d0ce 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -59,13 +59,14 @@ func initConfig() {
viper.SetDefault("log.enabled", true)
// keybindings: status view / global
viper.SetDefault("keybinding.quit", "ctrl+c")
- viper.SetDefault("keybinding.toggle-view", "tab, ctrl+space")
+ viper.SetDefault("keybinding.toggle-view", "tab")
viper.SetDefault("keybinding.filter-files", "ctrl+f, ctrl+slash")
// keybindings: layer view
viper.SetDefault("keybinding.compare-all", "ctrl+a")
viper.SetDefault("keybinding.compare-layer", "ctrl+l")
// keybindings: filetree view
viper.SetDefault("keybinding.toggle-collapse-dir", "space")
+ viper.SetDefault("keybinding.toggle-collapse-all-dir", "ctrl+space")
viper.SetDefault("keybinding.toggle-added-files", "ctrl+a")
viper.SetDefault("keybinding.toggle-removed-files", "ctrl+r")
viper.SetDefault("keybinding.toggle-modified-files", "ctrl+m")
diff --git a/ui/filetreeview.go b/ui/filetreeview.go
index 0e36ccb..56d40ae 100644
--- a/ui/filetreeview.go
+++ b/ui/filetreeview.go
@@ -39,13 +39,14 @@ type FileTreeView struct {
bufferIndexUpperBound uint
bufferIndexLowerBound uint
- keybindingToggleCollapse []keybinding.Key
- keybindingToggleAdded []keybinding.Key
- keybindingToggleRemoved []keybinding.Key
- keybindingToggleModified []keybinding.Key
- keybindingToggleUnchanged []keybinding.Key
- keybindingPageDown []keybinding.Key
- keybindingPageUp []keybinding.Key
+ keybindingToggleCollapse []keybinding.Key
+ keybindingToggleCollapseAll []keybinding.Key
+ keybindingToggleAdded []keybinding.Key
+ keybindingToggleRemoved []keybinding.Key
+ keybindingToggleModified []keybinding.Key
+ keybindingToggleUnchanged []keybinding.Key
+ keybindingPageDown []keybinding.Key
+ keybindingPageUp []keybinding.Key
}
// NewFileTreeView creates a new view object attached the the global [gocui] screen object.
@@ -82,6 +83,11 @@ func NewFileTreeView(name string, gui *gocui.Gui, tree *filetree.FileTree, refTr
log.Panicln(err)
}
+ treeView.keybindingToggleCollapseAll, err = keybinding.ParseAll(viper.GetString("keybinding.toggle-collapse-all-dir"))
+ if err != nil {
+ log.Panicln(err)
+ }
+
treeView.keybindingToggleAdded, err = keybinding.ParseAll(viper.GetString("keybinding.toggle-added-files"))
if err != nil {
log.Panicln(err)
@@ -158,6 +164,11 @@ func (view *FileTreeView) Setup(v *gocui.View, header *gocui.View) error {
return err
}
}
+ for _, key := range view.keybindingToggleCollapseAll {
+ if err := view.gui.SetKeybinding(view.Name, key.Value, key.Modifier, func(*gocui.Gui, *gocui.View) error { return view.toggleCollapseAll() }); err != nil {
+ return err
+ }
+ }
for _, key := range view.keybindingToggleAdded {
if err := view.gui.SetKeybinding(view.Name, key.Value, key.Modifier, func(*gocui.Gui, *gocui.View) error { return view.toggleShowDiffType(filetree.Added) }); err != nil {
return err
@@ -466,13 +477,39 @@ func (view *FileTreeView) getAbsPositionNode() (node *filetree.FileNode) {
// toggleCollapse will collapse/expand the selected FileNode.
func (view *FileTreeView) toggleCollapse() error {
node := view.getAbsPositionNode()
- if node != nil {
+ if node != nil && node.Data.FileInfo.IsDir {
node.Data.ViewInfo.Collapsed = !node.Data.ViewInfo.Collapsed
}
view.Update()
return view.Render()
}
+// toggleCollapseAll will collapse/expand the all directories.
+func (view *FileTreeView) toggleCollapseAll() error {
+ node := view.getAbsPositionNode()
+ var collapseTargetState bool
+ if node != nil && node.Data.FileInfo.IsDir {
+ collapseTargetState = !node.Data.ViewInfo.Collapsed
+ }
+
+ visitor := func(curNode *filetree.FileNode) error {
+ curNode.Data.ViewInfo.Collapsed = collapseTargetState
+ return nil
+ }
+
+ evaluator := func(curNode *filetree.FileNode) bool {
+ return curNode.Data.FileInfo.IsDir
+ }
+
+ err := view.ModelTree.VisitDepthChildFirst(visitor, evaluator)
+ if err != nil {
+ logrus.Panic(err)
+ }
+
+ view.Update()
+ return view.Render()
+}
+
// toggleShowDiffType will show/hide the selected DiffType in the filetree pane.
func (view *FileTreeView) toggleShowDiffType(diffType filetree.DiffType) error {
view.HiddenDiffTypes[diffType] = !view.HiddenDiffTypes[diffType]
@@ -589,8 +626,9 @@ func (view *FileTreeView) Render() error {
// KeyHelp indicates all the possible actions a user can take while the current pane is selected.
func (view *FileTreeView) KeyHelp() string {
return renderStatusOption(view.keybindingToggleCollapse[0].String(), "Collapse dir", false) +
- renderStatusOption(view.keybindingToggleAdded[0].String(), "Added files", !view.HiddenDiffTypes[filetree.Added]) +
- renderStatusOption(view.keybindingToggleRemoved[0].String(), "Removed files", !view.HiddenDiffTypes[filetree.Removed]) +
- renderStatusOption(view.keybindingToggleModified[0].String(), "Modified files", !view.HiddenDiffTypes[filetree.Changed]) +
- renderStatusOption(view.keybindingToggleUnchanged[0].String(), "Unmodified files", !view.HiddenDiffTypes[filetree.Unchanged])
+ renderStatusOption(view.keybindingToggleCollapseAll[0].String(), "Collapse all dir", false) +
+ renderStatusOption(view.keybindingToggleAdded[0].String(), "Added", !view.HiddenDiffTypes[filetree.Added]) +
+ renderStatusOption(view.keybindingToggleRemoved[0].String(), "Removed", !view.HiddenDiffTypes[filetree.Removed]) +
+ renderStatusOption(view.keybindingToggleModified[0].String(), "Modified", !view.HiddenDiffTypes[filetree.Changed]) +
+ renderStatusOption(view.keybindingToggleUnchanged[0].String(), "Unmodified", !view.HiddenDiffTypes[filetree.Unchanged])
}
diff --git a/ui/statusview.go b/ui/statusview.go
index 9fe9cd0..266077c 100644
--- a/ui/statusview.go
+++ b/ui/statusview.go
@@ -77,5 +77,5 @@ func (view *StatusView) Render() error {
func (view *StatusView) KeyHelp() string {
return renderStatusOption(GlobalKeybindings.quit[0].String(), "Quit", false) +
renderStatusOption(GlobalKeybindings.toggleView[0].String(), "Switch view", false) +
- renderStatusOption(GlobalKeybindings.filterView[0].String(), "Filter files", Views.Filter.IsVisible())
+ renderStatusOption(GlobalKeybindings.filterView[0].String(), "Filter", Views.Filter.IsVisible())
}
diff --git a/ui/ui.go b/ui/ui.go
index c9a0fa7..f2443ae 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -295,9 +295,9 @@ func Render() {
// renderStatusOption formats key help bindings-to-title pairs.
func renderStatusOption(control, title string, selected bool) string {
if selected {
- return Formatting.StatusSelected("▏") + Formatting.StatusControlSelected(control) + Formatting.StatusSelected(" "+title+" ")
+ return Formatting.StatusSelected("▏") + Formatting.StatusControlSelected(control) + Formatting.StatusSelected(" "+title+" ")
} else {
- return Formatting.StatusNormal("▏") + Formatting.StatusControlNormal(control) + Formatting.StatusNormal(" "+title+" ")
+ return Formatting.StatusNormal("▏") + Formatting.StatusControlNormal(control) + Formatting.StatusNormal(" "+title+" ")
}
}