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:
Stefan Haller
2026-04-30 22:14:26 +02:00
parent bff77fc4f9
commit 64996d12d9
38 changed files with 346 additions and 349 deletions
+1 -1
View File
@@ -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 {
+30 -29
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+49
View File
@@ -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
View File
@@ -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.
+3 -7
View File
@@ -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:
+2 -2
View File
@@ -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 {
+9 -8
View File
@@ -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'),
},
},
})
+8 -8
View File
@@ -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'),
},
}...)
+20 -20
View File
@@ -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 -4
View File
@@ -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{
+12 -12
View File
@@ -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,
},
},
+1 -1
View File
@@ -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,
},
+4 -5
View File
@@ -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'),
},
},
})
+3 -3
View File
@@ -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
View File
@@ -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 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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,
},
+25 -25
View File
@@ -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 -2
View File
@@ -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{}
}
}
+2 -1
View File
@@ -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
}))
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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
}
+1 -3
View File
@@ -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
+16 -16
View File
@@ -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())
}