Merge branch 'master' into efficiency-map
This commit is contained in:
commit
1b5adfd447
@ -50,9 +50,6 @@ func (view *FileTreeView) Setup(v *gocui.View, header *gocui.View) error {
|
|||||||
view.view = v
|
view.view = v
|
||||||
view.view.Editable = false
|
view.view.Editable = false
|
||||||
view.view.Wrap = false
|
view.view.Wrap = false
|
||||||
//view.view.Highlight = true
|
|
||||||
//view.view.SelBgColor = gocui.ColorGreen
|
|
||||||
//view.view.SelFgColor = gocui.ColorBlack
|
|
||||||
view.view.Frame = false
|
view.view.Frame = false
|
||||||
|
|
||||||
view.header = header
|
view.header = header
|
||||||
@ -82,19 +79,17 @@ func (view *FileTreeView) Setup(v *gocui.View, header *gocui.View) error {
|
|||||||
if err := view.gui.SetKeybinding(view.Name, gocui.KeyCtrlU, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.toggleShowDiffType(filetree.Unchanged) }); err != nil {
|
if err := view.gui.SetKeybinding(view.Name, gocui.KeyCtrlU, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.toggleShowDiffType(filetree.Unchanged) }); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := view.gui.SetKeybinding(view.Name, gocui.KeyCtrlSlash, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return nil }); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
view.updateViewTree()
|
view.Update()
|
||||||
view.Render()
|
view.Render()
|
||||||
|
|
||||||
headerStr := fmt.Sprintf(filetree.AttributeFormat+" %s", "P", "ermission", "UID:GID", "Size", "Filetree")
|
|
||||||
fmt.Fprintln(view.header, Formatting.Header(vtclean.Clean(headerStr, false)))
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *FileTreeView) IsVisible() bool {
|
||||||
|
if view == nil {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) error {
|
func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTreeStart, topTreeStop int) error {
|
||||||
@ -120,7 +115,7 @@ func (view *FileTreeView) setTreeByLayer(bottomTreeStart, bottomTreeStop, topTre
|
|||||||
view.view.SetCursor(0, 0)
|
view.view.SetCursor(0, 0)
|
||||||
view.TreeIndex = 0
|
view.TreeIndex = 0
|
||||||
view.ModelTree = newTree
|
view.ModelTree = newTree
|
||||||
view.updateViewTree()
|
view.Update()
|
||||||
return view.Render()
|
return view.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +153,7 @@ func (view *FileTreeView) getAbsPositionNode() (node *filetree.FileNode) {
|
|||||||
}
|
}
|
||||||
var filterBytes []byte
|
var filterBytes []byte
|
||||||
var filterRegex *regexp.Regexp
|
var filterRegex *regexp.Regexp
|
||||||
read, err := Views.Command.view.Read(filterBytes)
|
read, err := Views.Filter.view.Read(filterBytes)
|
||||||
if read > 0 && err == nil {
|
if read > 0 && err == nil {
|
||||||
regex, err := regexp.Compile(string(filterBytes))
|
regex, err := regexp.Compile(string(filterBytes))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -188,7 +183,7 @@ func (view *FileTreeView) toggleCollapse() error {
|
|||||||
if node != nil {
|
if node != nil {
|
||||||
node.Data.ViewInfo.Collapsed = !node.Data.ViewInfo.Collapsed
|
node.Data.ViewInfo.Collapsed = !node.Data.ViewInfo.Collapsed
|
||||||
}
|
}
|
||||||
view.updateViewTree()
|
view.Update()
|
||||||
return view.Render()
|
return view.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,15 +192,17 @@ func (view *FileTreeView) toggleShowDiffType(diffType filetree.DiffType) error {
|
|||||||
|
|
||||||
view.view.SetCursor(0, 0)
|
view.view.SetCursor(0, 0)
|
||||||
view.TreeIndex = 0
|
view.TreeIndex = 0
|
||||||
view.updateViewTree()
|
|
||||||
return view.Render()
|
Update()
|
||||||
|
Render()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterRegex() *regexp.Regexp {
|
func filterRegex() *regexp.Regexp {
|
||||||
if Views.Command == nil || Views.Command.view == nil {
|
if Views.Filter == nil || Views.Filter.view == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
filterString := strings.TrimSpace(Views.Command.view.Buffer())
|
filterString := strings.TrimSpace(Views.Filter.view.Buffer())
|
||||||
if len(filterString) < 1 {
|
if len(filterString) < 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -218,7 +215,7 @@ func filterRegex() *regexp.Regexp {
|
|||||||
return regex
|
return regex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *FileTreeView) updateViewTree() {
|
func (view *FileTreeView) Update() error {
|
||||||
regex := filterRegex()
|
regex := filterRegex()
|
||||||
|
|
||||||
// keep the view selection in parity with the current DiffType selection
|
// keep the view selection in parity with the current DiffType selection
|
||||||
@ -245,24 +242,31 @@ func (view *FileTreeView) updateViewTree() {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}, nil)
|
}, nil)
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *FileTreeView) KeyHelp() string {
|
func (view *FileTreeView) KeyHelp() string {
|
||||||
return Formatting.Control("[Space]") + ": Collapse dir " +
|
return renderStatusOption("Space","Collapse dir", false) +
|
||||||
Formatting.Control("[^A]") + ": Added files " +
|
renderStatusOption("^A","Added files", !view.HiddenDiffTypes[filetree.Added]) +
|
||||||
Formatting.Control("[^R]") + ": Removed files " +
|
renderStatusOption("^R","Removed files", !view.HiddenDiffTypes[filetree.Removed]) +
|
||||||
Formatting.Control("[^M]") + ": Modified files " +
|
renderStatusOption("^M","Modified files", !view.HiddenDiffTypes[filetree.Changed]) +
|
||||||
Formatting.Control("[^U]") + ": Unmodified files"
|
renderStatusOption("^U","Unmodified files", !view.HiddenDiffTypes[filetree.Unchanged])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *FileTreeView) Render() error {
|
func (view *FileTreeView) Render() error {
|
||||||
// print the tree to the view
|
// print the tree to the view
|
||||||
lines := strings.Split(view.ViewTree.String(true), "\n")
|
lines := strings.Split(view.ViewTree.String(true), "\n")
|
||||||
view.gui.Update(func(g *gocui.Gui) error {
|
view.gui.Update(func(g *gocui.Gui) error {
|
||||||
|
// update the header
|
||||||
|
view.header.Clear()
|
||||||
|
headerStr := fmt.Sprintf(filetree.AttributeFormat+" %s", "P", "ermission", "UID:GID", "Size", "Filetree")
|
||||||
|
fmt.Fprintln(view.header, Formatting.Header(vtclean.Clean(headerStr, false)))
|
||||||
|
|
||||||
|
// update the contents
|
||||||
view.view.Clear()
|
view.view.Clear()
|
||||||
for idx, line := range lines {
|
for idx, line := range lines {
|
||||||
if idx == view.TreeIndex {
|
if idx == view.TreeIndex {
|
||||||
fmt.Fprintln(view.view, Formatting.StatusBar(vtclean.Clean(line, false)))
|
fmt.Fprintln(view.view, Formatting.Selected(vtclean.Clean(line, false)))
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(view.view, line)
|
fmt.Fprintln(view.view, line)
|
||||||
}
|
}
|
||||||
@ -272,8 +276,3 @@ func (view *FileTreeView) Render() error {
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *FileTreeView) ReRender() error {
|
|
||||||
view.updateViewTree()
|
|
||||||
return view.Render()
|
|
||||||
}
|
|
||||||
|
@ -8,11 +8,14 @@ import (
|
|||||||
|
|
||||||
// with special thanks to https://gist.github.com/jroimartin/3b2e943a3811d795e0718b4a95b89bec
|
// with special thanks to https://gist.github.com/jroimartin/3b2e943a3811d795e0718b4a95b89bec
|
||||||
|
|
||||||
type CommandView struct {
|
type FilterView struct {
|
||||||
Name string
|
Name string
|
||||||
gui *gocui.Gui
|
gui *gocui.Gui
|
||||||
view *gocui.View
|
view *gocui.View
|
||||||
|
header *gocui.View
|
||||||
|
headerStr string
|
||||||
maxLength int
|
maxLength int
|
||||||
|
hidden bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Input struct {
|
type Input struct {
|
||||||
@ -22,25 +25,34 @@ type Input struct {
|
|||||||
maxLength int
|
maxLength int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommandView(name string, gui *gocui.Gui) (commandview *CommandView) {
|
func NewFilterView(name string, gui *gocui.Gui) (filterview *FilterView) {
|
||||||
commandview = new(CommandView)
|
filterview = new(FilterView)
|
||||||
|
|
||||||
// populate main fields
|
// populate main fields
|
||||||
commandview.Name = name
|
filterview.Name = name
|
||||||
commandview.gui = gui
|
filterview.gui = gui
|
||||||
|
filterview.headerStr = "Path Filter: "
|
||||||
|
filterview.hidden = true
|
||||||
|
|
||||||
return commandview
|
return filterview
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *CommandView) Setup(v *gocui.View, header *gocui.View) error {
|
func (view *FilterView) Setup(v *gocui.View, header *gocui.View) error {
|
||||||
|
|
||||||
// set view options
|
// set view options
|
||||||
view.view = v
|
view.view = v
|
||||||
view.maxLength = 200
|
view.maxLength = 200
|
||||||
view.view.Frame = false
|
view.view.Frame = false
|
||||||
view.view.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
view.view.BgColor = gocui.AttrReverse
|
||||||
view.view.Editable = true
|
view.view.Editable = true
|
||||||
view.view.Editor = view
|
view.view.Editor = view
|
||||||
|
|
||||||
|
view.header = header
|
||||||
|
view.header.BgColor = gocui.AttrReverse
|
||||||
|
view.header.Editable = false
|
||||||
|
view.header.Wrap = false
|
||||||
|
view.header.Frame = false
|
||||||
|
|
||||||
// set keybindings
|
// set keybindings
|
||||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorDown() }); err != nil {
|
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorDown() }); err != nil {
|
||||||
// return err
|
// return err
|
||||||
@ -54,18 +66,27 @@ func (view *CommandView) Setup(v *gocui.View, header *gocui.View) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *CommandView) CursorDown() error {
|
func (view *FilterView) IsVisible() bool {
|
||||||
|
if view == nil {return false}
|
||||||
|
return !view.hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *FilterView) CursorDown() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *CommandView) CursorUp() error {
|
func (view *FilterView) CursorUp() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *CommandView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
|
func (view *FilterView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
|
||||||
|
if !view.IsVisible() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cx, _ := v.Cursor()
|
cx, _ := v.Cursor()
|
||||||
ox, _ := v.Origin()
|
ox, _ := v.Origin()
|
||||||
limit := ox+cx+1 > i.maxLength
|
limit := ox+cx+1 > view.maxLength
|
||||||
switch {
|
switch {
|
||||||
case ch != 0 && mod == 0 && !limit:
|
case ch != 0 && mod == 0 && !limit:
|
||||||
v.EditWrite(ch)
|
v.EditWrite(ch)
|
||||||
@ -75,17 +96,23 @@ func (i *CommandView) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modi
|
|||||||
v.EditDelete(true)
|
v.EditDelete(true)
|
||||||
}
|
}
|
||||||
if Views.Tree != nil {
|
if Views.Tree != nil {
|
||||||
Views.Tree.ReRender()
|
Views.Tree.Update()
|
||||||
|
Views.Tree.Render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *CommandView) KeyHelp() string {
|
func (view *FilterView) KeyHelp() string {
|
||||||
return "Type string to filter"
|
return Formatting.StatusControlNormal("▏Type to filter the file tree ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *CommandView) Render() error {
|
func (view *FilterView) Update() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *FilterView) Render() error {
|
||||||
view.gui.Update(func(g *gocui.Gui) error {
|
view.gui.Update(func(g *gocui.Gui) error {
|
||||||
fmt.Fprintln(view.view, "")
|
// render the header
|
||||||
|
fmt.Fprintln(view.header, Formatting.Header(view.headerStr))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
@ -61,16 +61,18 @@ func (view *LayerView) Setup(v *gocui.View, header *gocui.View) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
headerStr := fmt.Sprintf("Cmp "+image.LayerFormat, "Image ID", "Size", "Command")
|
|
||||||
fmt.Fprintln(view.header, Formatting.Header(vtclean.Clean(headerStr, false)))
|
|
||||||
|
|
||||||
return view.Render()
|
return view.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *LayerView) IsVisible() bool {
|
||||||
|
if view == nil {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (view *LayerView) setCompareMode(compareMode CompareType) error {
|
func (view *LayerView) setCompareMode(compareMode CompareType) error {
|
||||||
view.CompareMode = compareMode
|
view.CompareMode = compareMode
|
||||||
view.Render()
|
Update()
|
||||||
|
Render()
|
||||||
return Views.Tree.setTreeByLayer(view.getCompareIndexes())
|
return Views.Tree.setTreeByLayer(view.getCompareIndexes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +126,17 @@ func (view *LayerView) renderCompareBar(layerIdx int) string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *LayerView) Update() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (view *LayerView) Render() error {
|
func (view *LayerView) Render() error {
|
||||||
view.gui.Update(func(g *gocui.Gui) error {
|
view.gui.Update(func(g *gocui.Gui) error {
|
||||||
|
// update header
|
||||||
|
headerStr := fmt.Sprintf("Cmp "+image.LayerFormat, "Image ID", "Size", "Filter")
|
||||||
|
fmt.Fprintln(view.header, Formatting.Header(vtclean.Clean(headerStr, false)))
|
||||||
|
|
||||||
|
// update contents
|
||||||
view.view.Clear()
|
view.view.Clear()
|
||||||
for revIdx := len(view.Layers) - 1; revIdx >= 0; revIdx-- {
|
for revIdx := len(view.Layers) - 1; revIdx >= 0; revIdx-- {
|
||||||
layer := view.Layers[revIdx]
|
layer := view.Layers[revIdx]
|
||||||
@ -140,7 +151,7 @@ func (view *LayerView) Render() error {
|
|||||||
compareBar := view.renderCompareBar(idx)
|
compareBar := view.renderCompareBar(idx)
|
||||||
|
|
||||||
if idx == view.LayerIndex {
|
if idx == view.LayerIndex {
|
||||||
fmt.Fprintln(view.view, compareBar + " " + Formatting.StatusBar(layerStr))
|
fmt.Fprintln(view.view, compareBar + " " + Formatting.Selected(layerStr))
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(view.view, compareBar + " " + layerStr)
|
fmt.Fprintln(view.view, compareBar + " " + layerStr)
|
||||||
}
|
}
|
||||||
@ -177,6 +188,6 @@ func (view *LayerView) CursorUp() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *LayerView) KeyHelp() string {
|
func (view *LayerView) KeyHelp() string {
|
||||||
return Formatting.Control("[^L]") + ": Layer Changes " +
|
return renderStatusOption("^L","Layer changes", view.CompareMode == CompareLayer) +
|
||||||
Formatting.Control("[^A]") + ": All Changes "
|
renderStatusOption("^A","All changes", view.CompareMode == CompareAll)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jroimartin/gocui"
|
"github.com/jroimartin/gocui"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StatusView struct {
|
type StatusView struct {
|
||||||
@ -27,21 +28,18 @@ func (view *StatusView) Setup(v *gocui.View, header *gocui.View) error {
|
|||||||
// set view options
|
// set view options
|
||||||
view.view = v
|
view.view = v
|
||||||
view.view.Frame = false
|
view.view.Frame = false
|
||||||
view.view.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
//view.view.BgColor = gocui.ColorDefault + gocui.AttrReverse
|
||||||
|
|
||||||
// set keybindings
|
|
||||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorDown() }); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// if err := view.gui.SetKeybinding(view.Name, gocui.KeyArrowUp, gocui.ModNone, func(*gocui.Gui, *gocui.View) error { return view.CursorUp() }); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
view.Render()
|
view.Render()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *StatusView) IsVisible() bool {
|
||||||
|
if view == nil {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (view *StatusView) CursorDown() error {
|
func (view *StatusView) CursorDown() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -51,15 +49,19 @@ func (view *StatusView) CursorUp() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *StatusView) KeyHelp() string {
|
func (view *StatusView) KeyHelp() string {
|
||||||
return Formatting.Control("[^C]") + ": Quit " +
|
return renderStatusOption("^C","Quit", false) +
|
||||||
Formatting.Control("[^Space]") + ": Switch View " +
|
renderStatusOption("^Space","Switch view", false) +
|
||||||
Formatting.Control("[^/]") + ": Filter files"
|
renderStatusOption("^/","Filter files", Views.Filter.IsVisible())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *StatusView) Update() error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *StatusView) Render() error {
|
func (view *StatusView) Render() error {
|
||||||
view.gui.Update(func(g *gocui.Gui) error {
|
view.gui.Update(func(g *gocui.Gui) error {
|
||||||
view.view.Clear()
|
view.view.Clear()
|
||||||
fmt.Fprintln(view.view, view.KeyHelp()+" | "+Views.lookup[view.gui.CurrentView().Name()].KeyHelp())
|
fmt.Fprintln(view.view, view.KeyHelp()+Views.lookup[view.gui.CurrentView().Name()].KeyHelp() + Formatting.StatusNormal("▏" + strings.Repeat(" ", 1000)))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
160
ui/ui.go
160
ui/ui.go
@ -27,8 +27,11 @@ func debugPrint(s string) {
|
|||||||
|
|
||||||
var Formatting struct {
|
var Formatting struct {
|
||||||
Header func(...interface{})(string)
|
Header func(...interface{})(string)
|
||||||
StatusBar func(...interface{})(string)
|
Selected func(...interface{})(string)
|
||||||
Control func(...interface{})(string)
|
StatusSelected func(...interface{})(string)
|
||||||
|
StatusNormal func(...interface{})(string)
|
||||||
|
StatusControlSelected func(...interface{})(string)
|
||||||
|
StatusControlNormal func(...interface{})(string)
|
||||||
CompareTop func(...interface{})(string)
|
CompareTop func(...interface{})(string)
|
||||||
CompareBottom func(...interface{})(string)
|
CompareBottom func(...interface{})(string)
|
||||||
}
|
}
|
||||||
@ -37,7 +40,7 @@ var Views struct {
|
|||||||
Tree *FileTreeView
|
Tree *FileTreeView
|
||||||
Layer *LayerView
|
Layer *LayerView
|
||||||
Status *StatusView
|
Status *StatusView
|
||||||
Command *CommandView
|
Filter *FilterView
|
||||||
lookup map[string]View
|
lookup map[string]View
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,32 +49,44 @@ type View interface {
|
|||||||
CursorDown() error
|
CursorDown() error
|
||||||
CursorUp() error
|
CursorUp() error
|
||||||
Render() error
|
Render() error
|
||||||
|
Update() error
|
||||||
KeyHelp() string
|
KeyHelp() string
|
||||||
|
IsVisible() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleView(g *gocui.Gui, v *gocui.View) error {
|
func toggleView(g *gocui.Gui, v *gocui.View) error {
|
||||||
if v == nil || v.Name() == Views.Layer.Name {
|
if v == nil || v.Name() == Views.Layer.Name {
|
||||||
_, err := g.SetCurrentView(Views.Tree.Name)
|
_, err := g.SetCurrentView(Views.Tree.Name)
|
||||||
|
Update()
|
||||||
Render()
|
Render()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err := g.SetCurrentView(Views.Layer.Name)
|
_, err := g.SetCurrentView(Views.Layer.Name)
|
||||||
|
Update()
|
||||||
Render()
|
Render()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func focusFilterView(g *gocui.Gui, v *gocui.View) error {
|
func toggleFilterView(g *gocui.Gui, v *gocui.View) error {
|
||||||
_, err := g.SetCurrentView(Views.Command.Name)
|
// delete all user input from the tree view
|
||||||
Render()
|
Views.Filter.view.Clear()
|
||||||
|
Views.Filter.view.SetCursor(0,0)
|
||||||
|
|
||||||
|
// toggle hiding
|
||||||
|
Views.Filter.hidden = !Views.Filter.hidden
|
||||||
|
|
||||||
|
if !Views.Filter.hidden {
|
||||||
|
_, err := g.SetCurrentView(Views.Filter.Name)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Update()
|
||||||
|
Render()
|
||||||
|
} else {
|
||||||
|
toggleView(g, v)
|
||||||
|
}
|
||||||
|
|
||||||
func returnToTreeView(g *gocui.Gui, v *gocui.View) error {
|
return nil
|
||||||
_, err := g.SetCurrentView(Views.Tree.Name)
|
|
||||||
if Views.Tree != nil {
|
|
||||||
Views.Tree.ReRender()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CursorDown(g *gocui.Gui, v *gocui.View) error {
|
func CursorDown(g *gocui.Gui, v *gocui.View) error {
|
||||||
@ -116,22 +131,29 @@ func keybindings(g *gocui.Gui) error {
|
|||||||
//if err := g.SetKeybinding("main", gocui.MouseLeft, gocui.ModNone, toggleCollapse); err != nil {
|
//if err := g.SetKeybinding("main", gocui.MouseLeft, gocui.ModNone, toggleCollapse); err != nil {
|
||||||
// return err
|
// return err
|
||||||
//}
|
//}
|
||||||
if err := g.SetKeybinding("side", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
if err := g.SetKeybinding("", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := g.SetKeybinding("main", gocui.KeyCtrlSpace, gocui.ModNone, toggleView); err != nil {
|
if err := g.SetKeybinding("", gocui.KeyCtrlSlash, gocui.ModNone, toggleFilterView); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := g.SetKeybinding("", gocui.KeyCtrlSlash, gocui.ModNone, focusFilterView); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := g.SetKeybinding("command", gocui.KeyEnter, gocui.ModNone, returnToTreeView); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNewView(errs ...error) bool {
|
||||||
|
for _, err := range errs {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err != nil && err != gocui.ErrUnknownView {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this logic should be refactored into an abstraction that takes care of the math for us
|
||||||
func layout(g *gocui.Gui) error {
|
func layout(g *gocui.Gui) error {
|
||||||
maxX, maxY := g.Size()
|
maxX, maxY := g.Size()
|
||||||
splitCols := maxX / 2
|
splitCols := maxX / 2
|
||||||
@ -143,35 +165,18 @@ func layout(g *gocui.Gui) error {
|
|||||||
bottomRows := 1
|
bottomRows := 1
|
||||||
headerRows := 1
|
headerRows := 1
|
||||||
|
|
||||||
// Layers
|
filterBarHeight := 1
|
||||||
if view, err := g.SetView(Views.Layer.Name, -1, -1+headerRows, splitCols, maxY-bottomRows); err != nil {
|
statusBarHeight := 1
|
||||||
if err != gocui.ErrUnknownView {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if header, err := g.SetView(Views.Layer.Name+"header", -1, -1, splitCols, headerRows); err != nil {
|
|
||||||
if err != gocui.ErrUnknownView {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Views.Layer.Setup(view, header)
|
|
||||||
|
|
||||||
if _, err := g.SetCurrentView(Views.Layer.Name); err != nil {
|
statusBarIndex := 1
|
||||||
return err
|
filterBarIndex := 2
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
var view, header *gocui.View
|
||||||
// Filetree
|
var viewErr, headerErr, err error
|
||||||
if view, err := g.SetView(Views.Tree.Name, splitCols, -1+headerRows, debugCols, maxY-bottomRows); err != nil {
|
|
||||||
if err != gocui.ErrUnknownView {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if header, err := g.SetView(Views.Tree.Name+"header", splitCols, -1, debugCols, headerRows); err != nil {
|
if Views.Filter.hidden {
|
||||||
if err != gocui.ErrUnknownView {
|
bottomRows--
|
||||||
return err
|
filterBarHeight = 0
|
||||||
}
|
|
||||||
Views.Tree.Setup(view, header)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug pane
|
// Debug pane
|
||||||
@ -183,35 +188,70 @@ func layout(g *gocui.Gui) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layers
|
||||||
|
view, viewErr = g.SetView(Views.Layer.Name, -1, -1+headerRows, splitCols, maxY-bottomRows)
|
||||||
|
header, headerErr = g.SetView(Views.Layer.Name+"header", -1, -1, splitCols, headerRows)
|
||||||
|
if isNewView(viewErr, headerErr) {
|
||||||
|
Views.Layer.Setup(view, header)
|
||||||
|
|
||||||
|
if _, err = g.SetCurrentView(Views.Layer.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filetree
|
||||||
|
view, viewErr = g.SetView(Views.Tree.Name, splitCols, -1+headerRows, debugCols, maxY-bottomRows)
|
||||||
|
header, headerErr = g.SetView(Views.Tree.Name+"header", splitCols, -1, debugCols, headerRows)
|
||||||
|
if isNewView(viewErr, headerErr) {
|
||||||
|
Views.Tree.Setup(view, header)
|
||||||
|
}
|
||||||
|
|
||||||
// Status Bar
|
// Status Bar
|
||||||
if view, err := g.SetView(Views.Status.Name, -1, maxY-bottomRows-1, maxX, maxY); err != nil {
|
view, viewErr = g.SetView(Views.Status.Name, -1, maxY-statusBarHeight-statusBarIndex, maxX, maxY-(statusBarIndex-1))
|
||||||
if err != gocui.ErrUnknownView {
|
if isNewView(viewErr, headerErr) {
|
||||||
return err
|
|
||||||
}
|
|
||||||
Views.Status.Setup(view, nil)
|
Views.Status.Setup(view, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter Bar
|
||||||
|
view, viewErr = g.SetView(Views.Filter.Name, len(Views.Filter.headerStr)-1, maxY-filterBarHeight-filterBarIndex, maxX, maxY-(filterBarIndex-1))
|
||||||
|
header, headerErr = g.SetView(Views.Filter.Name+"header", -1, maxY-filterBarHeight - filterBarIndex, len(Views.Filter.headerStr), maxY-(filterBarIndex-1))
|
||||||
|
if isNewView(viewErr, headerErr) {
|
||||||
|
Views.Filter.Setup(view, header)
|
||||||
}
|
}
|
||||||
if view, err := g.SetView(Views.Command.Name, -1, maxY-bottomRows-2, maxX, maxY-1); err != nil {
|
|
||||||
if err != gocui.ErrUnknownView {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Views.Command.Setup(view, nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Update() {
|
||||||
|
for _, view := range Views.lookup {
|
||||||
|
view.Update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Render() {
|
func Render() {
|
||||||
for _, view := range Views.lookup {
|
for _, view := range Views.lookup {
|
||||||
|
if view.IsVisible() {
|
||||||
view.Render()
|
view.Render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderStatusOption(control, title string, selected bool) string {
|
||||||
|
if selected {
|
||||||
|
return Formatting.StatusSelected("▏") + Formatting.StatusControlSelected(control) + Formatting.StatusSelected(" " + title + " ")
|
||||||
|
} else {
|
||||||
|
return Formatting.StatusNormal("▏") + Formatting.StatusControlNormal(control) + Formatting.StatusNormal(" " + title + " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Run(layers []*image.Layer, refTrees []*filetree.FileTree) {
|
func Run(layers []*image.Layer, refTrees []*filetree.FileTree) {
|
||||||
Formatting.StatusBar = color.New(color.ReverseVideo, color.Bold).SprintFunc()
|
Formatting.Selected = color.New(color.ReverseVideo, color.Bold).SprintFunc()
|
||||||
Formatting.Header = color.New(color.Bold).SprintFunc()
|
Formatting.Header = color.New(color.Bold).SprintFunc()
|
||||||
Formatting.Control = color.New(color.Bold).SprintFunc()
|
Formatting.StatusSelected = color.New(color.BgMagenta, color.FgWhite).SprintFunc()
|
||||||
|
Formatting.StatusNormal = color.New(color.ReverseVideo).SprintFunc()
|
||||||
|
Formatting.StatusControlSelected = color.New(color.BgMagenta, color.FgWhite, color.Bold).SprintFunc()
|
||||||
|
Formatting.StatusControlNormal = color.New(color.ReverseVideo, color.Bold).SprintFunc()
|
||||||
Formatting.CompareTop = color.New(color.BgMagenta).SprintFunc()
|
Formatting.CompareTop = color.New(color.BgMagenta).SprintFunc()
|
||||||
Formatting.CompareBottom = color.New(color.BgGreen).SprintFunc()
|
Formatting.CompareBottom = color.New(color.BgGreen).SprintFunc()
|
||||||
|
|
||||||
@ -232,8 +272,8 @@ func Run(layers []*image.Layer, refTrees []*filetree.FileTree) {
|
|||||||
Views.Status = NewStatusView("status", g)
|
Views.Status = NewStatusView("status", g)
|
||||||
Views.lookup[Views.Status.Name] = Views.Status
|
Views.lookup[Views.Status.Name] = Views.Status
|
||||||
|
|
||||||
Views.Command = NewCommandView("command", g)
|
Views.Filter = NewFilterView("command", g)
|
||||||
Views.lookup[Views.Command.Name] = Views.Command
|
Views.lookup[Views.Filter.Name] = Views.Filter
|
||||||
|
|
||||||
g.Cursor = false
|
g.Cursor = false
|
||||||
//g.Mouse = true
|
//g.Mouse = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user