mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-02 09:21:40 +02:00
212 lines
5.8 KiB
Go
212 lines
5.8 KiB
Go
// This "script" generates a file called Keybindings_{{.LANG}}.md
|
|
// in current working directory.
|
|
//
|
|
// The content of this generated file is a keybindings cheatsheet.
|
|
//
|
|
// To generate cheatsheet in english run:
|
|
// go run scripts/generate_cheatsheet.go
|
|
|
|
package cheatsheet
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
|
|
"github.com/jesseduffield/generics/maps"
|
|
"github.com/jesseduffield/generics/slices"
|
|
"github.com/jesseduffield/lazycore/pkg/utils"
|
|
"github.com/jesseduffield/lazygit/pkg/app"
|
|
"github.com/jesseduffield/lazygit/pkg/config"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type bindingSection struct {
|
|
title string
|
|
bindings []*types.Binding
|
|
}
|
|
|
|
type header struct {
|
|
// priority decides the order of the headers in the cheatsheet (lower means higher)
|
|
priority int
|
|
title string
|
|
}
|
|
|
|
type headerWithBindings struct {
|
|
header header
|
|
bindings []*types.Binding
|
|
}
|
|
|
|
func CommandToRun() string {
|
|
return "go run scripts/cheatsheet/main.go generate"
|
|
}
|
|
|
|
func GetKeybindingsDir() string {
|
|
return utils.GetLazyRootDirectory() + "/docs/keybindings"
|
|
}
|
|
|
|
func generateAtDir(cheatsheetDir string) {
|
|
translationSetsByLang := i18n.GetTranslationSets()
|
|
mConfig := config.NewDummyAppConfig()
|
|
|
|
for lang := range translationSetsByLang {
|
|
mConfig.GetUserConfig().Gui.Language = lang
|
|
common, err := app.NewCommon(mConfig)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
mApp, _ := app.NewApp(mConfig, common)
|
|
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
bindings := mApp.Gui.GetCheatsheetKeybindings()
|
|
bindingSections := getBindingSections(bindings, mApp.Tr)
|
|
content := formatSections(mApp.Tr, bindingSections)
|
|
content = fmt.Sprintf("_This file is auto-generated. To update, make the changes in the "+
|
|
"pkg/i18n directory and then run `%s` from the project root._\n\n%s", CommandToRun(), content)
|
|
writeString(file, content)
|
|
}
|
|
}
|
|
|
|
func Generate() {
|
|
generateAtDir(GetKeybindingsDir())
|
|
}
|
|
|
|
func writeString(file *os.File, str string) {
|
|
_, err := file.WriteString(str)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
|
contextTitleMap := map[string]string{
|
|
"global": tr.GlobalTitle,
|
|
"navigation": tr.NavigationTitle,
|
|
"branches": tr.BranchesTitle,
|
|
"localBranches": tr.LocalBranchesTitle,
|
|
"files": tr.FilesTitle,
|
|
"status": tr.StatusTitle,
|
|
"submodules": tr.SubmodulesTitle,
|
|
"subCommits": tr.SubCommitsTitle,
|
|
"remoteBranches": tr.RemoteBranchesTitle,
|
|
"remotes": tr.RemotesTitle,
|
|
"reflogCommits": tr.ReflogCommitsTitle,
|
|
"tags": tr.TagsTitle,
|
|
"commitFiles": tr.CommitFilesTitle,
|
|
"commitMessage": tr.CommitMessageTitle,
|
|
"commits": tr.CommitsTitle,
|
|
"confirmation": tr.ConfirmationTitle,
|
|
"information": tr.InformationTitle,
|
|
"main": tr.NormalTitle,
|
|
"patchBuilding": tr.PatchBuildingTitle,
|
|
"mergeConflicts": tr.MergingTitle,
|
|
"staging": tr.StagingTitle,
|
|
"menu": tr.MenuTitle,
|
|
"search": tr.SearchTitle,
|
|
"secondary": tr.SecondaryTitle,
|
|
"stash": tr.StashTitle,
|
|
"suggestions": tr.SuggestionsCheatsheetTitle,
|
|
"extras": tr.ExtrasTitle,
|
|
}
|
|
|
|
title, ok := contextTitleMap[str]
|
|
if !ok {
|
|
panic(fmt.Sprintf("title not found for %s", str))
|
|
}
|
|
|
|
return title
|
|
}
|
|
|
|
func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection {
|
|
excludedViews := []string{"stagingSecondary", "patchBuildingSecondary"}
|
|
bindingsToDisplay := slices.Filter(bindings, func(binding *types.Binding) bool {
|
|
if lo.Contains(excludedViews, binding.ViewName) {
|
|
return false
|
|
}
|
|
|
|
return (binding.Description != "" || binding.Alternative != "") && binding.Key != nil
|
|
})
|
|
|
|
bindingsByHeader := lo.GroupBy(bindingsToDisplay, func(binding *types.Binding) header {
|
|
return getHeader(binding, tr)
|
|
})
|
|
|
|
bindingGroups := maps.MapToSlice(
|
|
bindingsByHeader,
|
|
func(header header, hBindings []*types.Binding) headerWithBindings {
|
|
uniqBindings := lo.UniqBy(hBindings, func(binding *types.Binding) string {
|
|
return binding.Description + keybindings.LabelFromKey(binding.Key)
|
|
})
|
|
|
|
return headerWithBindings{
|
|
header: header,
|
|
bindings: uniqBindings,
|
|
}
|
|
},
|
|
)
|
|
|
|
slices.SortFunc(bindingGroups, func(a, b headerWithBindings) bool {
|
|
if a.header.priority != b.header.priority {
|
|
return a.header.priority > b.header.priority
|
|
}
|
|
return a.header.title < b.header.title
|
|
})
|
|
|
|
return slices.Map(bindingGroups, func(hb headerWithBindings) *bindingSection {
|
|
return &bindingSection{
|
|
title: hb.header.title,
|
|
bindings: hb.bindings,
|
|
}
|
|
})
|
|
}
|
|
|
|
func getHeader(binding *types.Binding, tr *i18n.TranslationSet) header {
|
|
if binding.Tag == "navigation" {
|
|
return header{priority: 2, title: localisedTitle(tr, "navigation")}
|
|
}
|
|
|
|
if binding.ViewName == "" {
|
|
return header{priority: 3, title: localisedTitle(tr, "global")}
|
|
}
|
|
|
|
return header{priority: 1, title: localisedTitle(tr, binding.ViewName)}
|
|
}
|
|
|
|
func formatSections(tr *i18n.TranslationSet, bindingSections []*bindingSection) string {
|
|
content := fmt.Sprintf("# Lazygit %s\n", tr.Keybindings)
|
|
|
|
for _, section := range bindingSections {
|
|
content += formatTitle(section.title)
|
|
content += "<pre>\n"
|
|
for _, binding := range section.bindings {
|
|
content += formatBinding(binding)
|
|
}
|
|
content += "</pre>\n"
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
func formatTitle(title string) string {
|
|
return fmt.Sprintf("\n## %s\n\n", title)
|
|
}
|
|
|
|
func formatBinding(binding *types.Binding) string {
|
|
if binding.Alternative != "" {
|
|
return fmt.Sprintf(
|
|
" <kbd>%s</kbd>: %s (%s)\n",
|
|
keybindings.LabelFromKey(binding.Key),
|
|
binding.Description,
|
|
binding.Alternative,
|
|
)
|
|
}
|
|
return fmt.Sprintf(" <kbd>%s</kbd>: %s\n", keybindings.LabelFromKey(binding.Key), binding.Description)
|
|
}
|