From 184d3a2b0c82d149f17e17c6494d3a4e4a1f93c8 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 17 Feb 2019 13:25:14 -0500 Subject: [PATCH] added layerview pgup/pgdown --- cmd/root.go | 10 +++---- ui/layerview.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ ui/ui.go | 38 +++++++++++++-------------- 3 files changed, 91 insertions(+), 26 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 9402fdd..01ff50e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,8 +15,6 @@ import ( "github.com/wagoodman/dive/utils" ) -const pathSep = string(os.PathSeparator) - var cfgFile string var exportFile string var ciConfigFile string @@ -139,7 +137,7 @@ func getCfgFile(fromFlag string) string { xdgHome := os.Getenv("XDG_CONFIG_HOME") xdgDirs := os.Getenv("XDG_CONFIG_DIRS") xdgPaths := append([]string{xdgHome}, strings.Split(xdgDirs, ":")...) - allDirs := append(xdgPaths, home+pathSep+".config") + allDirs := append(xdgPaths, path.Join(home, ".config")) for _, val := range allDirs { file := findInPath(val) @@ -147,13 +145,13 @@ func getCfgFile(fromFlag string) string { return file } } - return home + pathSep + "dive.yaml" + return path.Join(home, ".dive.yaml") } // findInPath returns first "*.yaml" file in path's subdirectory "dive" // if not found returns empty string func findInPath(pathTo string) string { - directory := pathTo + pathSep + "dive" + directory := path.Join(pathTo, "dive") files, err := ioutil.ReadDir(directory) if err != nil { return "" @@ -162,7 +160,7 @@ func findInPath(pathTo string) string { for _, file := range files { filename := file.Name() if path.Ext(filename) == ".yaml" { - return directory + pathSep + filename + return path.Join(directory, filename) } } return "" diff --git a/ui/layerview.go b/ui/layerview.go index 98dce2e..0179e06 100644 --- a/ui/layerview.go +++ b/ui/layerview.go @@ -28,6 +28,8 @@ type LayerView struct { keybindingCompareAll []keybinding.Key keybindingCompareLayer []keybinding.Key + keybindingPageDown []keybinding.Key + keybindingPageUp []keybinding.Key } // NewDetailsView creates a new view object attached the the global [gocui] screen object. @@ -59,6 +61,16 @@ func NewLayerView(name string, gui *gocui.Gui, layers []image.Layer) (layerView log.Panicln(err) } + layerView.keybindingPageUp, err = keybinding.ParseAll(viper.GetString("keybinding.page-up")) + if err != nil { + log.Panicln(err) + } + + layerView.keybindingPageDown, err = keybinding.ParseAll(viper.GetString("keybinding.page-down")) + if err != nil { + log.Panicln(err) + } + return layerView } @@ -84,6 +96,17 @@ func (view *LayerView) Setup(v *gocui.View, header *gocui.View) error { return err } + for _, key := range view.keybindingPageUp { + if err := view.gui.SetKeybinding(view.Name, key.Value, key.Modifier, func(*gocui.Gui, *gocui.View) error { return view.PageUp() }); err != nil { + return err + } + } + for _, key := range view.keybindingPageDown { + if err := view.gui.SetKeybinding(view.Name, key.Value, key.Modifier, func(*gocui.Gui, *gocui.View) error { return view.PageDown() }); err != nil { + return err + } + } + for _, key := range view.keybindingCompareLayer { if err := view.gui.SetKeybinding(view.Name, key.Value, key.Modifier, func(*gocui.Gui, *gocui.View) error { return view.setCompareMode(CompareLayer) }); err != nil { return err @@ -99,6 +122,13 @@ func (view *LayerView) Setup(v *gocui.View, header *gocui.View) error { return view.Render() } +// height obtains the height of the current pane (taking into account the lost space due to the header). +func (view *LayerView) height() uint { + _, height := view.view.Size() + return uint(height - 1) +} + + // IsVisible indicates if the layer view pane is currently initialized. func (view *LayerView) IsVisible() bool { if view == nil { @@ -107,6 +137,45 @@ func (view *LayerView) IsVisible() bool { return true } +// PageDown moves to next page putting the cursor on top +func (view *LayerView) PageDown() error { + step := int(view.height())+1 + targetLayerIndex := view.LayerIndex + step + + if targetLayerIndex > len(view.Layers) { + step -= targetLayerIndex - (len(view.Layers) -1) + targetLayerIndex = view.LayerIndex + step + } + + if step > 0 { + err := CursorStep(view.gui, view.view, step) + if err == nil { + view.SetCursor(view.LayerIndex + step) + } + } + return nil +} + +// PageUp moves to previous page putting the cursor on top +func (view *LayerView) PageUp() error { + step := int(view.height())+1 + targetLayerIndex := view.LayerIndex - step + + if targetLayerIndex < 0 { + step += targetLayerIndex + targetLayerIndex = view.LayerIndex - step + } + + if step > 0 { + err := CursorStep(view.gui, view.view, -step) + if err == nil { + view.SetCursor(view.LayerIndex - step) + } + } + return nil +} + + // CursorDown moves the cursor down in the layer pane (selecting a higher layer). func (view *LayerView) CursorDown() error { if view.LayerIndex < len(view.Layers) { diff --git a/ui/ui.go b/ui/ui.go index ccdcd3f..58a5e1e 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -110,31 +110,29 @@ func toggleFilterView(g *gocui.Gui, v *gocui.View) error { // CursorDown moves the cursor down in the currently selected gocui pane, scrolling the screen as needed. func CursorDown(g *gocui.Gui, v *gocui.View) error { - cx, cy := v.Cursor() - - // if there isn't a next line - line, err := v.Line(cy + 1) - if err != nil { - // todo: handle error - } - if len(line) == 0 { - return errors.New("unable to move cursor down, empty line") - } - if err := v.SetCursor(cx, cy+1); err != nil { - ox, oy := v.Origin() - if err := v.SetOrigin(ox, oy+1); err != nil { - return err - } - } - return nil + return CursorStep(g, v,1) } // CursorUp moves the cursor up in the currently selected gocui pane, scrolling the screen as needed. func CursorUp(g *gocui.Gui, v *gocui.View) error { - ox, oy := v.Origin() + return CursorStep(g, v,-1) +} + +// Moves the cursor the given step distance, setting the origin to the new cursor line +func CursorStep(g *gocui.Gui, v *gocui.View, step int) error { cx, cy := v.Cursor() - if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 { - if err := v.SetOrigin(ox, oy-1); err != nil { + + // if there isn't a next line + line, err := v.Line(cy+step) + if err != nil { + // todo: handle error + } + if len(line) == 0 { + return errors.New("unable to move the cursor, empty line") + } + if err := v.SetCursor(cx, cy+step); err != nil { + ox, oy := v.Origin() + if err := v.SetOrigin(ox, oy+step); err != nil { return err } }