summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Burke <rich.g.burke@gmail.com>2019-05-01 20:58:05 +0100
committerRichard Burke <rich.g.burke@gmail.com>2019-05-01 20:58:05 +0100
commitcffa246f92566fa385373cee82349f84d7c28212 (patch)
tree786c8d5ecd182a0fc383a6396ddcaaa82c328eb4
parent48320a6077a2ab55caa5b6edc56ce606e646f848 (diff)
Show bindings for each action in popup menuHEADmaster
- The displayed bindings can be used to execute actions - User defined mappings are also displayed
-rw-r--r--cmd/grv/commit_view.go1
-rw-r--r--cmd/grv/config.go7
-rw-r--r--cmd/grv/context_menu_view.go100
-rw-r--r--cmd/grv/key_bindings.go5
-rw-r--r--cmd/grv/ref_view.go7
-rw-r--r--cmd/grv/theme.go1
-rw-r--r--cmd/grv/themes.go8
-rw-r--r--doc/documentation.md3
8 files changed, 114 insertions, 18 deletions
diff --git a/cmd/grv/commit_view.go b/cmd/grv/commit_view.go
index 87c3749..9e48e28 100644
--- a/cmd/grv/commit_view.go
+++ b/cmd/grv/commit_view.go
@@ -1016,6 +1016,7 @@ func showActionsForCommit(commitView *CommitView, action Action) (err error) {
cols: 60,
},
config: ContextMenuConfig{
+ ActionView: ViewCommit,
Entries: []ContextMenuEntry{
{
DisplayName: "Checkout commit",
diff --git a/cmd/grv/config.go b/cmd/grv/config.go
index a808739..f53a179 100644
--- a/cmd/grv/config.go
+++ b/cmd/grv/config.go
@@ -222,9 +222,10 @@ var themeComponents = map[string]ThemeComponentID{
cfErrorView + ".Footer": CmpErrorViewFooter,
cfErrorView + ".Errors": CmpErrorViewErrors,
- cfContextMenuView + ".Title": CmpContextMenuTitle,
- cfContextMenuView + ".Content": CmpContextMenuContent,
- cfContextMenuView + ".Footer": CmpContextMenuFooter,
+ cfContextMenuView + ".Title": CmpContextMenuTitle,
+ cfContextMenuView + ".Content": CmpContextMenuContent,
+ cfContextMenuView + ".KeyMapping": CmpContextMenuKeyMapping,
+ cfContextMenuView + ".Footer": CmpContextMenuFooter,
cfCommandOutputView + ".Title": CmpCommandOutputTitle,
cfCommandOutputView + ".Command": CmpCommandOutputCommand,
diff --git a/cmd/grv/context_menu_view.go b/cmd/grv/context_menu_view.go
index aa3835b..46cbceb 100644
--- a/cmd/grv/context_menu_view.go
+++ b/cmd/grv/context_menu_view.go
@@ -21,9 +21,10 @@ type ContextMenuEntry struct {
// ContextMenuConfig is the configuration for the ContextMenuView
// It contains all context menu contextMenuConfig and an observer
type ContextMenuConfig struct {
- Entity string
- Entries []ContextMenuEntry
- OnSelect OnContextMenuEntrySelected
+ Entity string
+ Entries []ContextMenuEntry
+ OnSelect OnContextMenuEntrySelected
+ ActionView ViewID
}
type contextMenuViewHandler func(*ContextMenuView, Action) error
@@ -51,16 +52,65 @@ func NewContextMenuView(contextMenuConfig ContextMenuConfig, channels Channels,
}
contextMenuView.AbstractWindowView = NewAbstractWindowView(contextMenuView, channels, config, variables, &contextMenuView.lock, "menu item")
+ contextMenuView.processConfig()
+
+ return contextMenuView
+}
+
+func (contextMenuView *ContextMenuView) processConfig() {
+ contextMenuConfig := &contextMenuView.contextMenuConfig
if contextMenuConfig.Entity == "" {
- contextMenuView.contextMenuConfig.Entity = "Action"
+ contextMenuConfig.Entity = "Action"
}
- return contextMenuView
+ if contextMenuConfig.ActionView != ViewAll {
+ var keys []string
+ maxKeyWidth := 0
+
+ for i := uint(0); i < contextMenuView.rows(); i++ {
+ entry := &contextMenuConfig.Entries[i]
+ var key string
+
+ if action, ok := entry.Value.(Action); ok {
+ mappings := contextMenuView.config.KeyStrings(action.ActionType, ViewHierarchy{contextMenuConfig.ActionView})
+
+ if len(mappings) > 0 {
+ key = mappings[len(mappings)-1].keystring
+ }
+ }
+
+ if key == "" {
+ key = "None"
+ }
+
+ keys = append(keys, key)
+
+ width := StringWidth(key)
+ if width > maxKeyWidth {
+ maxKeyWidth = width
+ }
+ }
+
+ for keyIndex, key := range keys {
+ if width := StringWidth(key); width < maxKeyWidth {
+ key = fmt.Sprintf("%v%v", key, strings.Repeat(" ", maxKeyWidth-width))
+ }
+
+ entry := &contextMenuConfig.Entries[keyIndex]
+ entry.DisplayName = fmt.Sprintf("%v %v", key, entry.DisplayName)
+ }
+ }
+
+ return
}
// ViewID returns the ViewID of the context menu view
func (contextMenuView *ContextMenuView) ViewID() ViewID {
+ if contextMenuView.contextMenuConfig.ActionView != ViewAll {
+ return contextMenuView.contextMenuConfig.ActionView
+ }
+
return ViewContextMenu
}
@@ -80,18 +130,29 @@ func (contextMenuView *ContextMenuView) Render(win RenderWindow) (err error) {
viewRowIndex := viewPos.ViewStartRowIndex()
startColumn := viewPos.ViewStartColumn()
- for rowIndex := uint(0); rowIndex < winRows && viewRowIndex < viewRows; rowIndex++ {
- entry := contextMenuView.contextMenuConfig.Entries[viewRowIndex]
+ win.ApplyStyle(CmpContextMenuContent)
- if err = win.SetRow(rowIndex+1, startColumn, CmpNone, " %v", entry.DisplayName); err != nil {
+ var lineBuilder *LineBuilder
+ for rowIndex := uint(0); rowIndex < winRows && viewRowIndex < viewRows; rowIndex++ {
+ if lineBuilder, err = win.LineBuilder(rowIndex+1, startColumn); err != nil {
return
}
+ entry := contextMenuView.contextMenuConfig.Entries[viewRowIndex]
+ if contextMenuView.contextMenuConfig.ActionView != ViewAll {
+ if displayParts := strings.SplitN(entry.DisplayName, " ", 2); len(displayParts) == 2 {
+ lineBuilder.AppendWithStyle(CmpContextMenuKeyMapping, " %v ", displayParts[0]).
+ AppendWithStyle(CmpContextMenuContent, "%v", displayParts[1])
+ } else {
+ return fmt.Errorf(`Expected entry of format "key DisplayText" but found %v`, entry.DisplayName)
+ }
+ } else {
+ lineBuilder.AppendWithStyle(CmpContextMenuContent, " %v", entry.DisplayName)
+ }
+
viewRowIndex++
}
- win.ApplyStyle(CmpContextMenuContent)
-
if err = win.SetSelectedRow(viewPos.SelectedRowIndex()+1, ViewStateActive); err != nil {
return
}
@@ -159,6 +220,8 @@ func (contextMenuView *ContextMenuView) HandleAction(action Action) (err error)
err = handler(contextMenuView, action)
} else if handled, err = contextMenuView.AbstractWindowView.HandleAction(action); handled {
log.Debugf("Action handled by AbstractWindowView")
+ } else if handled, err = contextMenuView.handleMenuAction(action); handled {
+ log.Debugf("Menu action handled")
} else {
log.Debugf("Action not handled")
}
@@ -166,6 +229,23 @@ func (contextMenuView *ContextMenuView) HandleAction(action Action) (err error)
return
}
+func (contextMenuView *ContextMenuView) handleMenuAction(action Action) (handled bool, err error) {
+ if contextMenuView.contextMenuConfig.ActionView == ViewAll {
+ return
+ }
+
+ for entryIndex, entry := range contextMenuView.contextMenuConfig.Entries {
+ if entryAction, ok := entry.Value.(Action); ok && entryAction.ActionType == action.ActionType {
+ contextMenuView.viewPos().SetActiveRowIndex(uint(entryIndex))
+ err = selectContextMenuEntry(contextMenuView, Action{ActionType: ActionSelect})
+ handled = true
+ break
+ }
+ }
+
+ return
+}
+
func selectContextMenuEntry(contextMenuView *ContextMenuView, action Action) (err error) {
viewPos := contextMenuView.viewPos()
selectedIndex := viewPos.ActiveRowIndex()
diff --git a/cmd/grv/key_bindings.go b/cmd/grv/key_bindings.go
index 8a9fdcb..b76dbb6 100644
--- a/cmd/grv/key_bindings.go
+++ b/cmd/grv/key_bindings.go
@@ -491,8 +491,11 @@ var actionDescriptors = map[ActionType]ActionDescriptor{
},
ActionCheckoutPreviousRef: {
actionKey: "<grv-checkout-previous-ref>",
- actionCategory: ActionCategoryGeneral,
+ actionCategory: ActionCategoryViewSpecific,
description: "Checkout previous ref",
+ keyBindings: map[ViewID][]string{
+ ViewRef: {"-"},
+ },
},
ActionCheckoutCommit: {
actionKey: "<grv-checkout-commit>",
diff --git a/cmd/grv/ref_view.go b/cmd/grv/ref_view.go
index 68cfa5f..7197d48 100644
--- a/cmd/grv/ref_view.go
+++ b/cmd/grv/ref_view.go
@@ -1362,8 +1362,8 @@ func showActionsForRef(refView *RefView, action Action) (err error) {
head := refView.repoData.Head()
headName := head.Shorthand()
- if StringWidth(headName) > 15 {
- headName = headName[:15] + "..."
+ if StringWidth(headName) > 12 {
+ headName = headName[:12] + "..."
}
if !isHead {
@@ -1393,7 +1393,8 @@ func showActionsForRef(refView *RefView, action Action) (err error) {
cols: 60,
},
config: ContextMenuConfig{
- Entries: contextMenuEntries,
+ ActionView: ViewRef,
+ Entries: contextMenuEntries,
OnSelect: func(entry ContextMenuEntry, entryIndex uint) {
if selectedAction, ok := entry.Value.(Action); ok {
refView.channels.DoAction(selectedAction)
diff --git a/cmd/grv/theme.go b/cmd/grv/theme.go
index ce0d149..9a239b6 100644
--- a/cmd/grv/theme.go
+++ b/cmd/grv/theme.go
@@ -105,6 +105,7 @@ const (
CmpContextMenuTitle
CmpContextMenuContent
+ CmpContextMenuKeyMapping
CmpContextMenuFooter
CmpCommandOutputTitle
diff --git a/cmd/grv/themes.go b/cmd/grv/themes.go
index 48db135..64d3c31 100644
--- a/cmd/grv/themes.go
+++ b/cmd/grv/themes.go
@@ -311,6 +311,10 @@ func NewClassicTheme() MutableTheme {
bgcolor: NewSystemColor(ColorNone),
fgcolor: NewSystemColor(ColorNone),
},
+ CmpContextMenuKeyMapping: {
+ bgcolor: NewSystemColor(ColorNone),
+ fgcolor: NewSystemColor(ColorBlue),
+ },
CmpContextMenuFooter: {
bgcolor: NewSystemColor(ColorNone),
fgcolor: NewSystemColor(ColorCyan),
@@ -795,6 +799,10 @@ func NewSolarizedTheme() MutableTheme {
bgcolor: NewColorNumber(solarizedBlack),
fgcolor: NewColorNumber(solarizedWhite),
},
+ CmpContextMenuKeyMapping: {
+ bgcolor: NewColorNumber(solarizedBlack),
+ fgcolor: NewColorNumber(solarizedBlue),
+ },
CmpContextMenuFooter: {
bgcolor: NewColorNumber(solarizedBlack),
fgcolor: NewColorNumber(solarizedCyan),
diff --git a/doc/documentation.md b/doc/documentation.md
index c510c4d..d6df5c2 100644
--- a/doc/documentation.md
+++ b/doc/documentation.md
@@ -125,7 +125,6 @@ The following tables contain default and user configured key bindings
```
Key Bindings | Action | Description
-------------+------------------------------+--------------------------------------------------
- None | <grv-checkout-previous-ref> | Checkout previous ref
None | <grv-exit> | Exit GRV
: | <grv-prompt> | GRV Command prompt
None | <grv-remove-tab> | Remove the active tab
@@ -140,6 +139,7 @@ The following tables contain default and user configured key bindings
```
Key Bindings | Action | Description
-------------+----------------------------------+--------------------------------------------
+ - | <grv-checkout-previous-ref> | Checkout previous ref
c | <grv-checkout-ref> | Checkout ref
T | <grv-create-annotated-tag> | Create a new annotated tag
B | <grv-create-branch-and-checkout> | Create a new branch and checkout
@@ -590,6 +590,7 @@ CommitView.Title
ContextMenuView.Content
ContextMenuView.Footer
+ContextMenuView.KeyMapping
ContextMenuView.Title
DiffView.AddedLine