diff --git a/Keybindings_en.md b/Keybindings_en.md new file mode 100644 index 000000000..ff91437df --- /dev/null +++ b/Keybindings_en.md @@ -0,0 +1,114 @@ +# Lazygit menu + +## Global + +
+ m: view merge/rebase options + P: push + p: pull + R: refresh ++ +## Status + +
+ e: edit config file + o: open config file + u: check for update + s: switch to a recent repo ++ +## Files + +
+ c: commit changes + A: amend last commit + C: commit changes using git editor + space: toggle staged + d: delete if untracked / checkout if tracked + e: edit file + o: open file + i: add to .gitignore + r: refresh files + s: stash files + S: soft reset to last commit + a: stage/unstage all + t: add patch + D: reset hard and remove untracked files + enter: stage individual hunks/lines + f: fetch ++ +## Branches + +
+ space: checkout + o: create pull request + c: checkout by name + F: force checkout + n: new branch + d: delete branch + r: rebase branch + M: merge into currently checked out branch + f: fast-forward this branch from its upstream ++ +## Commits + +
+ s: squash down + r: rename commit + R: rename commit with editor + g: reset to this commit + f: fixup commit + d: delete commit + J: move commit down one + K: move commit up one + e: edit commit + A: amend commit with staged changes + p: pick commit (when mid-rebase) + t: revert commit + c: copy commit (cherry-pick) + C: copy commit range (cherry-pick) + v: paste commits (cherry-pick) ++ +## Stash + +
+ space: apply + g: pop + d: drop ++ +## Main (Normal) + +
+ PgDn: scroll down + PgUp: scroll up ++ +## Main (Staging) + +
+ esc: return to files panel + ▲: select previous line + ▼: select next line + ◄: select previous hunk + ►: select next hunk + space: stage line + a: stage hunk ++ +## Main (Merging) + +
+ esc: return to files panel + space: pick hunk + b: pick both hunks + ◄: select previous conflict + ►: select next conflict + ▲: select top hunk + ▼: select bottom hunk + z: undo +diff --git a/pkg/gui/context.go b/pkg/gui/context.go index d349286cf..861ffc0be 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -38,7 +38,7 @@ func (gui *Gui) changeContext(viewName, context string) error { return nil } - contextMap := gui.getContextMap() + contextMap := gui.GetContextMap() gui.g.DeleteKeybindings(viewName) @@ -53,7 +53,7 @@ func (gui *Gui) changeContext(viewName, context string) error { } func (gui *Gui) setInitialContexts() error { - contextMap := gui.getContextMap() + contextMap := gui.GetContextMap() initialContexts := map[string]string{ "main": "merging", diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 3992513ef..6084d26e7 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -13,6 +13,7 @@ type Binding struct { Key interface{} // FIXME: find out how to get `gocui.Key | rune` Modifier gocui.Modifier Description string + panic bool } // GetDisplayStrings returns the display string of a file @@ -31,6 +32,10 @@ func (b *Binding) GetKey() string { key = int(b.Key.(gocui.Key)) } + if b.panic { + panic(key) + } + // special keys switch key { case 27: @@ -39,6 +44,18 @@ func (b *Binding) GetKey() string { return "enter" case 32: return "space" + case 65514: + return "►" + case 65515: + return "◄" + case 65517: + return "▲" + case 65516: + return "▼" + case 65508: + return "PgUp" + case 65507: + return "PgDn" } return string(key) @@ -461,11 +478,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { return bindings } +// GetCurrentKeybindings gets the list of keybindings given the current context func (gui *Gui) GetCurrentKeybindings() []*Binding { bindings := gui.GetInitialKeybindings() viewName := gui.currentViewName(gui.g) currentContext := gui.State.Contexts[viewName] - contextBindings := gui.getContextMap()[viewName][currentContext] + contextBindings := gui.GetContextMap()[viewName][currentContext] return append(bindings, contextBindings...) } @@ -484,9 +502,24 @@ func (gui *Gui) keybindings(g *gocui.Gui) error { return nil } -func (gui *Gui) getContextMap() map[string]map[string][]*Binding { +func (gui *Gui) GetContextMap() map[string]map[string][]*Binding { return map[string]map[string][]*Binding{ "main": { + "normal": { + { + ViewName: "main", + Key: gocui.MouseWheelDown, + Modifier: gocui.ModNone, + Handler: gui.scrollDownMain, + Description: gui.Tr.SLocalize("ScrollDown"), + }, { + ViewName: "main", + Key: gocui.MouseWheelUp, + Modifier: gocui.ModNone, + Handler: gui.scrollUpMain, + Description: gui.Tr.SLocalize("ScrollUp"), + }, + }, "staging": { { ViewName: "main", @@ -495,15 +528,17 @@ func (gui *Gui) getContextMap() map[string]map[string][]*Binding { Handler: gui.handleStagingEscape, Description: gui.Tr.SLocalize("EscapeStaging"), }, { - ViewName: "main", - Key: gocui.KeyArrowUp, - Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevLine, + ViewName: "main", + Key: gocui.KeyArrowUp, + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevLine, + Description: gui.Tr.SLocalize("PrevLine"), }, { - ViewName: "main", - Key: gocui.KeyArrowDown, - Modifier: gocui.ModNone, - Handler: gui.handleStagingNextLine, + ViewName: "main", + Key: gocui.KeyArrowDown, + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextLine, + Description: gui.Tr.SLocalize("NextLine"), }, { ViewName: "main", Key: 'k', @@ -516,14 +551,26 @@ func (gui *Gui) getContextMap() map[string]map[string][]*Binding { Handler: gui.handleStagingNextLine, }, { ViewName: "main", - Key: gocui.KeyArrowLeft, + Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, - Handler: gui.handleStagingPrevHunk, + Handler: gui.handleStagingPrevLine, }, { ViewName: "main", - Key: gocui.KeyArrowRight, + Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, - Handler: gui.handleStagingNextHunk, + Handler: gui.handleStagingNextLine, + }, { + ViewName: "main", + Key: gocui.KeyArrowLeft, + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevHunk, + Description: gui.Tr.SLocalize("PrevHunk"), + }, { + ViewName: "main", + Key: gocui.KeyArrowRight, + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextHunk, + Description: gui.Tr.SLocalize("NextHunk"), }, { ViewName: "main", Key: 'h', @@ -550,10 +597,11 @@ func (gui *Gui) getContextMap() map[string]map[string][]*Binding { }, "merging": { { - ViewName: "main", - Key: gocui.KeyEsc, - Modifier: gocui.ModNone, - Handler: gui.handleEscapeMerge, + ViewName: "main", + Key: gocui.KeyEsc, + Modifier: gocui.ModNone, + Handler: gui.handleEscapeMerge, + Description: gui.Tr.SLocalize("EscapeStaging"), }, { ViewName: "main", Key: gocui.KeySpace, @@ -567,25 +615,31 @@ func (gui *Gui) getContextMap() map[string]map[string][]*Binding { Handler: gui.handlePickBothHunks, Description: gui.Tr.SLocalize("PickBothHunks"), }, { - ViewName: "main", - Key: gocui.KeyArrowLeft, - Modifier: gocui.ModNone, - Handler: gui.handleSelectPrevConflict, + ViewName: "main", + Key: gocui.KeyArrowLeft, + Modifier: gocui.ModNone, + Handler: gui.handleSelectPrevConflict, + Description: gui.Tr.SLocalize("PrevConflict"), }, { ViewName: "main", Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.handleSelectNextConflict, + + Description: gui.Tr.SLocalize("NextConflict"), }, { ViewName: "main", Key: gocui.KeyArrowUp, - Modifier: gocui.ModNone, - Handler: gui.handleSelectTop, + + Modifier: gocui.ModNone, + Handler: gui.handleSelectTop, + Description: gui.Tr.SLocalize("SelectTop"), }, { - ViewName: "main", - Key: gocui.KeyArrowDown, - Modifier: gocui.ModNone, - Handler: gui.handleSelectBottom, + ViewName: "main", + Key: gocui.KeyArrowDown, + Modifier: gocui.ModNone, + Handler: gui.handleSelectBottom, + Description: gui.Tr.SLocalize("SelectBottom"), }, { ViewName: "main", Key: 'h', diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 74d9bfb7d..7195c5f0d 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -45,6 +45,18 @@ func addEnglish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "MergingMainTitle", Other: "Resolve merge conflicts", + }, &i18n.Message{ + ID: "MainTitle", + Other: "Main", + }, &i18n.Message{ + ID: "StagingTitle", + Other: "Staging", + }, &i18n.Message{ + ID: "MergingTitle", + Other: "Merging", + }, &i18n.Message{ + ID: "NormalTitle", + Other: "Normal", }, &i18n.Message{ ID: "CommitMessage", Other: "Commit message", @@ -588,6 +600,39 @@ func addEnglish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "CannotRebaseOntoFirstCommit", Other: "You cannot interactive rebase onto the first commit", + }, &i18n.Message{ + ID: "Donate", + Other: "Donate", + }, &i18n.Message{ + ID: "PrevLine", + Other: "select previous line", + }, &i18n.Message{ + ID: "NextLine", + Other: "select next line", + }, &i18n.Message{ + ID: "PrevHunk", + Other: "select previous hunk", + }, &i18n.Message{ + ID: "NextHunk", + Other: "select next hunk", + }, &i18n.Message{ + ID: "PrevConflict", + Other: "select previous conflict", + }, &i18n.Message{ + ID: "NextConflict", + Other: "select next conflict", + }, &i18n.Message{ + ID: "SelectTop", + Other: "select top hunk", + }, &i18n.Message{ + ID: "SelectBottom", + Other: "select bottom hunk", + }, &i18n.Message{ + ID: "ScrollDown", + Other: "scroll down", + }, &i18n.Message{ + ID: "ScrollUp", + Other: "scroll up", }, ) } diff --git a/scripts/generate_cheatsheet.go b/scripts/generate_cheatsheet.go index d42088d6b..92d5880a5 100644 --- a/scripts/generate_cheatsheet.go +++ b/scripts/generate_cheatsheet.go @@ -16,6 +16,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/app" "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/gui" ) func writeString(file *os.File, str string) { @@ -25,27 +26,36 @@ func writeString(file *os.File, str string) { } } -func getTitle(mApp *app.App, viewName string) string { - viewTitle := strings.Title(viewName) + "Title" - translatedTitle := mApp.Tr.SLocalize(viewTitle) - formattedTitle := fmt.Sprintf("\n## %s\n\n", translatedTitle) - return formattedTitle +func localisedTitle(mApp *app.App, str string) string { + viewTitle := strings.Title(str) + "Title" + return mApp.Tr.SLocalize(viewTitle) } +func formatTitle(title string) string { + return fmt.Sprintf("\n## %s\n\n", title) +} + +func writeBinding(file *os.File, binding *gui.Binding) { + info := fmt.Sprintf(" %s: %s\n", binding.GetKey(), binding.Description) + writeString(file, info) +} + +// I should really just build an array of tuples, one thing with a string and the other with a list of bindings, and then build them like that. + func main() { - mConfig, _ := config.NewAppConfig("", "", "", "", "", new(bool)) - mApp, _ := app.Setup(mConfig) + mConfig, _ := config.NewAppConfig("", "", "", "", "", true) + mApp, _ := app.NewApp(mConfig) lang := mApp.Tr.GetLanguage() file, _ := os.Create("Keybindings_" + lang + ".md") current := "" writeString(file, fmt.Sprintf("# Lazygit %s\n", mApp.Tr.SLocalize("menu"))) - writeString(file, getTitle(mApp, "global")) + writeString(file, formatTitle(localisedTitle(mApp, "global"))) writeString(file, "
\n") // TODO: add context-based keybindings - for _, binding := range mApp.Gui.GetKeybindings() { + for _, binding := range mApp.Gui.GetInitialKeybindings() { if binding.Description == "" { continue } @@ -53,13 +63,29 @@ func main() { if binding.ViewName != current { current = binding.ViewName writeString(file, "\n") - writeString(file, getTitle(mApp, current)) + writeString(file, formatTitle(localisedTitle(mApp, current))) writeString(file, "
\n") } - info := fmt.Sprintf(" %s: %s\n", binding.GetKey(), binding.Description) - writeString(file, info) + writeBinding(file, binding) } writeString(file, "\n") + + for view, contexts := range mApp.Gui.GetContextMap() { + for contextName, contextBindings := range contexts { + translatedView := localisedTitle(mApp, view) + translatedContextName := localisedTitle(mApp, contextName) + writeString(file, fmt.Sprintf("\n## %s (%s)\n\n", translatedView, translatedContextName)) + writeString(file, "
\n") + for _, binding := range contextBindings { + if binding.Description == "" { + continue + } + + writeBinding(file, binding) + } + writeString(file, "\n") + } + } }