1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-08-24 19:39:16 +02:00

Add "CopyToClipboard" command to ConfirmationController (#4810)

## **PR Description**

Sometimes, I want to copy the error message to clipboard to search
google or ask to LLM about the error message.

So I added CopyToClipboard command to `ConfirmationController` and I
have confirmed that this command copies the content of the window to the
clipboard.
This commit is contained in:
Stefan Haller
2025-08-15 17:20:16 +02:00
committed by GitHub
15 changed files with 84 additions and 5 deletions

View File

@@ -125,6 +125,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|-----|--------|-------------|
| `` <enter> `` | Confirm | |
| `` <esc> `` | Close/Cancel | |
| `` <c-o> `` | Copy to clipboard | |
## Files

View File

@@ -402,3 +402,4 @@ _凡例:`<c-b>` はctrl+b、`<a-b>` はalt+b、`B` はshift+bを意味
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 閉じる/キャンセル | |
| `` <c-o> `` | クリップボードにコピー | |

View File

@@ -402,3 +402,4 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|-----|--------|-------------|
| `` <enter> `` | 확인 | |
| `` <esc> `` | 닫기/취소 | |
| `` <c-o> `` | 클립보드에 복사 | |

View File

@@ -91,6 +91,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|-----|--------|-------------|
| `` <enter> `` | Bevestig | |
| `` <esc> `` | Sluiten | |
| `` <c-o> `` | Copy to clipboard | |
## Branches

View File

@@ -217,6 +217,7 @@ _Legenda: `<c-b>` oznacza ctrl+b, `<a-b>` oznacza alt+b, `B` oznacza shift+b_
|-----|--------|-------------|
| `` <enter> `` | Potwierdź | |
| `` <esc> `` | Zamknij/Anuluj | |
| `` <c-o> `` | Kopiuj do schowka | |
## Pliki

View File

@@ -200,6 +200,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|-----|--------|-------------|
| `` <enter> `` | Confirmar | |
| `` <esc> `` | Fechar/Cancelar | |
| `` <c-o> `` | Copy to clipboard | |
## Etiquetas

View File

@@ -237,6 +237,7 @@ _Связки клавиш_
|-----|--------|-------------|
| `` <enter> `` | Подтвердить | |
| `` <esc> `` | Закрыть/отменить | |
| `` <c-o> `` | Copy to clipboard | |
## Подкоммиты

View File

@@ -350,6 +350,7 @@ _图例:`<c-b>` 意味着ctrl+b, `<a-b>意味着Alt+b, `B` 意味着shift+b_
|-----|--------|-------------|
| `` <enter> `` | 确认 | |
| `` <esc> `` | 关闭 | |
| `` <c-o> `` | 复制到剪贴板 | |
## 菜单

View File

@@ -372,6 +372,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B
|-----|--------|-------------|
| `` <enter> `` | 確認 | |
| `` <esc> `` | 關閉/取消 | |
| `` <c-o> `` | 複製到剪貼簿 | |
## 遠端

View File

@@ -47,6 +47,13 @@ func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) [
return nil
},
},
{
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
Handler: self.handleCopyToClipboard,
Description: self.c.Tr.CopyToClipboardMenu,
DisplayOnScreen: true,
GetDisabledReason: self.copyToClipboardEnabled,
},
}
return bindings
@@ -93,3 +100,23 @@ func (self *ConfirmationController) switchToSuggestions() {
self.c.Views().Suggestions.Subtitle = subtitle
self.c.Context().Replace(self.c.Contexts().Suggestions)
}
func (self *ConfirmationController) handleCopyToClipboard() error {
confirmationView := self.c.Views().Confirmation
text := confirmationView.Buffer()
if err := self.c.OS().CopyToClipboard(text); err != nil {
return err
}
self.c.Toast(self.c.Tr.MessageCopiedToClipboard)
return nil
}
func (self *ConfirmationController) copyToClipboardEnabled() *types.DisabledReason {
if self.c.Views().Confirmation.Editable {
// The empty text is intentional. We don't want to get a toast when invoking this, we only
// want to prevent it from showing up in the options bar.
return &types.DisabledReason{Text: ""}
}
return nil
}

View File

@@ -723,6 +723,7 @@ type TranslationSet struct {
CommitHasNoTags string
CommitHasNoMessageBody string
PatchCopiedToClipboard string
MessageCopiedToClipboard string
CopiedToClipboard string
ErrCannotEditDirectory string
ErrCannotCopyContentOfDirectory string
@@ -1800,6 +1801,7 @@ func EnglishTranslationSet() *TranslationSet {
CommitHasNoTags: "Commit has no tags",
CommitHasNoMessageBody: "Commit has no message body",
PatchCopiedToClipboard: "Patch copied to clipboard",
MessageCopiedToClipboard: "Message copied to clipboard",
CopiedToClipboard: "copied to clipboard",
ErrCannotEditDirectory: "Cannot edit directories: you can only edit individual files",
ErrCannotCopyContentOfDirectory: "Cannot copy content of directories: you can only copy content of individual files",

View File

@@ -36,6 +36,11 @@ func (self *Popup) Alert() *AlertDriver {
return &AlertDriver{t: self.t}
}
func (self *AlertDriver) Tap(f func()) *AlertDriver {
self.getViewDriver().Tap(f)
return self
}
func (self *Popup) inAlert() {
// basically the same thing as a confirmation popup with the current implementation
self.t.assertWithRetries(func() (bool, string) {

View File

@@ -0,0 +1,40 @@
package misc
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var CopyConfirmationMessageToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Copy the text of a confirmation popup to the clipboard",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().OS.CopyToClipboardCmd = "printf '%s' {{text}} > clipboard"
},
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("commit").IsSelected(),
).
Press(keys.Universal.Remove)
t.ExpectPopup().Alert().
Title(Equals("Drop commit")).
Content(Equals("Are you sure you want to drop the selected commit(s)?")).
Tap(func() {
t.GlobalPress(keys.Universal.CopyToClipboard)
t.ExpectToast(Equals("Message copied to clipboard"))
}).
Confirm()
t.FileSystem().FileContent("clipboard",
Equals("Are you sure you want to drop the selected commit(s)?"))
},
})

View File

@@ -29,11 +29,6 @@ var CopyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
t.ExpectToast(Equals("'branch-a' copied to clipboard"))
t.Views().Files().
Focus()
t.GlobalPress(keys.Files.RefreshFiles)
t.FileSystem().FileContent("clipboard", Equals("branch-a"))
},
})

View File

@@ -299,6 +299,7 @@ var tests = []*components.IntegrationTest{
interactive_rebase.SwapWithConflict,
interactive_rebase.ViewFilesOfTodoEntries,
misc.ConfirmOnQuit,
misc.CopyConfirmationMessageToClipboard,
misc.CopyToClipboard,
misc.DisabledKeybindings,
misc.InitialOpen,