From 327814f589c2dddef90f49dcaf5d365876258a5e Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 18 Feb 2019 16:59:32 -0500 Subject: [PATCH] Add collapse all directory keybinding (#162) * collapse all dir feature (closes #151) * render single title for keybindings --- README.md | 7 +++--- cmd/root.go | 3 ++- ui/filetreeview.go | 62 +++++++++++++++++++++++++++++++++++++--------- ui/statusview.go | 2 +- ui/ui.go | 4 +-- 5 files changed, 59 insertions(+), 19 deletions(-) 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+" ") } }