mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-15 00:15:32 +02:00
Add a "Content of selected file" entry to the copy menu for commit files
This is useful for copying the entire content of the selected file as it was at the selected commit. We only add it to the commit files panel; it is not needed in the files panel, because there you can simply press "e" to edit the file.
This commit is contained in:
@ -279,6 +279,13 @@ func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) oscommand
|
|||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitCommands) ShowFileContentCmdObj(hash string, filePath string) oscommands.ICmdObj {
|
||||||
|
cmdArgs := NewGitCmd("show").
|
||||||
|
Arg(fmt.Sprintf("%s:%s", hash, filePath)).
|
||||||
|
ToArgv()
|
||||||
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
|
}
|
||||||
|
|
||||||
// Revert reverts the selected commit by hash
|
// Revert reverts the selected commit by hash
|
||||||
func (self *CommitCommands) Revert(hash string) error {
|
func (self *CommitCommands) Revert(hash string) error {
|
||||||
cmdArgs := NewGitCmd("revert").Arg(hash).ToArgv()
|
cmdArgs := NewGitCmd("revert").Arg(hash).ToArgv()
|
||||||
|
@ -203,6 +203,16 @@ func (self *CommitFilesController) copyDiffToClipboard(path string, toastMessage
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitFilesController) copyFileContentToClipboard(path string) error {
|
||||||
|
_, to := self.context().GetFromAndToForDiff()
|
||||||
|
cmdObj := self.c.Git().Commit.ShowFileContentCmdObj(to, path)
|
||||||
|
diff, err := cmdObj.RunWithOutput()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return self.c.OS().CopyToClipboard(diff)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitFilesController) openCopyMenu() error {
|
func (self *CommitFilesController) openCopyMenu() error {
|
||||||
node := self.context().GetSelected()
|
node := self.context().GetSelected()
|
||||||
|
|
||||||
@ -246,6 +256,27 @@ func (self *CommitFilesController) openCopyMenu() error {
|
|||||||
DisabledReason: self.require(self.itemsSelected())(),
|
DisabledReason: self.require(self.itemsSelected())(),
|
||||||
Key: 'a',
|
Key: 'a',
|
||||||
}
|
}
|
||||||
|
copyFileContentItem := &types.MenuItem{
|
||||||
|
Label: self.c.Tr.CopyFileContent,
|
||||||
|
OnPress: func() error {
|
||||||
|
if err := self.copyFileContentToClipboard(node.GetPath()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
self.c.Toast(self.c.Tr.FileContentCopiedToast)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
DisabledReason: self.require(self.singleItemSelected(
|
||||||
|
func(node *filetree.CommitFileNode) *types.DisabledReason {
|
||||||
|
if !node.IsFile() {
|
||||||
|
return &types.DisabledReason{
|
||||||
|
Text: self.c.Tr.ErrCannotCopyContentOfDirectory,
|
||||||
|
ShowErrorInPanel: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}))(),
|
||||||
|
Key: 'c',
|
||||||
|
}
|
||||||
|
|
||||||
return self.c.Menu(types.CreateMenuOptions{
|
return self.c.Menu(types.CreateMenuOptions{
|
||||||
Title: self.c.Tr.CopyToClipboardMenu,
|
Title: self.c.Tr.CopyToClipboardMenu,
|
||||||
@ -254,6 +285,7 @@ func (self *CommitFilesController) openCopyMenu() error {
|
|||||||
copyPathItem,
|
copyPathItem,
|
||||||
copyFileDiffItem,
|
copyFileDiffItem,
|
||||||
copyAllDiff,
|
copyAllDiff,
|
||||||
|
copyFileContentItem,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -80,11 +80,13 @@ type TranslationSet struct {
|
|||||||
CopyFileDiffTooltip string
|
CopyFileDiffTooltip string
|
||||||
CopySelectedDiff string
|
CopySelectedDiff string
|
||||||
CopyAllFilesDiff string
|
CopyAllFilesDiff string
|
||||||
|
CopyFileContent string
|
||||||
NoContentToCopyError string
|
NoContentToCopyError string
|
||||||
FileNameCopiedToast string
|
FileNameCopiedToast string
|
||||||
FilePathCopiedToast string
|
FilePathCopiedToast string
|
||||||
FileDiffCopiedToast string
|
FileDiffCopiedToast string
|
||||||
AllFilesDiffCopiedToast string
|
AllFilesDiffCopiedToast string
|
||||||
|
FileContentCopiedToast string
|
||||||
FilterStagedFiles string
|
FilterStagedFiles string
|
||||||
FilterUnstagedFiles string
|
FilterUnstagedFiles string
|
||||||
FilterTrackedFiles string
|
FilterTrackedFiles string
|
||||||
@ -696,6 +698,7 @@ type TranslationSet struct {
|
|||||||
PatchCopiedToClipboard string
|
PatchCopiedToClipboard string
|
||||||
CopiedToClipboard string
|
CopiedToClipboard string
|
||||||
ErrCannotEditDirectory string
|
ErrCannotEditDirectory string
|
||||||
|
ErrCannotCopyContentOfDirectory string
|
||||||
ErrStageDirWithInlineMergeConflicts string
|
ErrStageDirWithInlineMergeConflicts string
|
||||||
ErrRepositoryMovedOrDeleted string
|
ErrRepositoryMovedOrDeleted string
|
||||||
ErrWorktreeMovedOrRemoved string
|
ErrWorktreeMovedOrRemoved string
|
||||||
@ -1120,11 +1123,13 @@ func EnglishTranslationSet() *TranslationSet {
|
|||||||
CopyFileDiffTooltip: "If there are staged items, this command considers only them. Otherwise, it considers all the unstaged ones.",
|
CopyFileDiffTooltip: "If there are staged items, this command considers only them. Otherwise, it considers all the unstaged ones.",
|
||||||
CopySelectedDiff: "Diff of selected file",
|
CopySelectedDiff: "Diff of selected file",
|
||||||
CopyAllFilesDiff: "Diff of all files",
|
CopyAllFilesDiff: "Diff of all files",
|
||||||
|
CopyFileContent: "Content of selected file",
|
||||||
NoContentToCopyError: "Nothing to copy",
|
NoContentToCopyError: "Nothing to copy",
|
||||||
FileNameCopiedToast: "File name copied to clipboard",
|
FileNameCopiedToast: "File name copied to clipboard",
|
||||||
FilePathCopiedToast: "File path copied to clipboard",
|
FilePathCopiedToast: "File path copied to clipboard",
|
||||||
FileDiffCopiedToast: "File diff copied to clipboard",
|
FileDiffCopiedToast: "File diff copied to clipboard",
|
||||||
AllFilesDiffCopiedToast: "All files diff copied to clipboard",
|
AllFilesDiffCopiedToast: "All files diff copied to clipboard",
|
||||||
|
FileContentCopiedToast: "File content copied to clipboard",
|
||||||
FilterStagedFiles: "Show only staged files",
|
FilterStagedFiles: "Show only staged files",
|
||||||
FilterUnstagedFiles: "Show only unstaged files",
|
FilterUnstagedFiles: "Show only unstaged files",
|
||||||
FilterTrackedFiles: "Show only tracked files",
|
FilterTrackedFiles: "Show only tracked files",
|
||||||
@ -1737,6 +1742,7 @@ func EnglishTranslationSet() *TranslationSet {
|
|||||||
PatchCopiedToClipboard: "Patch copied to clipboard",
|
PatchCopiedToClipboard: "Patch copied to clipboard",
|
||||||
CopiedToClipboard: "copied to clipboard",
|
CopiedToClipboard: "copied to clipboard",
|
||||||
ErrCannotEditDirectory: "Cannot edit directories: you can only edit individual files",
|
ErrCannotEditDirectory: "Cannot edit directories: you can only edit individual files",
|
||||||
|
ErrCannotCopyContentOfDirectory: "Cannot copy content of directories: you can only copy content of individual files",
|
||||||
ErrStageDirWithInlineMergeConflicts: "Cannot stage/unstage directory containing files with inline merge conflicts. Please fix up the merge conflicts first",
|
ErrStageDirWithInlineMergeConflicts: "Cannot stage/unstage directory containing files with inline merge conflicts. Please fix up the merge conflicts first",
|
||||||
ErrRepositoryMovedOrDeleted: "Cannot find repo. It might have been moved or deleted ¯\\_(ツ)_/¯",
|
ErrRepositoryMovedOrDeleted: "Cannot find repo. It might have been moved or deleted ¯\\_(ツ)_/¯",
|
||||||
CommandLog: "Command log",
|
CommandLog: "Command log",
|
||||||
|
@ -23,17 +23,21 @@ var CopyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
shell.CreateDir("dir")
|
shell.CreateDir("dir")
|
||||||
shell.CreateFileAndAdd("dir/file1", "1st line\n")
|
shell.CreateFileAndAdd("dir/file1", "1st line\n")
|
||||||
shell.Commit("1")
|
shell.Commit("1")
|
||||||
shell.CreateFileAndAdd("dir/file1", "1st line\n2nd line\n")
|
shell.UpdateFileAndAdd("dir/file1", "1st line\n2nd line\n")
|
||||||
shell.CreateFileAndAdd("dir/file2", "file2\n")
|
shell.CreateFileAndAdd("dir/file2", "file2\n")
|
||||||
shell.Commit("2")
|
shell.Commit("2")
|
||||||
|
shell.UpdateFileAndAdd("dir/file1", "1st line\n2nd line\n3rd line\n")
|
||||||
|
shell.Commit("3")
|
||||||
},
|
},
|
||||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
t.Views().Commits().
|
t.Views().Commits().
|
||||||
Focus().
|
Focus().
|
||||||
Lines(
|
Lines(
|
||||||
Contains("2").IsSelected(),
|
Contains("3").IsSelected(),
|
||||||
|
Contains("2"),
|
||||||
Contains("1"),
|
Contains("1"),
|
||||||
).
|
).
|
||||||
|
SelectNextItem().
|
||||||
PressEnter()
|
PressEnter()
|
||||||
|
|
||||||
t.Views().CommitFiles().
|
t.Views().CommitFiles().
|
||||||
@ -91,11 +95,22 @@ var CopyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
Contains("diff --git a/dir/file1 b/dir/file1").Contains("+2nd line").DoesNotContain("+1st line").
|
Contains("diff --git a/dir/file1 b/dir/file1").Contains("+2nd line").DoesNotContain("+1st line").
|
||||||
Contains("diff --git a/dir/file2 b/dir/file2").Contains("+file2"))
|
Contains("diff --git a/dir/file2 b/dir/file2").Contains("+file2"))
|
||||||
})
|
})
|
||||||
|
}).
|
||||||
|
Press(keys.Files.CopyFileInfoToClipboard).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Copy to clipboard")).
|
||||||
|
Select(Contains("Content of selected file")).
|
||||||
|
Confirm().
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectToast(Equals("File content copied to clipboard"))
|
||||||
|
expectClipboard(t, Equals("1st line\n2nd line\n"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Views().Commits().
|
t.Views().Commits().
|
||||||
Focus().
|
Focus().
|
||||||
// Select both commits
|
// Select commits 1 and 2
|
||||||
Press(keys.Universal.RangeSelectDown).
|
Press(keys.Universal.RangeSelectDown).
|
||||||
PressEnter()
|
PressEnter()
|
||||||
|
|
||||||
@ -118,6 +133,17 @@ var CopyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
expectClipboard(t,
|
expectClipboard(t,
|
||||||
Contains("diff --git a/dir/file1 b/dir/file1").Contains("+1st line").Contains("+2nd line"))
|
Contains("diff --git a/dir/file1 b/dir/file1").Contains("+1st line").Contains("+2nd line"))
|
||||||
})
|
})
|
||||||
|
}).
|
||||||
|
Press(keys.Files.CopyFileInfoToClipboard).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Equals("Copy to clipboard")).
|
||||||
|
Select(Contains("Content of selected file")).
|
||||||
|
Confirm().
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectToast(Equals("File content copied to clipboard"))
|
||||||
|
expectClipboard(t, Equals("1st line\n2nd line\n"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user