From 01072bac90ff8b2cbb6052e034d767c84debf405 Mon Sep 17 00:00:00 2001 From: tmwatchanan Date: Sat, 20 Jun 2026 22:12:50 +0700 Subject: [PATCH] Open the full command log in the user's editor from the @ menu Avoids awkward multi-line terminal copy when reusing log content elsewhere. --- pkg/gui/command_log_panel.go | 7 +++ pkg/gui/extras_panel.go | 25 +++++++++++ pkg/i18n/english.go | 4 ++ .../tests/misc/open_command_log_in_editor.go | 43 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 5 files changed, 80 insertions(+) create mode 100644 pkg/integration/tests/misc/open_command_log_in_editor.go diff --git a/pkg/gui/command_log_panel.go b/pkg/gui/command_log_panel.go index 09edd14dd..a30639baa 100644 --- a/pkg/gui/command_log_panel.go +++ b/pkg/gui/command_log_panel.go @@ -56,6 +56,13 @@ func (gui *Gui) hasGitOutput() bool { return gui.lastGitOutput() != "" } +func (gui *Gui) commandLogContent() string { + if gui.Views.Extras == nil { + return "" + } + return strings.TrimRight(gui.Views.Extras.Buffer(), "\n") +} + func gitOutputBlocksFromCommandLogLines(lines []string, gitOutputHeader string) []string { var blocks []string diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go index d4988b981..951ba0f75 100644 --- a/pkg/gui/extras_panel.go +++ b/pkg/gui/extras_panel.go @@ -3,6 +3,8 @@ package gui import ( "errors" "io" + "path/filepath" + "time" "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" @@ -53,6 +55,11 @@ func (gui *Gui) handleCreateExtrasMenuPanel() error { OnPress: gui.handleCopyAllGitOutputToClipboard, DisabledReason: noGitOutputDisabledReason(), }, + { + Label: gui.c.Tr.OpenCommandLogInEditor, + Keys: []gocui.Key{gocui.NewKeyRune('o')}, + OnPress: gui.handleOpenCommandLogInEditor, + }, }, }) } @@ -85,6 +92,24 @@ func (gui *Gui) handleCopyAllGitOutputToClipboard() error { return nil } +func (gui *Gui) handleOpenCommandLogInEditor() error { + content := gui.commandLogContent() + if content == "" { + return errors.New(gui.c.Tr.NoCommandLogToOpenInEditor) + } + + filepath := filepath.Join( + gui.os.GetTempDir(), + gui.c.Git().RepoPaths.RepoName(), + time.Now().Format("Jan _2 15.04.05.000000000")+"-command-log.txt", + ) + if err := gui.os.CreateFileWithContent(filepath, content); err != nil { + return err + } + + return gui.Helpers().Files.EditFiles([]string{filepath}) +} + func (gui *Gui) handleFocusCommandLog() error { gui.c.State().SetShowExtrasWindow(true) // TODO: is this necessary? Can't I just call 'return from context'? diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 346b10c54..aca3bc0cb 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -772,6 +772,8 @@ type TranslationSet struct { CopyAllGitOutputToClipboard string NoGitOutputToCopy string GitOutputCopiedToClipboard string + OpenCommandLogInEditor string + NoCommandLogToOpenInEditor string CommandLogHeader string RandomTip string ToggleWhitespaceInDiffView string @@ -1907,6 +1909,8 @@ func EnglishTranslationSet() *TranslationSet { CopyAllGitOutputToClipboard: "Copy all git outputs to clipboard", NoGitOutputToCopy: "No git output to copy", GitOutputCopiedToClipboard: "Git output copied to clipboard", + OpenCommandLogInEditor: "Open command log in editor", + NoCommandLogToOpenInEditor: "No command log to open in editor", CommandLogHeader: "You can hide/focus this panel by pressing '%s'\n", RandomTip: "Random tip", ToggleWhitespaceInDiffView: "Toggle whitespace", diff --git a/pkg/integration/tests/misc/open_command_log_in_editor.go b/pkg/integration/tests/misc/open_command_log_in_editor.go new file mode 100644 index 000000000..75c1c5aa0 --- /dev/null +++ b/pkg/integration/tests/misc/open_command_log_in_editor.go @@ -0,0 +1,43 @@ +package misc + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var OpenCommandLogInEditor = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Open the full command log in the user's editor", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().OS.Edit = "cp {{filename}} editor-output.txt" + }, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("one") + + shell.CloneIntoRemote("origin") + + shell.SetBranchUpstream("master", "origin/master") + + shell.EmptyCommit("two") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Files(). + IsFocused(). + Press(keys.Universal.Push) + + t.Views().Status().Content(Equals("✓ repo → master")) + + t.GlobalPress(keys.Universal.ExtrasMenu) + + t.ExpectPopup().Menu(). + Title(Equals("Command log")). + Select(Contains("Open command log in editor")). + Confirm() + + t.FileSystem().FileContent("editor-output.txt", + Contains("Push"). + Contains("git push"). + Contains("master -> master")) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 7c55017ce..ff0fabf89 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -340,6 +340,7 @@ var tests = []*components.IntegrationTest{ misc.DirenvLoadedOnRepoSwitch, misc.DirenvUnloadsOnBlockedEnvrc, misc.InitialOpen, + misc.OpenCommandLogInEditor, misc.RecentReposOnLaunch, patch_building.Apply, patch_building.ApplyInReverse,