mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-23 12:18:51 +02:00
Allow user to filter the files view to only show untracked files (#4226)
This handles the situation where the user's own config says to not show untracked files, as is often the case with bare repos managing a user's dotfiles. - **PR Description** - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [x] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [x] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc <!-- Be sure to name your PR with an imperative e.g. 'Add worktrees view' see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for examples -->
This commit is contained in:
commit
a1838d33e7
@ -32,13 +32,17 @@ func NewFileLoader(gitCommon *GitCommon, cmd oscommands.ICmdObjBuilder, config F
|
||||
|
||||
type GetStatusFileOptions struct {
|
||||
NoRenames bool
|
||||
// If true, we'll show untracked files even if the user has set the config to hide them.
|
||||
// This is useful for users with bare repos for dotfiles who default to hiding untracked files,
|
||||
// but want to occasionally see them to `git add` a new file.
|
||||
ForceShowUntracked bool
|
||||
}
|
||||
|
||||
func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
|
||||
// check if config wants us ignoring untracked files
|
||||
untrackedFilesSetting := self.config.GetShowUntrackedFiles()
|
||||
|
||||
if untrackedFilesSetting == "" {
|
||||
if opts.ForceShowUntracked || untrackedFilesSetting == "" {
|
||||
untrackedFilesSetting = "all"
|
||||
}
|
||||
untrackedFilesArg := fmt.Sprintf("--untracked-files=%s", untrackedFilesSetting)
|
||||
|
@ -777,6 +777,13 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
},
|
||||
Key: 't',
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.FilterUntrackedFiles,
|
||||
OnPress: func() error {
|
||||
return self.setStatusFiltering(filetree.DisplayUntracked)
|
||||
},
|
||||
Key: 'T',
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.ResetFilter,
|
||||
OnPress: func() error {
|
||||
@ -789,9 +796,19 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
||||
}
|
||||
|
||||
func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error {
|
||||
previousFilter := self.context().GetFilter()
|
||||
|
||||
self.context().FileTreeViewModel.SetStatusFilter(filter)
|
||||
self.c.PostRefreshUpdate(self.context())
|
||||
return nil
|
||||
|
||||
// Whenever we switch between untracked and other filters, we need to refresh the files view
|
||||
// because the untracked files filter applies when running `git status`.
|
||||
if previousFilter != filter && (previousFilter == filetree.DisplayUntracked || filter == filetree.DisplayUntracked) {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}, Mode: types.ASYNC})
|
||||
} else {
|
||||
self.c.PostRefreshUpdate(self.context())
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FilesController) edit(nodes []*filetree.FileNode) error {
|
||||
|
@ -570,7 +570,9 @@ func (self *RefreshHelper) refreshStateFiles() error {
|
||||
}
|
||||
|
||||
files := self.c.Git().Loaders.FileLoader.
|
||||
GetStatusFiles(git_commands.GetStatusFileOptions{})
|
||||
GetStatusFiles(git_commands.GetStatusFileOptions{
|
||||
ForceShowUntracked: self.c.Contexts().Files.ForceShowUntracked(),
|
||||
})
|
||||
|
||||
conflictFileCount := 0
|
||||
for _, file := range files {
|
||||
|
@ -16,6 +16,7 @@ const (
|
||||
DisplayStaged
|
||||
DisplayUnstaged
|
||||
DisplayTracked
|
||||
DisplayUntracked
|
||||
// this shows files with merge conflicts
|
||||
DisplayConflicted
|
||||
)
|
||||
@ -40,6 +41,7 @@ type IFileTree interface {
|
||||
|
||||
FilterFiles(test func(*models.File) bool) []*models.File
|
||||
SetStatusFilter(filter FileTreeDisplayFilter)
|
||||
ForceShowUntracked() bool
|
||||
Get(index int) *FileNode
|
||||
GetFile(path string) *models.File
|
||||
GetAllItems() []*FileNode
|
||||
@ -87,6 +89,8 @@ func (self *FileTree) getFilesForDisplay() []*models.File {
|
||||
return self.FilterFiles(func(file *models.File) bool { return file.HasUnstagedChanges })
|
||||
case DisplayTracked:
|
||||
return self.FilterFiles(func(file *models.File) bool { return file.Tracked })
|
||||
case DisplayUntracked:
|
||||
return self.FilterFiles(func(file *models.File) bool { return !file.Tracked })
|
||||
case DisplayConflicted:
|
||||
return self.FilterFiles(func(file *models.File) bool { return file.HasMergeConflicts })
|
||||
default:
|
||||
@ -94,6 +98,10 @@ func (self *FileTree) getFilesForDisplay() []*models.File {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FileTree) ForceShowUntracked() bool {
|
||||
return self.filter == DisplayUntracked
|
||||
}
|
||||
|
||||
func (self *FileTree) FilterFiles(test func(*models.File) bool) []*models.File {
|
||||
return lo.Filter(self.getFiles(), func(file *models.File, _ int) bool { return test(file) })
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ type TranslationSet struct {
|
||||
FilterStagedFiles string
|
||||
FilterUnstagedFiles string
|
||||
FilterTrackedFiles string
|
||||
FilterUntrackedFiles string
|
||||
ResetFilter string
|
||||
MergeConflictsTitle string
|
||||
Checkout string
|
||||
@ -1113,6 +1114,7 @@ func EnglishTranslationSet() *TranslationSet {
|
||||
FilterStagedFiles: "Show only staged files",
|
||||
FilterUnstagedFiles: "Show only unstaged files",
|
||||
FilterTrackedFiles: "Show only tracked files",
|
||||
FilterUntrackedFiles: "Show only untracked files",
|
||||
ResetFilter: "Reset filter",
|
||||
NoChangedFiles: "No changed files",
|
||||
SoftReset: "Soft reset",
|
||||
|
@ -0,0 +1,62 @@
|
||||
package filter_and_search
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var FilterByFileStatus = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Filtering to show untracked files in repo that hides them by default",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
// need to set untracked files to not be displayed in git config
|
||||
shell.SetConfig("status.showUntrackedFiles", "no")
|
||||
|
||||
shell.CreateFileAndAdd("file-tracked", "foo")
|
||||
|
||||
shell.Commit("first commit")
|
||||
|
||||
shell.CreateFile("file-untracked", "bar")
|
||||
shell.UpdateFile("file-tracked", "baz")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains(`file-tracked`).IsSelected(),
|
||||
).
|
||||
Press(keys.Files.OpenStatusFilter).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Filtering")).
|
||||
Select(Contains("Show only untracked files")).
|
||||
Confirm()
|
||||
}).
|
||||
Lines(
|
||||
Contains(`file-untracked`).IsSelected(),
|
||||
).
|
||||
Press(keys.Files.OpenStatusFilter).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Filtering")).
|
||||
Select(Contains("Show only tracked files")).
|
||||
Confirm()
|
||||
}).
|
||||
Lines(
|
||||
Contains(`file-tracked`).IsSelected(),
|
||||
).
|
||||
Press(keys.Files.OpenStatusFilter).
|
||||
Tap(func() {
|
||||
t.ExpectPopup().Menu().
|
||||
Title(Equals("Filtering")).
|
||||
Select(Contains("Reset filter")).
|
||||
Confirm()
|
||||
}).
|
||||
Lines(
|
||||
Contains(`file-tracked`).IsSelected(),
|
||||
)
|
||||
},
|
||||
})
|
@ -186,6 +186,7 @@ var tests = []*components.IntegrationTest{
|
||||
file.StageChildrenRangeSelect,
|
||||
file.StageDeletedRangeSelect,
|
||||
file.StageRangeSelect,
|
||||
filter_and_search.FilterByFileStatus,
|
||||
filter_and_search.FilterCommitFiles,
|
||||
filter_and_search.FilterFiles,
|
||||
filter_and_search.FilterFuzzy,
|
||||
|
Loading…
x
Reference in New Issue
Block a user