Skip to content

Commit 77651ca

Browse files
authored
Add "Absolute path" item to the file view's copy menu (#4410)
- **PR Description** Make it possible to copy the absolute path of a file to the clipboard. Addresses #4409.
2 parents 200e490 + a8f6b04 commit 77651ca

File tree

5 files changed

+74
-11
lines changed

5 files changed

+74
-11
lines changed

Diff for: pkg/gui/controllers/commits_files_controller.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controllers
22

33
import (
44
"errors"
5+
"path/filepath"
56
"strings"
67

78
"github.com/jesseduffield/gocui"
@@ -228,8 +229,8 @@ func (self *CommitFilesController) openCopyMenu() error {
228229
DisabledReason: self.require(self.singleItemSelected())(),
229230
Key: 'n',
230231
}
231-
copyPathItem := &types.MenuItem{
232-
Label: self.c.Tr.CopyFilePath,
232+
copyRelativePathItem := &types.MenuItem{
233+
Label: self.c.Tr.CopyRelativeFilePath,
233234
OnPress: func() error {
234235
if err := self.c.OS().CopyToClipboard(node.GetPath()); err != nil {
235236
return err
@@ -240,6 +241,18 @@ func (self *CommitFilesController) openCopyMenu() error {
240241
DisabledReason: self.require(self.singleItemSelected())(),
241242
Key: 'p',
242243
}
244+
copyAbsolutePathItem := &types.MenuItem{
245+
Label: self.c.Tr.CopyAbsoluteFilePath,
246+
OnPress: func() error {
247+
if err := self.c.OS().CopyToClipboard(filepath.Join(self.c.Git().RepoPaths.RepoPath(), node.GetPath())); err != nil {
248+
return err
249+
}
250+
self.c.Toast(self.c.Tr.FilePathCopiedToast)
251+
return nil
252+
},
253+
DisabledReason: self.require(self.singleItemSelected())(),
254+
Key: 'P',
255+
}
243256
copyFileDiffItem := &types.MenuItem{
244257
Label: self.c.Tr.CopySelectedDiff,
245258
OnPress: func() error {
@@ -282,7 +295,8 @@ func (self *CommitFilesController) openCopyMenu() error {
282295
Title: self.c.Tr.CopyToClipboardMenu,
283296
Items: []*types.MenuItem{
284297
copyNameItem,
285-
copyPathItem,
298+
copyRelativePathItem,
299+
copyAbsolutePathItem,
286300
copyFileDiffItem,
287301
copyAllDiff,
288302
copyFileContentItem,

Diff for: pkg/gui/controllers/files_controller.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllers
33
import (
44
"errors"
55
"fmt"
6+
"path/filepath"
67
"strings"
78

89
"github.com/jesseduffield/gocui"
@@ -976,8 +977,8 @@ func (self *FilesController) openCopyMenu() error {
976977
DisabledReason: self.require(self.singleItemSelected())(),
977978
Key: 'n',
978979
}
979-
copyPathItem := &types.MenuItem{
980-
Label: self.c.Tr.CopyFilePath,
980+
copyRelativePathItem := &types.MenuItem{
981+
Label: self.c.Tr.CopyRelativeFilePath,
981982
OnPress: func() error {
982983
if err := self.c.OS().CopyToClipboard(node.GetPath()); err != nil {
983984
return err
@@ -988,6 +989,18 @@ func (self *FilesController) openCopyMenu() error {
988989
DisabledReason: self.require(self.singleItemSelected())(),
989990
Key: 'p',
990991
}
992+
copyAbsolutePathItem := &types.MenuItem{
993+
Label: self.c.Tr.CopyAbsoluteFilePath,
994+
OnPress: func() error {
995+
if err := self.c.OS().CopyToClipboard(filepath.Join(self.c.Git().RepoPaths.RepoPath(), node.GetPath())); err != nil {
996+
return err
997+
}
998+
self.c.Toast(self.c.Tr.FilePathCopiedToast)
999+
return nil
1000+
},
1001+
DisabledReason: self.require(self.singleItemSelected())(),
1002+
Key: 'P',
1003+
}
9911004
copyFileDiffItem := &types.MenuItem{
9921005
Label: self.c.Tr.CopySelectedDiff,
9931006
Tooltip: self.c.Tr.CopyFileDiffTooltip,
@@ -1044,7 +1057,8 @@ func (self *FilesController) openCopyMenu() error {
10441057
Title: self.c.Tr.CopyToClipboardMenu,
10451058
Items: []*types.MenuItem{
10461059
copyNameItem,
1047-
copyPathItem,
1060+
copyRelativePathItem,
1061+
copyAbsolutePathItem,
10481062
copyFileDiffItem,
10491063
copyAllDiff,
10501064
},

Diff for: pkg/i18n/english.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ type TranslationSet struct {
7676
FileFilter string
7777
CopyToClipboardMenu string
7878
CopyFileName string
79-
CopyFilePath string
79+
CopyRelativeFilePath string
80+
CopyAbsoluteFilePath string
8081
CopyFileDiffTooltip string
8182
CopySelectedDiff string
8283
CopyAllFilesDiff string
@@ -1120,7 +1121,8 @@ func EnglishTranslationSet() *TranslationSet {
11201121
FileFilter: "Filter files by status",
11211122
CopyToClipboardMenu: "Copy to clipboard",
11221123
CopyFileName: "File name",
1123-
CopyFilePath: "Path",
1124+
CopyRelativeFilePath: "Relative path",
1125+
CopyAbsoluteFilePath: "Absolute path",
11241126
CopyFileDiffTooltip: "If there are staged items, this command considers only them. Otherwise, it considers all the unstaged ones.",
11251127
CopySelectedDiff: "Diff of selected file",
11261128
CopyAllFilesDiff: "Diff of all files",

Diff for: pkg/integration/tests/diff/copy_to_clipboard.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package diff
22

33
import (
4+
"os"
5+
46
"github.com/jesseduffield/lazygit/pkg/config"
57
. "github.com/jesseduffield/lazygit/pkg/integration/components"
68
)
@@ -63,14 +65,27 @@ var CopyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
6365
Tap(func() {
6466
t.ExpectPopup().Menu().
6567
Title(Equals("Copy to clipboard")).
66-
Select(Contains("Path")).
68+
Select(Contains("Relative path")).
6769
Confirm().
6870
Tap(func() {
6971
t.ExpectToast(Equals("File path copied to clipboard"))
7072
expectClipboard(t, Equals("dir/file1"))
7173
})
7274
}).
7375
Press(keys.Files.CopyFileInfoToClipboard).
76+
Tap(func() {
77+
t.ExpectPopup().Menu().
78+
Title(Equals("Copy to clipboard")).
79+
Select(Contains("Absolute path")).
80+
Confirm().
81+
Tap(func() {
82+
t.ExpectToast(Equals("File path copied to clipboard"))
83+
repoDir, _ := os.Getwd()
84+
// On windows the following path would have backslashes, but we don't run integration tests on windows yet.
85+
expectClipboard(t, Equals(repoDir+"/dir/file1"))
86+
})
87+
}).
88+
Press(keys.Files.CopyFileInfoToClipboard).
7489
Tap(func() {
7590
t.ExpectPopup().Menu().
7691
Title(Equals("Copy to clipboard")).

Diff for: pkg/integration/tests/file/copy_menu.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package file
22

33
import (
4+
"os"
5+
46
"github.com/jesseduffield/lazygit/pkg/config"
57
. "github.com/jesseduffield/lazygit/pkg/integration/components"
68
)
@@ -103,20 +105,36 @@ var CopyMenu = NewIntegrationTest(NewIntegrationTestArgs{
103105
expectClipboard(t, Equals("1-unstaged_file"))
104106
})
105107

106-
// Copy file path
108+
// Copy relative file path
107109
t.Views().Files().
108110
Press(keys.Files.CopyFileInfoToClipboard).
109111
Tap(func() {
110112
t.ExpectPopup().Menu().
111113
Title(Equals("Copy to clipboard")).
112-
Select(Contains("Path")).
114+
Select(Contains("Relative path")).
113115
Confirm()
114116

115117
t.ExpectToast(Equals("File path copied to clipboard"))
116118

117119
expectClipboard(t, Equals("dir/1-unstaged_file"))
118120
})
119121

122+
// Copy absolute file path
123+
t.Views().Files().
124+
Press(keys.Files.CopyFileInfoToClipboard).
125+
Tap(func() {
126+
t.ExpectPopup().Menu().
127+
Title(Equals("Copy to clipboard")).
128+
Select(Contains("Absolute path")).
129+
Confirm()
130+
131+
t.ExpectToast(Equals("File path copied to clipboard"))
132+
133+
repoDir, _ := os.Getwd()
134+
// On windows the following path would have backslashes, but we don't run integration tests on windows yet.
135+
expectClipboard(t, Equals(repoDir+"/dir/1-unstaged_file"))
136+
})
137+
120138
// Selected path diff on a single (unstaged) file
121139
t.Views().Files().
122140
Press(keys.Files.CopyFileInfoToClipboard).

0 commit comments

Comments
 (0)