mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Add Key type
This bundles the keyName and a rune, so that we don't have to pass these around separately everywhere. This should make it easier to swap out the rune for a string when we upgrade to tcell v3.
This commit is contained in:
@@ -146,7 +146,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
|
||||
return false
|
||||
}
|
||||
|
||||
return (binding.Description != "" || binding.Alternative != "") && binding.Key != nil
|
||||
return (binding.Description != "" || binding.Alternative != "") && binding.Key.IsSet()
|
||||
})
|
||||
|
||||
bindingsByHeader := lo.GroupBy(bindingsToDisplay, func(binding *types.Binding) header {
|
||||
|
||||
@@ -3,6 +3,7 @@ package cheatsheet
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -27,7 +28,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -37,7 +38,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -49,7 +50,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "",
|
||||
Description: "quit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -59,7 +60,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "",
|
||||
Description: "quit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -71,17 +72,17 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "submodules",
|
||||
Description: "drop submodule",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -91,12 +92,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -106,7 +107,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "submodules",
|
||||
Description: "drop submodule",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -118,23 +119,23 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
expected: []*bindingSection{
|
||||
@@ -144,7 +145,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -155,7 +156,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -165,12 +166,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -182,34 +183,34 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "scroll",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "page up",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -220,13 +221,13 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "scroll",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "page up",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tag: "navigation",
|
||||
},
|
||||
},
|
||||
@@ -237,7 +238,7 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "commits",
|
||||
Description: "revert commit",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -247,12 +248,12 @@ func TestGetBindingSections(t *testing.T) {
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "stage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
ViewName: "files",
|
||||
Description: "unstage file",
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+27
-27
@@ -6,64 +6,64 @@ package gocui
|
||||
|
||||
// Editor interface must be satisfied by gocui editors.
|
||||
type Editor interface {
|
||||
Edit(v *View, key KeyName, ch rune, mod Modifier) bool
|
||||
Edit(v *View, key Key, mod Modifier) bool
|
||||
}
|
||||
|
||||
// The EditorFunc type is an adapter to allow the use of ordinary functions as
|
||||
// Editors. If f is a function with the appropriate signature, EditorFunc(f)
|
||||
// is an Editor object that calls f.
|
||||
type EditorFunc func(v *View, key KeyName, ch rune, mod Modifier) bool
|
||||
type EditorFunc func(v *View, key Key, mod Modifier) bool
|
||||
|
||||
// Edit calls f(v, key, ch, mod)
|
||||
func (f EditorFunc) Edit(v *View, key KeyName, ch rune, mod Modifier) bool {
|
||||
return f(v, key, ch, mod)
|
||||
// Edit calls f(v, key, mod)
|
||||
func (f EditorFunc) Edit(v *View, key Key, mod Modifier) bool {
|
||||
return f(v, key, mod)
|
||||
}
|
||||
|
||||
// DefaultEditor is the default editor.
|
||||
var DefaultEditor Editor = EditorFunc(SimpleEditor)
|
||||
|
||||
// SimpleEditor is used as the default gocui editor.
|
||||
func SimpleEditor(v *View, key KeyName, ch rune, mod Modifier) bool {
|
||||
func SimpleEditor(v *View, key Key, mod Modifier) bool {
|
||||
switch {
|
||||
case (key == KeyBackspace || key == KeyBackspace2) && (mod&ModAlt) != 0,
|
||||
key == KeyCtrlW:
|
||||
case (key.KeyName() == KeyBackspace || key.KeyName() == KeyBackspace2) && (mod&ModAlt) != 0,
|
||||
key.KeyName() == KeyCtrlW:
|
||||
v.TextArea.BackSpaceWord()
|
||||
case key == KeyBackspace || key == KeyBackspace2 || key == KeyCtrlH:
|
||||
case key.KeyName() == KeyBackspace || key.KeyName() == KeyBackspace2 || key.KeyName() == KeyCtrlH:
|
||||
v.TextArea.BackSpaceChar()
|
||||
case key == KeyCtrlD || key == KeyDelete:
|
||||
case key.KeyName() == KeyCtrlD || key.KeyName() == KeyDelete:
|
||||
v.TextArea.DeleteChar()
|
||||
case key == KeyArrowDown:
|
||||
case key.KeyName() == KeyArrowDown:
|
||||
v.TextArea.MoveCursorDown()
|
||||
case key == KeyArrowUp:
|
||||
case key.KeyName() == KeyArrowUp:
|
||||
v.TextArea.MoveCursorUp()
|
||||
case (key == KeyArrowLeft || ch == 'b') && (mod&ModAlt) != 0:
|
||||
case (key.KeyName() == KeyArrowLeft || key.Equals(NewKeyRune('b'))) && (mod&ModAlt) != 0:
|
||||
v.TextArea.MoveLeftWord()
|
||||
case key == KeyArrowLeft || key == KeyCtrlB:
|
||||
case key.KeyName() == KeyArrowLeft || key.KeyName() == KeyCtrlB:
|
||||
v.TextArea.MoveCursorLeft()
|
||||
case (key == KeyArrowRight || ch == 'f') && (mod&ModAlt) != 0:
|
||||
case (key.KeyName() == KeyArrowRight || key.Equals(NewKeyRune('f'))) && (mod&ModAlt) != 0:
|
||||
v.TextArea.MoveRightWord()
|
||||
case key == KeyArrowRight || key == KeyCtrlF:
|
||||
case key.KeyName() == KeyArrowRight || key.KeyName() == KeyCtrlF:
|
||||
v.TextArea.MoveCursorRight()
|
||||
case key == KeyEnter:
|
||||
case key.KeyName() == KeyEnter:
|
||||
v.TextArea.TypeCharacter("\n")
|
||||
case key == KeySpace:
|
||||
case key.KeyName() == KeySpace:
|
||||
v.TextArea.TypeCharacter(" ")
|
||||
case key == KeyInsert:
|
||||
case key.KeyName() == KeyInsert:
|
||||
v.TextArea.ToggleOverwrite()
|
||||
case key == KeyCtrlU:
|
||||
case key.KeyName() == KeyCtrlU:
|
||||
v.TextArea.DeleteToStartOfLine()
|
||||
case key == KeyCtrlK:
|
||||
case key.KeyName() == KeyCtrlK:
|
||||
v.TextArea.DeleteToEndOfLine()
|
||||
case key == KeyCtrlA || key == KeyHome:
|
||||
case key.KeyName() == KeyCtrlA || key.KeyName() == KeyHome:
|
||||
v.TextArea.GoToStartOfLine()
|
||||
case key == KeyCtrlE || key == KeyEnd:
|
||||
case key.KeyName() == KeyCtrlE || key.KeyName() == KeyEnd:
|
||||
v.TextArea.GoToEndOfLine()
|
||||
case key == KeyCtrlW:
|
||||
case key.KeyName() == KeyCtrlW:
|
||||
v.TextArea.BackSpaceWord()
|
||||
case key == KeyCtrlY:
|
||||
case key.KeyName() == KeyCtrlY:
|
||||
v.TextArea.Yank()
|
||||
case ch != 0:
|
||||
v.TextArea.TypeCharacter(string(ch))
|
||||
case key.Ch() != 0:
|
||||
v.TextArea.TypeCharacter(string(key.Ch()))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
+30
-57
@@ -175,10 +175,10 @@ type Gui struct {
|
||||
Mutexes GuiMutexes
|
||||
|
||||
OnSearchEscape func() error
|
||||
// these keys must either be of type Key of rune
|
||||
SearchEscapeKey any
|
||||
NextSearchMatchKey any
|
||||
PrevSearchMatchKey any
|
||||
|
||||
SearchEscapeKey Key
|
||||
NextSearchMatchKey Key
|
||||
PrevSearchMatchKey Key
|
||||
|
||||
ErrorHandler func(error) error
|
||||
|
||||
@@ -254,9 +254,9 @@ func NewGui(opts NewGuiOpts) (*Gui, error) {
|
||||
g.SupportOverlaps = opts.SupportOverlaps
|
||||
|
||||
// default keys for when searching strings in a view
|
||||
g.SearchEscapeKey = KeyEsc
|
||||
g.NextSearchMatchKey = 'n'
|
||||
g.PrevSearchMatchKey = 'N'
|
||||
g.SearchEscapeKey = NewKeyName(KeyEsc)
|
||||
g.NextSearchMatchKey = NewKeyRune('n')
|
||||
g.PrevSearchMatchKey = NewKeyRune('N')
|
||||
|
||||
g.playRecording = opts.PlayRecording
|
||||
|
||||
@@ -549,28 +549,16 @@ func (g *Gui) CurrentView() *View {
|
||||
// It behaves differently on different platforms. Somewhere it doesn't register Alt key press,
|
||||
// on others it might report Ctrl as Alt. It's not consistent and therefore it's not recommended
|
||||
// to use with mouse keys.
|
||||
func (g *Gui) SetKeybinding(viewname string, key any, mod Modifier, handler func(*Gui, *View) error) error {
|
||||
var kb *keybinding
|
||||
|
||||
k, ch, err := getKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kb = newKeybinding(viewname, k, ch, mod, handler)
|
||||
func (g *Gui) SetKeybinding(viewname string, key Key, mod Modifier, handler func(*Gui, *View) error) error {
|
||||
kb := newKeybinding(viewname, key, mod, handler)
|
||||
g.keybindings = append(g.keybindings, kb)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteKeybinding deletes a keybinding.
|
||||
func (g *Gui) DeleteKeybinding(viewname string, key any, mod Modifier) error {
|
||||
k, ch, err := getKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func (g *Gui) DeleteKeybinding(viewname string, key Key, mod Modifier) error {
|
||||
for i, kb := range g.keybindings {
|
||||
if kb.viewName == viewname && kb.ch == ch && kb.key == k && kb.mod == mod {
|
||||
if kb.viewName == viewname && kb.key.keyName == key.KeyName() && kb.key.ch == key.ch && kb.mod == mod {
|
||||
g.keybindings = append(g.keybindings[:i], g.keybindings[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
@@ -628,21 +616,6 @@ func (g *Gui) SetRenderSearchStatusFunc(renderSearchStatusFunc func(*View, int,
|
||||
g.renderSearchStatusFunc = renderSearchStatusFunc
|
||||
}
|
||||
|
||||
// getKey takes an empty interface with a key and returns the corresponding
|
||||
// typed Key or rune.
|
||||
func getKey(key any) (KeyName, rune, error) {
|
||||
switch t := key.(type) {
|
||||
case nil: // Ignore keybinding if `nil`
|
||||
return 0, 0, nil
|
||||
case KeyName:
|
||||
return t, 0, nil
|
||||
case rune:
|
||||
return 0, t, nil
|
||||
default:
|
||||
return 0, 0, errors.New("unknown type")
|
||||
}
|
||||
}
|
||||
|
||||
// userEvent represents an event triggered by the user.
|
||||
type userEvent struct {
|
||||
f func(*Gui) error
|
||||
@@ -1301,8 +1274,8 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
|
||||
// seem harmful for other terminal emulators.
|
||||
//
|
||||
// KeyCtrlJ (int value 10) is '\r'.
|
||||
if g.IsPasting && ev.Key == KeyCtrlJ {
|
||||
ev.Key = KeyEnter
|
||||
if g.IsPasting && ev.Key.KeyName() == KeyCtrlJ {
|
||||
ev.Key = NewKeyName(KeyEnter)
|
||||
}
|
||||
|
||||
err := g.execKeybindings(g.currentView, ev)
|
||||
@@ -1343,7 +1316,7 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
|
||||
}
|
||||
}
|
||||
|
||||
if ev.Key == MouseLeft && (ev.Mod&ModMotion) == 0 && !v.Editable && g.openHyperlink != nil {
|
||||
if ev.Key.KeyName() == MouseLeft && (ev.Mod&ModMotion) == 0 && !v.Editable && g.openHyperlink != nil {
|
||||
if newY >= 0 && newY <= len(v.viewLines)-1 && newX >= 0 && newX <= len(v.viewLines[newY].line)-1 {
|
||||
if link := v.viewLines[newY].line[newX].hyperlink; link != "" {
|
||||
return g.openHyperlink(link, v.name)
|
||||
@@ -1352,14 +1325,14 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
|
||||
}
|
||||
|
||||
if g.ShouldHandleMouseEvent != nil {
|
||||
if !g.ShouldHandleMouseEvent(v, ev.Key) {
|
||||
if !g.ShouldHandleMouseEvent(v, ev.Key.KeyName()) {
|
||||
// Give clients a chance to reject clicks, for example clicks in inactive views
|
||||
// when a modal panel is open.
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !IsMouseScrollKey(ev.Key) {
|
||||
if !IsMouseScrollKey(ev.Key.KeyName()) {
|
||||
v.SetCursor(newCx, newCy)
|
||||
if v.Editable {
|
||||
v.TextArea.SetCursor2D(newX, newY)
|
||||
@@ -1387,8 +1360,8 @@ func (g *Gui) onKey(ev *GocuiEvent) error {
|
||||
}
|
||||
|
||||
if IsMouseKey(ev.Key) {
|
||||
isDoubleClick := g.recordClickInfo(newX, newY, ev.Key, v)
|
||||
opts := ViewMouseBindingOpts{X: newX, Y: newY, Key: ev.Key, IsDoubleClick: isDoubleClick}
|
||||
isDoubleClick := g.recordClickInfo(newX, newY, ev.Key.KeyName(), v)
|
||||
opts := ViewMouseBindingOpts{X: newX, Y: newY, Key: ev.Key.KeyName(), IsDoubleClick: isDoubleClick}
|
||||
matched, err := g.execMouseKeybindings(v, ev, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1450,7 +1423,7 @@ func (g *Gui) recordClickInfo(x, y int, key KeyName, v *View) bool {
|
||||
func (g *Gui) execMouseKeybindings(view *View, ev *GocuiEvent, opts ViewMouseBindingOpts) (bool, error) {
|
||||
isMatch := func(binding *ViewMouseBinding) bool {
|
||||
return binding.ViewName == view.Name() &&
|
||||
ev.Key == binding.Key &&
|
||||
ev.Key.KeyName() == binding.Key &&
|
||||
ev.Mod == binding.Modifier
|
||||
}
|
||||
|
||||
@@ -1472,8 +1445,8 @@ func (g *Gui) execMouseKeybindings(view *View, ev *GocuiEvent, opts ViewMouseBin
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func IsMouseKey(key any) bool {
|
||||
switch key {
|
||||
func IsMouseKey(key Key) bool {
|
||||
switch key.KeyName() {
|
||||
case
|
||||
MouseLeft,
|
||||
MouseRight,
|
||||
@@ -1489,8 +1462,8 @@ func IsMouseKey(key any) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func IsMouseScrollKey(key any) bool {
|
||||
switch key {
|
||||
func IsMouseScrollKey(keyName KeyName) bool {
|
||||
switch keyName {
|
||||
case
|
||||
MouseWheelUp,
|
||||
MouseWheelDown,
|
||||
@@ -1514,11 +1487,11 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
|
||||
|
||||
// if we're searching, and we've hit n/N/Esc, we ignore the default keybinding
|
||||
if v != nil && v.IsSearching() && ev.Mod == ModNone {
|
||||
if eventMatchesKey(ev, g.NextSearchMatchKey) {
|
||||
if ev.Key.Equals(g.NextSearchMatchKey) {
|
||||
return v.gotoNextMatch()
|
||||
} else if eventMatchesKey(ev, g.PrevSearchMatchKey) {
|
||||
} else if ev.Key.Equals(g.PrevSearchMatchKey) {
|
||||
return v.gotoPreviousMatch()
|
||||
} else if eventMatchesKey(ev, g.SearchEscapeKey) {
|
||||
} else if ev.Key.Equals(g.SearchEscapeKey) {
|
||||
v.searcher.clearSearch()
|
||||
if g.OnSearchEscape != nil {
|
||||
if err := g.OnSearchEscape(); err != nil {
|
||||
@@ -1535,7 +1508,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
|
||||
if kb.handler == nil {
|
||||
continue
|
||||
}
|
||||
if !kb.matchKeypress(ev.Key, ev.Ch, ev.Mod) {
|
||||
if !kb.matchKeypress(ev.Key, ev.Mod) {
|
||||
continue
|
||||
}
|
||||
if g.matchView(v, kb) {
|
||||
@@ -1550,7 +1523,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
|
||||
if v != nil && g.matchView(v.ParentView, kb) {
|
||||
matchingParentViewKb = kb
|
||||
}
|
||||
if globalKb == nil && kb.viewName == "" && ((v != nil && !v.Editable) || (kb.ch == 0 && kb.key != KeyCtrlU && kb.key != KeyCtrlA && kb.key != KeyCtrlE)) {
|
||||
if globalKb == nil && kb.viewName == "" && ((v != nil && !v.Editable) || (kb.key.keyName != KeyCtrlU && kb.key.keyName != KeyCtrlA && kb.key.keyName != KeyCtrlE)) {
|
||||
globalKb = kb
|
||||
}
|
||||
}
|
||||
@@ -1562,7 +1535,7 @@ func (g *Gui) execKeybindings(v *View, ev *GocuiEvent) error {
|
||||
}
|
||||
|
||||
if g.currentView != nil && g.currentView.Editable && g.currentView.Editor != nil {
|
||||
matched := g.currentView.Editor.Edit(g.currentView, ev.Key, ev.Ch, ev.Mod)
|
||||
matched := g.currentView.Editor.Edit(g.currentView, ev.Key, ev.Mod)
|
||||
if matched {
|
||||
return nil
|
||||
}
|
||||
@@ -1622,7 +1595,7 @@ func (g *Gui) matchView(v *View, kb *keybinding) bool {
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
if v.Editable && kb.ch != 0 {
|
||||
if v.Editable && kb.key.ch != 0 {
|
||||
return false
|
||||
}
|
||||
if kb.viewName != v.name {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2026 The gocui Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gocui
|
||||
|
||||
import "github.com/gdamore/tcell/v2"
|
||||
|
||||
type Key struct {
|
||||
keyName KeyName
|
||||
ch rune
|
||||
}
|
||||
|
||||
func NewKey(keyName KeyName, ch rune) Key {
|
||||
return Key{
|
||||
keyName: keyName,
|
||||
ch: ch,
|
||||
}
|
||||
}
|
||||
|
||||
func NewKeyName(keyName KeyName) Key {
|
||||
return Key{
|
||||
keyName: keyName,
|
||||
ch: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func NewKeyRune(ch rune) Key {
|
||||
return Key{
|
||||
keyName: KeyName(tcell.KeyRune),
|
||||
ch: ch,
|
||||
}
|
||||
}
|
||||
|
||||
func (k Key) KeyName() KeyName {
|
||||
return k.keyName
|
||||
}
|
||||
|
||||
func (k Key) Ch() rune {
|
||||
return k.ch
|
||||
}
|
||||
|
||||
func (k Key) IsSet() bool {
|
||||
return k.keyName != 0
|
||||
}
|
||||
|
||||
func (k Key) Equals(otherKey Key) bool {
|
||||
return k.keyName == otherKey.keyName && k.ch == otherKey.ch
|
||||
}
|
||||
+4
-20
@@ -18,41 +18,25 @@ type Modifier tcell.ModMask
|
||||
// Keybindings are used to link a given key-press event with a handler.
|
||||
type keybinding struct {
|
||||
viewName string
|
||||
key KeyName
|
||||
ch rune
|
||||
key Key
|
||||
mod Modifier
|
||||
handler func(*Gui, *View) error
|
||||
}
|
||||
|
||||
// newKeybinding returns a new Keybinding object.
|
||||
func newKeybinding(viewname string, key KeyName, ch rune, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) {
|
||||
func newKeybinding(viewname string, key Key, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) {
|
||||
kb = &keybinding{
|
||||
viewName: viewname,
|
||||
key: key,
|
||||
ch: ch,
|
||||
mod: mod,
|
||||
handler: handler,
|
||||
}
|
||||
return kb
|
||||
}
|
||||
|
||||
func eventMatchesKey(ev *GocuiEvent, key any) bool {
|
||||
// assuming ModNone for now
|
||||
if ev.Mod != ModNone {
|
||||
return false
|
||||
}
|
||||
|
||||
k, ch, err := getKey(key)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return k == ev.Key && ch == ev.Ch
|
||||
}
|
||||
|
||||
// matchKeypress returns if the keybinding matches the keypress.
|
||||
func (kb *keybinding) matchKeypress(keyName KeyName, ch rune, mod Modifier) bool {
|
||||
return kb.key == keyName && kb.ch == ch && kb.mod == mod
|
||||
func (kb *keybinding) matchKeypress(key Key, mod Modifier) bool {
|
||||
return kb.key.Equals(key) && kb.mod == mod
|
||||
}
|
||||
|
||||
// Special keys.
|
||||
|
||||
@@ -162,8 +162,7 @@ type gocuiEventType uint8
|
||||
type GocuiEvent struct {
|
||||
Type gocuiEventType
|
||||
Mod Modifier
|
||||
Key KeyName
|
||||
Ch rune
|
||||
Key Key
|
||||
Width int
|
||||
Height int
|
||||
Err error
|
||||
@@ -292,7 +291,6 @@ func (g *Gui) pollEvent() GocuiEvent {
|
||||
k := tev.Key()
|
||||
ch := rune(0)
|
||||
if k == tcell.KeyRune {
|
||||
k = 0 // if rune remove key (so it can match rune instead of key)
|
||||
ch = tev.Rune()
|
||||
if ch == ' ' {
|
||||
// special handling for spacebar
|
||||
@@ -329,8 +327,7 @@ func (g *Gui) pollEvent() GocuiEvent {
|
||||
|
||||
return GocuiEvent{
|
||||
Type: eventKey,
|
||||
Key: KeyName(k),
|
||||
Ch: ch,
|
||||
Key: NewKey(KeyName(k), ch),
|
||||
Mod: Modifier(mod),
|
||||
}
|
||||
case *tcell.EventMouse:
|
||||
@@ -413,8 +410,7 @@ func (g *Gui) pollEvent() GocuiEvent {
|
||||
Type: eventMouse,
|
||||
MouseX: x,
|
||||
MouseY: y,
|
||||
Key: mouseKey,
|
||||
Ch: 0,
|
||||
Key: NewKeyName(mouseKey),
|
||||
Mod: mouseMod,
|
||||
}
|
||||
case *tcell.EventFocus:
|
||||
|
||||
@@ -138,7 +138,7 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
|
||||
}
|
||||
|
||||
keyLabel := ""
|
||||
if item.Key != nil {
|
||||
if item.Key.IsSet() {
|
||||
keyLabel = style.FgCyan.Sprint(keybindings.LabelFromKey(item.Key))
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func (self *MenuViewModel) GetNonModelItems() []*NonModelItem {
|
||||
func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
basicBindings := self.ListContextTrait.GetKeybindings(opts)
|
||||
menuItemsWithKeys := lo.Filter(self.menuItems, func(item *types.MenuItem, _ int) bool {
|
||||
return item.Key != nil
|
||||
return item.Key.IsSet()
|
||||
})
|
||||
|
||||
menuItemBindings := lo.Map(menuItemsWithKeys, func(item *types.MenuItem, _ int) *types.Binding {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
@@ -163,14 +164,14 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
|
||||
OnPress: func() error {
|
||||
return self.copyCommitSubjectToClipboard(commit)
|
||||
},
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.CommitMessage,
|
||||
OnPress: func() error {
|
||||
return self.copyCommitMessageToClipboard(commit)
|
||||
},
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.CommitMessageBody,
|
||||
@@ -178,28 +179,28 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
|
||||
OnPress: func() error {
|
||||
return self.copyCommitMessageBodyToClipboard(commitMessageBody)
|
||||
},
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.CommitURL,
|
||||
OnPress: func() error {
|
||||
return self.copyCommitURLToClipboard(commit)
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.CommitDiff,
|
||||
OnPress: func() error {
|
||||
return self.copyCommitDiffToClipboard(commit)
|
||||
},
|
||||
Key: 'd',
|
||||
Key: gocui.NewKeyRune('d'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.CommitAuthor,
|
||||
OnPress: func() error {
|
||||
return self.copyAuthorToClipboard(commit)
|
||||
},
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
|
||||
OnPress: func() error {
|
||||
return self.copyCommitTagsToClipboard(commit)
|
||||
},
|
||||
Key: 't',
|
||||
Key: gocui.NewKeyRune('t'),
|
||||
}
|
||||
|
||||
if len(commit.Tags) == 0 {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
@@ -101,7 +102,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortHashToMark, info.OldTerm()),
|
||||
@@ -114,7 +115,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 'g',
|
||||
Key: gocui.NewKeyRune('g'),
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortHashToMark),
|
||||
@@ -127,7 +128,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
},
|
||||
}
|
||||
if info.GetCurrentHash() != "" && info.GetCurrentHash() != commit.Hash() {
|
||||
@@ -142,7 +143,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'S',
|
||||
Key: gocui.NewKeyRune('S'),
|
||||
}))
|
||||
}
|
||||
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
|
||||
@@ -150,7 +151,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
OnPress: func() error {
|
||||
return self.c.Helpers().Bisect.Reset()
|
||||
},
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
}))
|
||||
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
@@ -179,7 +180,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortHash(), info.OldTerm()),
|
||||
@@ -197,7 +198,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'g',
|
||||
Key: gocui.NewKeyRune('g'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.Bisect.ChooseTerms,
|
||||
@@ -222,7 +223,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
})
|
||||
return nil
|
||||
},
|
||||
Key: 't',
|
||||
Key: gocui.NewKeyRune('t'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -300,7 +300,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
)
|
||||
viewDivergenceFromBaseBranchItem := &types.MenuItem{
|
||||
LabelColumns: []string{label},
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
OnPress: func() error {
|
||||
branch := self.context().GetSelected()
|
||||
if branch == nil {
|
||||
@@ -333,7 +333,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
})
|
||||
return nil
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
}
|
||||
|
||||
setUpstreamItem := &types.MenuItem{
|
||||
@@ -358,7 +358,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
}
|
||||
|
||||
upstreamResetOptions := utils.ResolvePlaceholderString(
|
||||
@@ -391,7 +391,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
return nil
|
||||
},
|
||||
Tooltip: upstreamResetTooltip,
|
||||
Key: 'g',
|
||||
Key: gocui.NewKeyRune('g'),
|
||||
}
|
||||
|
||||
upstreamRebaseItem := &types.MenuItem{
|
||||
@@ -404,7 +404,7 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
|
||||
return nil
|
||||
},
|
||||
Tooltip: upstreamRebaseTooltip,
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
}
|
||||
|
||||
if !selectedBranch.IsTrackingRemote() {
|
||||
@@ -624,7 +624,7 @@ func (self *BranchesController) delete(branches []*models.Branch) error {
|
||||
|
||||
localDeleteItem := &types.MenuItem{
|
||||
Label: lo.Ternary(len(branches) > 1, self.c.Tr.DeleteLocalBranches, self.c.Tr.DeleteLocalBranch),
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
OnPress: func() error {
|
||||
return self.localDelete(branches)
|
||||
},
|
||||
@@ -635,7 +635,7 @@ func (self *BranchesController) delete(branches []*models.Branch) error {
|
||||
|
||||
remoteDeleteItem := &types.MenuItem{
|
||||
Label: lo.Ternary(len(branches) > 1, self.c.Tr.DeleteRemoteBranches, self.c.Tr.DeleteRemoteBranch),
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
OnPress: func() error {
|
||||
return self.remoteDelete(branches)
|
||||
},
|
||||
@@ -648,7 +648,7 @@ func (self *BranchesController) delete(branches []*models.Branch) error {
|
||||
|
||||
deleteBothItem := &types.MenuItem{
|
||||
Label: lo.Ternary(len(branches) > 1, self.c.Tr.DeleteLocalAndRemoteBranches, self.c.Tr.DeleteLocalAndRemoteBranch),
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
OnPress: func() error {
|
||||
return self.localAndRemoteDelete(branches)
|
||||
},
|
||||
|
||||
@@ -119,7 +119,7 @@ func (self *CommitDescriptionController) handleTogglePanel() error {
|
||||
// which is common in pasted code snippets.
|
||||
view := self.Context().GetView()
|
||||
for range 4 {
|
||||
view.Editor.Edit(view, gocui.KeySpace, ' ', 0)
|
||||
view.Editor.Edit(view, gocui.NewKeyRune(' '), 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ func (self *CommitMessageController) handleTogglePanel() error {
|
||||
// switch to the description panel.
|
||||
view := self.context().GetView()
|
||||
for range 4 {
|
||||
view.Editor.Edit(view, gocui.KeySpace, ' ', 0)
|
||||
view.Editor.Edit(view, gocui.NewKeyRune(' '), 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'n',
|
||||
Key: gocui.NewKeyRune('n'),
|
||||
}
|
||||
copyRelativePathItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyRelativeFilePath,
|
||||
@@ -242,7 +242,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'p',
|
||||
Key: gocui.NewKeyRune('p'),
|
||||
}
|
||||
copyAbsolutePathItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyAbsoluteFilePath,
|
||||
@@ -258,7 +258,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'P',
|
||||
Key: gocui.NewKeyRune('P'),
|
||||
}
|
||||
copyFileDiffItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopySelectedDiff,
|
||||
@@ -266,7 +266,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
return self.copyDiffToClipboard(node.GetPath(), self.c.Tr.FileDiffCopiedToast)
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
}
|
||||
copyAllDiff := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyAllFilesDiff,
|
||||
@@ -274,7 +274,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
return self.copyDiffToClipboard(".", self.c.Tr.AllFilesDiffCopiedToast)
|
||||
},
|
||||
DisabledReason: self.require(self.itemsSelected())(),
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
}
|
||||
copyFileContentItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyFileContent,
|
||||
@@ -295,7 +295,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
||||
}
|
||||
return nil
|
||||
}))(),
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
}
|
||||
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
|
||||
@@ -31,19 +31,19 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
Label: self.c.Tr.ResetPatch,
|
||||
Tooltip: self.c.Tr.ResetPatchTooltip,
|
||||
OnPress: self.c.Helpers().PatchBuilding.Reset,
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.ApplyPatch,
|
||||
Tooltip: self.c.Tr.ApplyPatchTooltip,
|
||||
OnPress: func() error { return self.handleApplyPatch(false) },
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.ApplyPatchInReverse,
|
||||
Tooltip: self.c.Tr.ApplyPatchInReverseTooltip,
|
||||
OnPress: func() error { return self.handleApplyPatch(true) },
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -53,25 +53,25 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
Label: fmt.Sprintf(self.c.Tr.RemovePatchFromOriginalCommit, utils.ShortHash(self.c.Git().Patch.PatchBuilder.To)),
|
||||
Tooltip: self.c.Tr.RemovePatchFromOriginalCommitTooltip,
|
||||
OnPress: self.handleDeletePatchFromCommit,
|
||||
Key: 'd',
|
||||
Key: gocui.NewKeyRune('d'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.MovePatchOutIntoIndex,
|
||||
Tooltip: self.c.Tr.MovePatchOutIntoIndexTooltip,
|
||||
OnPress: self.handleMovePatchIntoWorkingTree,
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.MovePatchIntoNewCommit,
|
||||
Tooltip: self.c.Tr.MovePatchIntoNewCommitTooltip,
|
||||
OnPress: self.handlePullPatchIntoNewCommit,
|
||||
Key: 'n',
|
||||
Key: gocui.NewKeyRune('n'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.MovePatchIntoNewCommitBefore,
|
||||
Tooltip: self.c.Tr.MovePatchIntoNewCommitBeforeTooltip,
|
||||
OnPress: self.handlePullPatchIntoNewCommitBefore,
|
||||
Key: 'N',
|
||||
Key: gocui.NewKeyRune('N'),
|
||||
},
|
||||
}...)
|
||||
|
||||
@@ -93,7 +93,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Hash()),
|
||||
Tooltip: self.c.Tr.MovePatchToSelectedCommitTooltip,
|
||||
OnPress: self.handleMovePatchToSelectedCommit,
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
DisabledReason: disabledReason,
|
||||
},
|
||||
}, menuItems[1:]...,
|
||||
@@ -107,7 +107,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
{
|
||||
Label: self.c.Tr.CopyPatchToClipboard,
|
||||
OnPress: func() error { return self.copyPatchToClipboard() },
|
||||
Key: 'y',
|
||||
Key: gocui.NewKeyRune('y'),
|
||||
},
|
||||
}...)
|
||||
|
||||
|
||||
@@ -671,14 +671,14 @@ func (self *FilesController) handleNonInlineConflict(file *models.File) error {
|
||||
OnPress: func() error {
|
||||
return handle(self.c.Git().WorkingTree.StageFile, self.c.Tr.Actions.ResolveConflictByKeepingFile)
|
||||
},
|
||||
Key: 'k',
|
||||
Key: gocui.NewKeyRune('k'),
|
||||
}
|
||||
deleteItem := &types.MenuItem{
|
||||
Label: self.c.Tr.MergeConflictDeleteFile,
|
||||
OnPress: func() error {
|
||||
return handle(self.c.Git().WorkingTree.RemoveConflictedFile, self.c.Tr.Actions.ResolveConflictByDeletingFile)
|
||||
},
|
||||
Key: 'd',
|
||||
Key: gocui.NewKeyRune('d'),
|
||||
}
|
||||
items := []*types.MenuItem{}
|
||||
switch file.ShortStatus {
|
||||
@@ -856,7 +856,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{self.c.Tr.ExcludeFile},
|
||||
@@ -866,7 +866,7 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Key: 'e',
|
||||
Key: gocui.NewKeyRune('e'),
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -950,7 +950,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayStaged)
|
||||
},
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
Widget: types.MakeMenuRadioButton(currentFilter == filetree.DisplayStaged),
|
||||
},
|
||||
{
|
||||
@@ -958,7 +958,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayUnstaged)
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
Widget: types.MakeMenuRadioButton(currentFilter == filetree.DisplayUnstaged),
|
||||
},
|
||||
{
|
||||
@@ -966,7 +966,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayTracked)
|
||||
},
|
||||
Key: 't',
|
||||
Key: gocui.NewKeyRune('t'),
|
||||
Widget: types.MakeMenuRadioButton(currentFilter == filetree.DisplayTracked),
|
||||
},
|
||||
{
|
||||
@@ -974,7 +974,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayUntracked)
|
||||
},
|
||||
Key: 'T',
|
||||
Key: gocui.NewKeyRune('T'),
|
||||
Widget: types.MakeMenuRadioButton(currentFilter == filetree.DisplayUntracked),
|
||||
},
|
||||
{
|
||||
@@ -982,7 +982,7 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayAll)
|
||||
},
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
Widget: types.MakeMenuRadioButton(currentFilter == filetree.DisplayAll),
|
||||
},
|
||||
},
|
||||
@@ -1092,7 +1092,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
}
|
||||
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges)
|
||||
},
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.StashAllChangesKeepIndex,
|
||||
@@ -1103,14 +1103,14 @@ func (self *FilesController) createStashMenu() error {
|
||||
// if there are no staged files it behaves the same as Stash.Save
|
||||
return self.handleStashSave(self.c.Git().Stash.StashAndKeepIndex, self.c.Tr.Actions.StashAllChangesKeepIndex)
|
||||
},
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.StashIncludeUntrackedChanges,
|
||||
OnPress: func() error {
|
||||
return self.handleStashSave(self.c.Git().Stash.StashIncludeUntrackedChanges, self.c.Tr.Actions.StashIncludeUntrackedChanges)
|
||||
},
|
||||
Key: 'U',
|
||||
Key: gocui.NewKeyRune('U'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.StashStagedChanges,
|
||||
@@ -1121,7 +1121,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
}
|
||||
return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges)
|
||||
},
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.StashUnstagedChanges,
|
||||
@@ -1135,7 +1135,7 @@ func (self *FilesController) createStashMenu() error {
|
||||
// ordinary stash
|
||||
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashUnstagedChanges)
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1182,7 +1182,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'n',
|
||||
Key: gocui.NewKeyRune('n'),
|
||||
}
|
||||
copyRelativePathItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyRelativeFilePath,
|
||||
@@ -1194,7 +1194,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'p',
|
||||
Key: gocui.NewKeyRune('p'),
|
||||
}
|
||||
copyAbsolutePathItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyAbsoluteFilePath,
|
||||
@@ -1210,7 +1210,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'P',
|
||||
Key: gocui.NewKeyRune('P'),
|
||||
}
|
||||
copyFileDiffItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopySelectedDiff,
|
||||
@@ -1236,7 +1236,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
))(),
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
}
|
||||
copyAllDiff := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyAllFilesDiff,
|
||||
@@ -1261,7 +1261,7 @@ func (self *FilesController) openCopyMenu() error {
|
||||
return nil
|
||||
},
|
||||
)(),
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
}
|
||||
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
@@ -1534,7 +1534,7 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
|
||||
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.WORKTREES}})
|
||||
return nil
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.DiscardUnstagedTooltip,
|
||||
map[string]string{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
@@ -82,22 +83,22 @@ func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) er
|
||||
{
|
||||
Label: "start feature",
|
||||
OnPress: startHandler("feature"),
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
},
|
||||
{
|
||||
Label: "start hotfix",
|
||||
OnPress: startHandler("hotfix"),
|
||||
Key: 'h',
|
||||
Key: gocui.NewKeyRune('h'),
|
||||
},
|
||||
{
|
||||
Label: "start bugfix",
|
||||
OnPress: startHandler("bugfix"),
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
},
|
||||
{
|
||||
Label: "start release",
|
||||
OnPress: startHandler("release"),
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -228,7 +228,7 @@ func (self *CommitsHelper) OpenCommitMenu(suggestionFunc func(string) []*types.S
|
||||
OnPress: func() error {
|
||||
return self.SwitchToEditor()
|
||||
},
|
||||
Key: 'e',
|
||||
Key: gocui.NewKeyRune('e'),
|
||||
DisabledReason: disabledReasonForOpenInEditor,
|
||||
},
|
||||
{
|
||||
@@ -236,14 +236,14 @@ func (self *CommitsHelper) OpenCommitMenu(suggestionFunc func(string) []*types.S
|
||||
OnPress: func() error {
|
||||
return self.addCoAuthor(suggestionFunc)
|
||||
},
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.PasteCommitMessageFromClipboard,
|
||||
OnPress: func() error {
|
||||
return self.pasteCommitMessageFromClipboard()
|
||||
},
|
||||
Key: 'p',
|
||||
Key: gocui.NewKeyRune('p'),
|
||||
},
|
||||
}
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
|
||||
@@ -39,17 +39,17 @@ const (
|
||||
func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error {
|
||||
type optionAndKey struct {
|
||||
option string
|
||||
key types.Key
|
||||
key gocui.Key
|
||||
}
|
||||
|
||||
options := []optionAndKey{
|
||||
{option: REBASE_OPTION_CONTINUE, key: 'c'},
|
||||
{option: REBASE_OPTION_ABORT, key: 'a'},
|
||||
{option: REBASE_OPTION_CONTINUE, key: gocui.NewKeyRune('c')},
|
||||
{option: REBASE_OPTION_ABORT, key: gocui.NewKeyRune('a')},
|
||||
}
|
||||
|
||||
if self.c.Git().Status.WorkingTreeState().CanSkip() {
|
||||
options = append(options, optionAndKey{
|
||||
option: REBASE_OPTION_SKIP, key: 's',
|
||||
option: REBASE_OPTION_SKIP, key: gocui.NewKeyRune('s'),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func (self *MergeAndRebaseHelper) PromptForConflictHandling() error {
|
||||
OnPress: func() error {
|
||||
return self.genericMergeCommand(REBASE_OPTION_ABORT)
|
||||
},
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
},
|
||||
},
|
||||
HideCancel: true,
|
||||
@@ -284,7 +284,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.SimpleRebase,
|
||||
map[string]string{"ref": ref},
|
||||
),
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
DisabledReason: disabledReason,
|
||||
OnPress: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.RebaseBranch)
|
||||
@@ -308,7 +308,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.InteractiveRebase,
|
||||
map[string]string{"ref": ref},
|
||||
),
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
DisabledReason: disabledReason,
|
||||
Tooltip: self.c.Tr.InteractiveRebaseTooltip,
|
||||
OnPress: func() error {
|
||||
@@ -334,7 +334,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
||||
Label: utils.ResolvePlaceholderString(self.c.Tr.RebaseOntoBaseBranch,
|
||||
map[string]string{"baseBranch": ShortBranchName(baseBranch)},
|
||||
),
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
DisabledReason: baseBranchDisabledReason,
|
||||
Tooltip: self.c.Tr.RebaseOntoBaseBranchTooltip,
|
||||
OnPress: func() error {
|
||||
@@ -392,7 +392,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
firstRegularMergeItem = &types.MenuItem{
|
||||
Label: self.c.Tr.RegularMergeFastForward,
|
||||
OnPress: self.RegularMerge(refName, git_commands.MERGE_VARIANT_REGULAR),
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.RegularMergeFastForwardTooltip,
|
||||
map[string]string{
|
||||
@@ -406,7 +406,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
secondRegularMergeItem = &types.MenuItem{
|
||||
Label: self.c.Tr.RegularMergeNonFastForward,
|
||||
OnPress: self.RegularMerge(refName, git_commands.MERGE_VARIANT_NON_FAST_FORWARD),
|
||||
Key: 'n',
|
||||
Key: gocui.NewKeyRune('n'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.RegularMergeNonFastForwardTooltip,
|
||||
map[string]string{
|
||||
@@ -419,7 +419,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
firstRegularMergeItem = &types.MenuItem{
|
||||
Label: self.c.Tr.RegularMergeNonFastForward,
|
||||
OnPress: self.RegularMerge(refName, git_commands.MERGE_VARIANT_REGULAR),
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.RegularMergeNonFastForwardTooltip,
|
||||
map[string]string{
|
||||
@@ -432,7 +432,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
secondRegularMergeItem = &types.MenuItem{
|
||||
Label: self.c.Tr.RegularMergeFastForward,
|
||||
OnPress: self.RegularMerge(refName, git_commands.MERGE_VARIANT_FAST_FORWARD),
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.RegularMergeFastForwardTooltip,
|
||||
map[string]string{
|
||||
@@ -464,7 +464,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
{
|
||||
Label: self.c.Tr.SquashMergeUncommitted,
|
||||
OnPress: self.SquashMergeUncommitted(refName),
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.SquashMergeUncommittedTooltip,
|
||||
map[string]string{
|
||||
@@ -475,7 +475,7 @@ func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) e
|
||||
{
|
||||
Label: self.c.Tr.SquashMergeCommitted,
|
||||
OnPress: self.SquashMergeCommitted(refName, checkedOutBranchName),
|
||||
Key: 'S',
|
||||
Key: gocui.NewKeyRune('S'),
|
||||
Tooltip: utils.ResolvePlaceholderString(
|
||||
self.c.Tr.SquashMergeCommittedTooltip,
|
||||
map[string]string{
|
||||
|
||||
@@ -216,15 +216,15 @@ func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string
|
||||
|
||||
func (self *RefsHelper) CreateSortOrderMenu(sortOptionsOrder []string, menuPrompt string, onSelected func(sortOrder string) error, currentValue string) error {
|
||||
type sortMenuOption struct {
|
||||
key types.Key
|
||||
key gocui.Key
|
||||
label string
|
||||
description string
|
||||
sortOrder string
|
||||
}
|
||||
availableSortOptions := map[string]sortMenuOption{
|
||||
"recency": {label: self.c.Tr.SortByRecency, description: self.c.Tr.SortBasedOnReflog, key: 'r'},
|
||||
"alphabetical": {label: self.c.Tr.SortAlphabetical, description: "--sort=refname", key: 'a'},
|
||||
"date": {label: self.c.Tr.SortByDate, description: "--sort=-committerdate", key: 'd'},
|
||||
"recency": {label: self.c.Tr.SortByRecency, description: self.c.Tr.SortBasedOnReflog, key: gocui.NewKeyRune('r')},
|
||||
"alphabetical": {label: self.c.Tr.SortAlphabetical, description: "--sort=refname", key: gocui.NewKeyRune('a')},
|
||||
"date": {label: self.c.Tr.SortByDate, description: "--sort=-committerdate", key: gocui.NewKeyRune('d')},
|
||||
}
|
||||
sortOptions := make([]sortMenuOption, 0, len(sortOptionsOrder))
|
||||
for _, key := range sortOptionsOrder {
|
||||
@@ -260,14 +260,14 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
|
||||
type strengthWithKey struct {
|
||||
strength string
|
||||
label string
|
||||
key types.Key
|
||||
key gocui.Key
|
||||
tooltip string
|
||||
}
|
||||
strengths := []strengthWithKey{
|
||||
// not i18'ing because it's git terminology
|
||||
{strength: "mixed", label: "Mixed reset", key: 'm', tooltip: self.c.Tr.ResetMixedTooltip},
|
||||
{strength: "soft", label: "Soft reset", key: 's', tooltip: self.c.Tr.ResetSoftTooltip},
|
||||
{strength: "hard", label: "Hard reset", key: 'h', tooltip: self.c.Tr.ResetHardTooltip},
|
||||
{strength: "mixed", label: "Mixed reset", key: gocui.NewKeyRune('m'), tooltip: self.c.Tr.ResetMixedTooltip},
|
||||
{strength: "soft", label: "Soft reset", key: gocui.NewKeyRune('s'), tooltip: self.c.Tr.ResetSoftTooltip},
|
||||
{strength: "hard", label: "Hard reset", key: gocui.NewKeyRune('h'), tooltip: self.c.Tr.ResetHardTooltip},
|
||||
}
|
||||
|
||||
menuItems := lo.Map(strengths, func(row strengthWithKey, _ int) *types.MenuItem {
|
||||
@@ -312,15 +312,15 @@ func (self *RefsHelper) CreateCheckoutMenu(commit *models.Commit) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CheckoutCommit)
|
||||
return self.CheckoutRef(hash, types.CheckoutRefOptions{})
|
||||
},
|
||||
Key: 'd',
|
||||
Key: gocui.NewKeyRune('d'),
|
||||
},
|
||||
}
|
||||
|
||||
if len(branches) > 0 {
|
||||
menuItems = append(menuItems, lo.Map(branches, func(branch *models.Branch, index int) *types.MenuItem {
|
||||
var key types.Key
|
||||
var key gocui.Key
|
||||
if index < 9 {
|
||||
key = rune(index + 1 + '0') // Convert 1-based index to key
|
||||
key = gocui.NewKeyRune(rune(index + 1 + '0')) // Convert 1-based index to key
|
||||
}
|
||||
return &types.MenuItem{
|
||||
LabelColumns: []string{fmt.Sprintf(self.c.Tr.Actions.CheckoutBranchAtCommit, branch.Name)},
|
||||
@@ -336,7 +336,7 @@ func (self *RefsHelper) CreateCheckoutMenu(commit *models.Commit) error {
|
||||
LabelColumns: []string{self.c.Tr.Actions.CheckoutBranch},
|
||||
OnPress: func() error { return nil },
|
||||
DisabledReason: &types.DisabledReason{Text: self.c.Tr.NoBranchesFoundAtCommitTooltip},
|
||||
Key: '1',
|
||||
Key: gocui.NewKeyRune('1'),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@@ -382,7 +383,7 @@ func (self *WorkingTreeHelper) CreateMergeConflictMenu(selectedFilepaths []strin
|
||||
OnPress: func() error {
|
||||
return onMergeStrategySelected("--ours")
|
||||
},
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -392,7 +393,7 @@ func (self *WorkingTreeHelper) CreateMergeConflictMenu(selectedFilepaths []strin
|
||||
OnPress: func() error {
|
||||
return onMergeStrategySelected("--theirs")
|
||||
},
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -402,7 +403,7 @@ func (self *WorkingTreeHelper) CreateMergeConflictMenu(selectedFilepaths []strin
|
||||
OnPress: func() error {
|
||||
return onMergeStrategySelected("--union")
|
||||
},
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -410,7 +411,7 @@ func (self *WorkingTreeHelper) CreateMergeConflictMenu(selectedFilepaths []strin
|
||||
cmdColor.Sprint("git mergetool"),
|
||||
},
|
||||
OnPress: self.OpenMergeTool,
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -361,7 +361,7 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.Fixup,
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
OnPress: func() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.FixupCommit)
|
||||
@@ -372,7 +372,7 @@ func (self *LocalCommitsController) fixup(selectedCommits []*models.Commit, star
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.FixupKeepMessage,
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
OnPress: func() error {
|
||||
return self.c.WithWaitingStatus(self.c.Tr.FixingStatus, func(gocui.Task) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.FixupCommitKeepMessage)
|
||||
@@ -403,7 +403,7 @@ func (self *LocalCommitsController) setFixupMessage(commit *models.Commit) error
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.FixupDiscardMessage,
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
OnPress: func() error {
|
||||
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "")
|
||||
},
|
||||
@@ -411,7 +411,7 @@ func (self *LocalCommitsController) setFixupMessage(commit *models.Commit) error
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.FixupKeepMessage,
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
OnPress: func() error {
|
||||
return self.updateTodosWithFlag(todo.Fixup, []*models.Commit{commit}, "-C")
|
||||
},
|
||||
@@ -1000,7 +1000,7 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.FixupMenu_Fixup,
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
OnPress: func() error {
|
||||
return self.c.Helpers().WorkingTree.WithEnsureCommittableFiles(func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.CreateFixupCommit)
|
||||
@@ -1024,7 +1024,7 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.FixupMenu_AmendWithChanges,
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
OnPress: func() error {
|
||||
return self.c.Helpers().WorkingTree.WithEnsureCommittableFiles(func() error {
|
||||
return self.createAmendCommit(commit, true)
|
||||
@@ -1035,7 +1035,7 @@ func (self *LocalCommitsController) createFixupCommit(commit *models.Commit) err
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.FixupMenu_AmendWithoutChanges,
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
OnPress: func() error { return self.createAmendCommit(commit, false) },
|
||||
Tooltip: self.c.Tr.FixupMenu_AmendWithoutChangesTooltip,
|
||||
},
|
||||
@@ -1134,14 +1134,14 @@ func (self *LocalCommitsController) squashFixupCommits() error {
|
||||
Label: self.c.Tr.SquashCommitsInCurrentBranch,
|
||||
OnPress: self.squashAllFixupsInCurrentBranch,
|
||||
DisabledReason: self.canFindCommitForSquashFixupsInCurrentBranch(),
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
Tooltip: self.c.Tr.SquashCommitsInCurrentBranchTooltip,
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.SquashCommitsAboveSelectedCommit,
|
||||
OnPress: self.withItem(self.squashAllFixupsAboveSelectedCommit),
|
||||
DisabledReason: self.singleItemSelected()(),
|
||||
Key: 'a',
|
||||
Key: gocui.NewKeyRune('a'),
|
||||
Tooltip: self.c.Tr.SquashCommitsAboveSelectedTooltip,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewPromptController(
|
||||
func (self *PromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: gocui.KeyEnter,
|
||||
Key: gocui.NewKeyName(gocui.KeyEnter),
|
||||
Handler: func() error { return self.context().State.OnConfirm() },
|
||||
Description: self.c.Tr.Confirm,
|
||||
DisplayOnScreen: true,
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewSearchPromptController(
|
||||
func (self *SearchPromptController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Key: gocui.KeyEnter,
|
||||
Key: gocui.NewKeyName(gocui.KeyEnter),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.confirm,
|
||||
},
|
||||
|
||||
@@ -94,7 +94,6 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: nil,
|
||||
Handler: self.easterEgg,
|
||||
Description: self.c.Tr.EasterEgg,
|
||||
},
|
||||
@@ -234,7 +233,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 'i',
|
||||
Key: gocui.NewKeyRune('i'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{self.c.Tr.BulkUpdateSubmodules, style.FgYellow.Sprint(self.c.Git().Submodule.BulkUpdateCmdObj().ToString())},
|
||||
@@ -249,7 +248,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{self.c.Tr.BulkUpdateRecursiveSubmodules, style.FgYellow.Sprint(self.c.Git().Submodule.BulkUpdateRecursivelyCmdObj().ToString())},
|
||||
@@ -264,7 +263,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{self.c.Tr.BulkDeinitSubmodules, style.FgRed.Sprint(self.c.Git().Submodule.BulkDeinitCmdObj().ToString())},
|
||||
@@ -279,7 +278,7 @@ func (self *SubmodulesController) openBulkActionsMenu() error {
|
||||
return nil
|
||||
})
|
||||
},
|
||||
Key: 'd',
|
||||
Key: gocui.NewKeyRune('d'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -282,14 +282,14 @@ func (self *TagsController) delete(tag *models.Tag) error {
|
||||
menuItems := []*types.MenuItem{
|
||||
{
|
||||
Label: self.c.Tr.DeleteLocalTag,
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
OnPress: func() error {
|
||||
return self.localDelete(tag)
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.DeleteRemoteTag,
|
||||
Key: 'r',
|
||||
Key: gocui.NewKeyRune('r'),
|
||||
OpensMenu: true,
|
||||
OnPress: func() error {
|
||||
return self.remoteDelete(tag)
|
||||
@@ -297,7 +297,7 @@ func (self *TagsController) delete(tag *models.Tag) error {
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.DeleteLocalAndRemoteTag,
|
||||
Key: 'b',
|
||||
Key: gocui.NewKeyRune('b'),
|
||||
OpensMenu: true,
|
||||
OnPress: func() error {
|
||||
return self.localAndRemoteDelete(tag)
|
||||
|
||||
@@ -53,7 +53,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
})
|
||||
return nil
|
||||
},
|
||||
Key: 'x',
|
||||
Key: gocui.NewKeyRune('x'),
|
||||
Tooltip: self.c.Tr.NukeDescription,
|
||||
},
|
||||
{
|
||||
@@ -72,7 +72,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
)
|
||||
return nil
|
||||
},
|
||||
Key: 'u',
|
||||
Key: gocui.NewKeyRune('u'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -90,7 +90,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
)
|
||||
return nil
|
||||
},
|
||||
Key: 'c',
|
||||
Key: gocui.NewKeyRune('c'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -115,7 +115,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
)
|
||||
return nil
|
||||
},
|
||||
Key: 'S',
|
||||
Key: gocui.NewKeyRune('S'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -133,7 +133,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
)
|
||||
return nil
|
||||
},
|
||||
Key: 's',
|
||||
Key: gocui.NewKeyRune('s'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -151,7 +151,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
)
|
||||
return nil
|
||||
},
|
||||
Key: 'm',
|
||||
Key: gocui.NewKeyRune('m'),
|
||||
},
|
||||
{
|
||||
LabelColumns: []string{
|
||||
@@ -176,7 +176,7 @@ func (self *FilesController) createResetMenu() error {
|
||||
},
|
||||
})
|
||||
},
|
||||
Key: 'h',
|
||||
Key: gocui.NewKeyRune('h'),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -4,33 +4,33 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
)
|
||||
|
||||
func (gui *Gui) handleEditorKeypress(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier, allowMultiline bool) bool {
|
||||
if key == gocui.KeyEnter && allowMultiline {
|
||||
func (gui *Gui) handleEditorKeypress(v *gocui.View, key gocui.Key, mod gocui.Modifier, allowMultiline bool) bool {
|
||||
if key.KeyName() == gocui.KeyEnter && allowMultiline {
|
||||
v.TextArea.TypeCharacter("\n")
|
||||
v.RenderTextArea()
|
||||
return true
|
||||
}
|
||||
|
||||
return gocui.DefaultEditor.Edit(v, key, ch, mod)
|
||||
return gocui.DefaultEditor.Edit(v, key, mod)
|
||||
}
|
||||
|
||||
// we've just copy+pasted the editor from gocui to here so that we can also re-
|
||||
// render the commit message length on each keypress
|
||||
func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, ch, mod, false)
|
||||
func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, mod, false)
|
||||
v.RenderTextArea()
|
||||
gui.c.Contexts().CommitMessage.RenderSubtitle()
|
||||
return matched
|
||||
}
|
||||
|
||||
func (gui *Gui) commitDescriptionEditor(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, ch, mod, true)
|
||||
func (gui *Gui) commitDescriptionEditor(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, mod, true)
|
||||
v.RenderTextArea()
|
||||
return matched
|
||||
}
|
||||
|
||||
func (gui *Gui) promptEditor(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, ch, mod, false)
|
||||
func (gui *Gui) promptEditor(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, mod, false)
|
||||
|
||||
v.RenderTextArea()
|
||||
|
||||
@@ -46,8 +46,8 @@ func (gui *Gui) promptEditor(v *gocui.View, key gocui.KeyName, ch rune, mod gocu
|
||||
return matched
|
||||
}
|
||||
|
||||
func (gui *Gui) searchEditor(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, ch, mod, false)
|
||||
func (gui *Gui) searchEditor(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
matched := gui.handleEditorKeypress(v, key, mod, false)
|
||||
v.RenderTextArea()
|
||||
|
||||
searchString := v.TextArea.GetContent()
|
||||
|
||||
@@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@@ -14,7 +15,7 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error {
|
||||
Items: []*types.MenuItem{
|
||||
{
|
||||
Label: gui.c.Tr.ToggleShowCommandLog,
|
||||
Key: 't',
|
||||
Key: gocui.NewKeyRune('t'),
|
||||
OnPress: func() error {
|
||||
currentContext := gui.c.Context().CurrentStatic()
|
||||
if gui.c.State().GetShowExtrasWindow() && currentContext.GetKey() == context.COMMAND_LOG_CONTEXT_KEY {
|
||||
@@ -29,7 +30,7 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error {
|
||||
},
|
||||
{
|
||||
Label: gui.c.Tr.FocusCommandLog,
|
||||
Key: 'f',
|
||||
Key: gocui.NewKeyRune('f'),
|
||||
OnPress: gui.handleFocusCommandLog,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-11
@@ -31,18 +31,8 @@ func (self *GuiDriver) PressKey(keyStr string) {
|
||||
|
||||
key := keybindings.GetKey(keyStr)
|
||||
|
||||
var r rune
|
||||
var tcellKey tcell.Key
|
||||
switch v := key.(type) {
|
||||
case rune:
|
||||
r = v
|
||||
tcellKey = tcell.KeyRune
|
||||
case gocui.KeyName:
|
||||
tcellKey = tcell.Key(v)
|
||||
}
|
||||
|
||||
self.gui.g.ReplayedEvents.Keys <- gocui.NewTcellKeyEventWrapper(
|
||||
tcell.NewEventKey(tcellKey, r, tcell.ModNone),
|
||||
tcell.NewEventKey(tcell.Key(key.KeyName()), key.Ch(), tcell.ModNone),
|
||||
0,
|
||||
)
|
||||
|
||||
|
||||
+10
-10
@@ -180,7 +180,7 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "information",
|
||||
Key: gocui.MouseLeft,
|
||||
Key: gocui.NewKeyName(gocui.MouseLeft),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleInfoClick,
|
||||
},
|
||||
@@ -201,27 +201,27 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "main",
|
||||
Key: gocui.MouseWheelDown,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Handler: gui.scrollDownMain,
|
||||
Description: gui.c.Tr.ScrollDown,
|
||||
Alternative: "fn+up",
|
||||
},
|
||||
{
|
||||
ViewName: "main",
|
||||
Key: gocui.MouseWheelUp,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Handler: gui.scrollUpMain,
|
||||
Description: gui.c.Tr.ScrollUp,
|
||||
Alternative: "fn+down",
|
||||
},
|
||||
{
|
||||
ViewName: "secondary",
|
||||
Key: gocui.MouseWheelDown,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.scrollDownSecondary,
|
||||
},
|
||||
{
|
||||
ViewName: "secondary",
|
||||
Key: gocui.MouseWheelUp,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.scrollUpSecondary,
|
||||
},
|
||||
@@ -251,12 +251,12 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "confirmation",
|
||||
Key: gocui.MouseWheelUp,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Handler: gui.scrollUpConfirmationPanel,
|
||||
},
|
||||
{
|
||||
ViewName: "confirmation",
|
||||
Key: gocui.MouseWheelDown,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Handler: gui.scrollDownConfirmationPanel,
|
||||
},
|
||||
{
|
||||
@@ -304,12 +304,12 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
},
|
||||
{
|
||||
ViewName: "extras",
|
||||
Key: gocui.MouseWheelUp,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelUp),
|
||||
Handler: gui.scrollUpExtra,
|
||||
},
|
||||
{
|
||||
ViewName: "extras",
|
||||
Key: gocui.MouseWheelDown,
|
||||
Key: gocui.NewKeyName(gocui.MouseWheelDown),
|
||||
Handler: gui.scrollDownExtra,
|
||||
},
|
||||
{
|
||||
@@ -379,7 +379,7 @@ func (gui *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBin
|
||||
{
|
||||
ViewName: "extras",
|
||||
Tag: "navigation",
|
||||
Key: gocui.MouseLeft,
|
||||
Key: gocui.NewKeyName(gocui.MouseLeft),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleFocusCommandLog,
|
||||
},
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
package keybindings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/constants"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
func LabelFromKey(key types.Key) string {
|
||||
if key == nil {
|
||||
func LabelFromKey(key gocui.Key) string {
|
||||
if !key.IsSet() {
|
||||
return ""
|
||||
}
|
||||
|
||||
keyInt := 0
|
||||
|
||||
switch key := key.(type) {
|
||||
case rune:
|
||||
keyInt = int(key)
|
||||
case gocui.KeyName:
|
||||
value, ok := config.LabelByKey[key]
|
||||
if ok {
|
||||
return value
|
||||
}
|
||||
keyInt = int(key)
|
||||
if key.KeyName() == gocui.KeyName(tcell.KeyRune) {
|
||||
return string(key.Ch())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%c", keyInt)
|
||||
value, ok := config.LabelByKey[key.KeyName()]
|
||||
if ok {
|
||||
return value
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func GetKey(key string) types.Key {
|
||||
runeCount := utf8.RuneCountInString(key)
|
||||
func GetKey(key string) gocui.Key {
|
||||
if key == "<disabled>" {
|
||||
return nil
|
||||
} else if runeCount > 1 {
|
||||
binding, ok := config.KeyByLabel[strings.ToLower(key)]
|
||||
return gocui.Key{}
|
||||
}
|
||||
|
||||
runeCount := utf8.RuneCountInString(key)
|
||||
if runeCount > 1 {
|
||||
keyName, ok := config.KeyByLabel[strings.ToLower(key)]
|
||||
if !ok {
|
||||
log.Fatalf("Unrecognized key %s for keybinding. For permitted values see %s", strings.ToLower(key), constants.Links.Docs.CustomKeybindings)
|
||||
}
|
||||
return binding
|
||||
} else if runeCount == 1 {
|
||||
return []rune(key)[0]
|
||||
return gocui.NewKeyName(keyName)
|
||||
}
|
||||
return nil
|
||||
|
||||
if runeCount == 1 {
|
||||
return gocui.NewKeyRune([]rune(key)[0])
|
||||
}
|
||||
|
||||
return gocui.Key{}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
@@ -26,7 +27,7 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
||||
|
||||
maxColumnSize := 1
|
||||
|
||||
essentialKeys := []types.Key{
|
||||
essentialKeys := []gocui.Key{
|
||||
keybindings.GetKey(gui.c.UserConfig().Keybinding.Universal.ConfirmMenu),
|
||||
keybindings.GetKey(gui.c.UserConfig().Keybinding.Universal.Return),
|
||||
keybindings.GetKey(gui.c.UserConfig().Keybinding.Universal.PrevItem),
|
||||
@@ -46,7 +47,7 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
||||
|
||||
// Remove all item keybindings that are the same as one of the essential bindings
|
||||
if !opts.KeepConflictingKeybindings && lo.Contains(essentialKeys, item.Key) {
|
||||
item.Key = nil
|
||||
item.Key = gocui.Key{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
@@ -40,7 +41,7 @@ func (self *OptionsMapMgr) renderContextOptionsMap() {
|
||||
globalBindings := self.c.Contexts().Global.GetKeybindings(self.c.KeybindingsOpts())
|
||||
|
||||
currentContextKeys := set.NewFromSlice(
|
||||
lo.Map(currentContextBindings, func(binding *types.Binding, _ int) types.Key {
|
||||
lo.Map(currentContextBindings, func(binding *types.Binding, _ int) gocui.Key {
|
||||
return binding.Key
|
||||
}))
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ type MenuItem struct {
|
||||
|
||||
// If Key is defined it allows the user to press the key to invoke the menu
|
||||
// item, as opposed to having to navigate to it
|
||||
Key Key
|
||||
Key gocui.Key
|
||||
|
||||
// A widget to show in front of the menu item. Supported widget types are
|
||||
// checkboxes and radio buttons,
|
||||
|
||||
@@ -239,7 +239,7 @@ type OnFocusLostOpts struct {
|
||||
type ContextKey string
|
||||
|
||||
type KeybindingsOpts struct {
|
||||
GetKey func(key string) Key
|
||||
GetKey func(key string) gocui.Key
|
||||
Config config.KeybindingConfig
|
||||
Guards KeybindingGuards
|
||||
}
|
||||
|
||||
@@ -5,15 +5,13 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||
)
|
||||
|
||||
type Key any // FIXME: find out how to get `gocui.Key | rune`
|
||||
|
||||
// Binding - a keybinding mapping a key and modifier to a handler. The keypress
|
||||
// is only handled if the given view has focus, or handled globally if the view
|
||||
// is ""
|
||||
type Binding struct {
|
||||
ViewName string
|
||||
Handler func() error
|
||||
Key Key
|
||||
Key gocui.Key
|
||||
Modifier gocui.Modifier
|
||||
Description string
|
||||
// DescriptionFunc is used instead of Description if non-nil, and is useful for dynamic
|
||||
|
||||
@@ -43,7 +43,7 @@ func RunTUI(raceDetector bool) {
|
||||
|
||||
g.SetManagerFunc(app.layout)
|
||||
|
||||
if err := g.SetKeybinding("list", gocui.KeyArrowUp, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyName(gocui.KeyArrowUp), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if app.itemIdx > 0 {
|
||||
app.itemIdx--
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", gocui.KeyArrowDown, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyName(gocui.KeyArrowDown), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if app.itemIdx < len(app.filteredTests)-1 {
|
||||
app.itemIdx++
|
||||
}
|
||||
@@ -72,15 +72,15 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyName(gocui.KeyCtrlC), gocui.ModNone, quit); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 'q', gocui.ModNone, quit); err != nil {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('q'), gocui.ModNone, quit); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 's', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('s'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -93,7 +93,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", gocui.KeyEnter, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyName(gocui.KeyEnter), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -106,7 +106,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 't', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('t'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -119,7 +119,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 'd', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('d'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -132,7 +132,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 'o', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('o'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -148,7 +148,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", 'O', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('O'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
currentTest := app.getCurrentTest()
|
||||
if currentTest == nil {
|
||||
return nil
|
||||
@@ -164,7 +164,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("list", '/', gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("list", gocui.NewKeyRune('/'), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
app.filtering = true
|
||||
if _, err := g.SetCurrentView("editor"); err != nil {
|
||||
return err
|
||||
@@ -181,7 +181,7 @@ func RunTUI(raceDetector bool) {
|
||||
}
|
||||
|
||||
// not using the editor yet, but will use it to help filter the list
|
||||
if err := g.SetKeybinding("editor", gocui.KeyEsc, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("editor", gocui.NewKeyName(gocui.KeyEsc), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
app.filtering = false
|
||||
if _, err := g.SetCurrentView("list"); err != nil {
|
||||
return err
|
||||
@@ -198,7 +198,7 @@ func RunTUI(raceDetector bool) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
if err := g.SetKeybinding("editor", gocui.KeyEnter, gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
if err := g.SetKeybinding("editor", gocui.NewKeyName(gocui.KeyEnter), gocui.ModNone, func(*gocui.Gui, *gocui.View) error {
|
||||
app.filtering = false
|
||||
|
||||
if _, err := g.SetCurrentView("list"); err != nil {
|
||||
@@ -273,9 +273,9 @@ func (self *app) renderTests() {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *app) wrapEditor(f func(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool) func(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
return func(v *gocui.View, key gocui.KeyName, ch rune, mod gocui.Modifier) bool {
|
||||
matched := f(v, key, ch, mod)
|
||||
func (self *app) wrapEditor(f func(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool) func(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
return func(v *gocui.View, key gocui.Key, mod gocui.Modifier) bool {
|
||||
matched := f(v, key, mod)
|
||||
if matched {
|
||||
self.filterWithString(v.TextArea.GetContent())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user