Open the full command log in the user's editor from the @ menu

Avoids awkward multi-line terminal copy when reusing log content
elsewhere.
This commit is contained in:
tmwatchanan 2026-06-20 22:12:50 +07:00
parent 799deabfef
commit 01072bac90
No known key found for this signature in database
GPG key ID: F4D43507B7A7F4AC
5 changed files with 80 additions and 0 deletions

View file

@ -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

View file

@ -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'?

View file

@ -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",

View file

@ -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"))
},
})

View file

@ -340,6 +340,7 @@ var tests = []*components.IntegrationTest{
misc.DirenvLoadedOnRepoSwitch,
misc.DirenvUnloadsOnBlockedEnvrc,
misc.InitialOpen,
misc.OpenCommandLogInEditor,
misc.RecentReposOnLaunch,
patch_building.Apply,
patch_building.ApplyInReverse,