diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index deab1a1..035f4b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,9 @@ jobs: key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test restore-keys: | ${{runner.os}}-go- + - name: Check Cheatsheet + run: | + go run scripts/cheatsheet/main.go check - name: Test code run: | bash ./test.sh diff --git a/docs/keybindings/Keybindings_de.md b/docs/keybindings/Keybindings_de.md index 3258e52..458cf79 100644 --- a/docs/keybindings/Keybindings_de.md +++ b/docs/keybindings/Keybindings_de.md @@ -1,4 +1,4 @@ -_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/generate_cheatsheet.go` from the project root._ +_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._ # Lazydocker menĂ¼ diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index db306cd..dd0925e 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -1,4 +1,4 @@ -_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/generate_cheatsheet.go` from the project root._ +_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._ # Lazydocker menu diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index 6f86660..00dc7f8 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -1,4 +1,4 @@ -_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/generate_cheatsheet.go` from the project root._ +_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._ # Lazydocker menu diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index 921b3db..174beb1 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -1,4 +1,4 @@ -_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/generate_cheatsheet.go` from the project root._ +_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._ # Lazydocker menu diff --git a/docs/keybindings/Keybindings_tr.md b/docs/keybindings/Keybindings_tr.md index 4c16e23..bb83fae 100644 --- a/docs/keybindings/Keybindings_tr.md +++ b/docs/keybindings/Keybindings_tr.md @@ -1,4 +1,4 @@ -_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/generate_cheatsheet.go` from the project root._ +_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._ # Lazydocker menĂ¼ diff --git a/scripts/generate_cheatsheet.go b/pkg/cheatsheet/generate.go similarity index 93% rename from scripts/generate_cheatsheet.go rename to pkg/cheatsheet/generate.go index 67b51f0..19dff30 100644 --- a/scripts/generate_cheatsheet.go +++ b/pkg/cheatsheet/generate.go @@ -6,7 +6,7 @@ // To generate cheatsheet in english run: // LANG=en go run scripts/generate_cheatsheet.go -package main +package cheatsheet import ( "fmt" @@ -20,7 +20,7 @@ import ( ) const ( - generateCheatsheetCmd = "go run scripts/generate_cheatsheet.go" + generateCheatsheetCmd = "go run scripts/cheatsheet/main.go generate" ) type bindingSection struct { @@ -28,7 +28,11 @@ type bindingSection struct { bindings []*gui.Binding } -func main() { +func Generate() { + generateAtDir(GetKeybindingsDir()) +} + +func generateAtDir(dir string) { mConfig, err := config.NewAppConfig("lazydocker", "", "", "", "", true, nil, "") if err != nil { panic(err) @@ -37,7 +41,8 @@ func main() { for lang := range i18n.GetTranslationSets() { os.Setenv("LC_ALL", lang) mApp, _ := app.NewApp(mConfig) - file, err := os.Create("./docs/keybindings/Keybindings_" + lang + ".md") + + file, err := os.Create(dir + "/Keybindings_" + lang + ".md") if err != nil { panic(err) } diff --git a/pkg/cheatsheet/validate.go b/pkg/cheatsheet/validate.go new file mode 100644 index 0000000..1ad3368 --- /dev/null +++ b/pkg/cheatsheet/validate.go @@ -0,0 +1,87 @@ +package cheatsheet + +import ( + "fmt" + "io/fs" + "log" + "os" + "path/filepath" + "regexp" + + "github.com/jesseduffield/lazydocker/pkg/utils" + "github.com/pmezard/go-difflib/difflib" +) + +func Check() { + dir := GetKeybindingsDir() + tmpDir := filepath.Join(os.TempDir(), "lazydocker_cheatsheet") + + err := os.RemoveAll(tmpDir) + if err != nil { + log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err) + } + defer os.RemoveAll(tmpDir) + + if err = os.Mkdir(tmpDir, 0o700); err != nil { + log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err) + } + + generateAtDir(tmpDir) + + actualContent := obtainContent(dir) + expectedContent := obtainContent(tmpDir) + + if expectedContent == "" { + log.Fatal("empty expected content") + } + + if actualContent != expectedContent { + if err := difflib.WriteUnifiedDiff(os.Stdout, difflib.UnifiedDiff{ + A: difflib.SplitLines(expectedContent), + B: difflib.SplitLines(actualContent), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }); err != nil { + log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err) + } + fmt.Printf( + "\nCheatsheets are out of date. Please run `%s` at the project root and commit the changes. "+ + "If you run the script and no keybindings files are updated as a result, try rebasing onto master"+ + "and trying again.\n", + generateCheatsheetCmd, + ) + os.Exit(1) + } + + fmt.Println("\nCheatsheets are up to date") +} + +func GetKeybindingsDir() string { + return utils.GetLazydockerRootDirectory() + "/docs/keybindings" +} + +func obtainContent(dir string) string { + re := regexp.MustCompile(`Keybindings_\w+\.md$`) + + content := "" + err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if re.MatchString(path) { + bytes, err := os.ReadFile(path) + if err != nil { + log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err) + } + content += fmt.Sprintf("\n%s\n\n", filepath.Base(path)) + content += string(bytes) + } + + return nil + }) + if err != nil { + log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err) + } + + return content +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index fe1ae3d..baf5cf5 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -5,7 +5,10 @@ import ( "fmt" "html/template" "io" + "log" "math" + "os" + "path/filepath" "reflect" "regexp" "sort" @@ -408,3 +411,31 @@ func IsValidHexValue(v string) bool { return true } + +// GetLazydockerRootDirectory finds lazydocker root directory. +// +// It's used for our cheatsheet script and integration tests. Not to be confused with finding the +// root directory of _any_ random repo. +func GetLazydockerRootDirectory() string { + path, err := os.Getwd() + if err != nil { + panic(err) + } + + for { + _, err := os.Stat(filepath.Join(path, ".git")) + if err == nil { + return path + } + + if !os.IsNotExist(err) { + panic(err) + } + + path = filepath.Dir(path) + + if path == "/" { + log.Fatal("must run in lazydocker folder or child folder") + } + } +} diff --git a/scripts/cheatsheet/main.go b/scripts/cheatsheet/main.go new file mode 100644 index 0000000..53f72ed --- /dev/null +++ b/scripts/cheatsheet/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "log" + "os" + + "github.com/jesseduffield/lazydocker/pkg/cheatsheet" +) + +func main() { + if len(os.Args) < 2 { + log.Fatal("Please provide a command: one of 'generate', 'check'") + } + + command := os.Args[1] + + switch command { + case "generate": + cheatsheet.Generate() + fmt.Printf("\nGenerated cheatsheets in %s\n", cheatsheet.GetKeybindingsDir()) + case "check": + cheatsheet.Check() + default: + log.Fatal("\nUnknown command. Expected one of 'generate', 'check'") + } +}