diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index d2d98ac52..9d61cb68f 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -189,6 +189,7 @@ type KeybindingFilesConfig struct { Fetch string `yaml:"fetch"` ToggleTreeView string `yaml:"toggleTreeView"` OpenMergeTool string `yaml:"openMergeTool"` + OpenStatusFilter string `yaml:"openStatusFilter"` } type KeybindingBranchesConfig struct { @@ -438,6 +439,7 @@ func GetDefaultConfig() *UserConfig { Fetch: "f", ToggleTreeView: "`", OpenMergeTool: "M", + OpenStatusFilter: "", }, Branches: KeybindingBranchesConfig{ CopyPullRequestURL: "", diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index f652c3f05..ac9b117eb 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -473,6 +473,39 @@ func (gui *Gui) handleCommitEditorPress() error { ) } +func (gui *Gui) handleStatusFilterPressed() error { + menuItems := []*menuItem{} + + menuItems = append(menuItems, &menuItem{ + displayString: "Show only staged files", + onPress: func() error { + return gui.setStatusFiltering(filetree.DisplayStaged) + }, + }) + + menuItems = append(menuItems, &menuItem{ + displayString: "Show only unstaged files", + onPress: func() error { + return gui.setStatusFiltering(filetree.DisplayUnstaged) + }, + }) + + menuItems = append(menuItems, &menuItem{ + displayString: "Reset Filter", + onPress: func() error { + return gui.setStatusFiltering(filetree.DisplayAll) + }, + }) + + return gui.createMenu(gui.Tr.FilteringMenuTitle, menuItems, createMenuOptions{showCancel: false}) +} + +func (gui *Gui) setStatusFiltering(filter filetree.FileManagerDisplayFilter) error { + state := gui.State + state.FileManager.SetDisplayFilter(filter) + return gui.handleRefreshFiles() +} + func (gui *Gui) editFile(filename string) error { return gui.editFileAtLine(filename, 1) } diff --git a/pkg/gui/filetree/file_manager.go b/pkg/gui/filetree/file_manager.go index 825ee0b01..699e20332 100644 --- a/pkg/gui/filetree/file_manager.go +++ b/pkg/gui/filetree/file_manager.go @@ -8,11 +8,20 @@ import ( "github.com/sirupsen/logrus" ) +type FileManagerDisplayFilter int + +const ( + DisplayAll FileManagerDisplayFilter = iota + DisplayStaged + DisplayUnstaged +) + type FileManager struct { files []*models.File tree *FileNode showTree bool log *logrus.Entry + filter FileManagerDisplayFilter collapsedPaths CollapsedPaths sync.RWMutex } @@ -22,6 +31,7 @@ func NewFileManager(files []*models.File, log *logrus.Entry, showTree bool) *Fil files: files, log: log, showTree: showTree, + filter: DisplayAll, collapsedPaths: CollapsedPaths{}, RWMutex: sync.RWMutex{}, } @@ -35,6 +45,35 @@ func (m *FileManager) ExpandToPath(path string) { m.collapsedPaths.ExpandToPath(path) } +func (m *FileManager) GetFilesForDisplay() []*models.File { + files := m.files + if m.filter == DisplayAll { + return files + } + + result := make([]*models.File, 0) + if m.filter == DisplayStaged { + for _, file := range files { + if file.HasStagedChanges { + result = append(result, file) + } + } + } else { + for _, file := range files { + if !file.HasStagedChanges { + result = append(result, file) + } + } + } + + return result +} + +func (m *FileManager) SetDisplayFilter(filter FileManagerDisplayFilter) { + m.filter = filter + m.SetTree() +} + func (m *FileManager) ToggleShowTree() { m.showTree = !m.showTree m.SetTree() @@ -73,10 +112,11 @@ func (m *FileManager) SetFiles(files []*models.File) { } func (m *FileManager) SetTree() { + filesForDisplay := m.GetFilesForDisplay() if m.showTree { - m.tree = BuildTreeFromFiles(m.files) + m.tree = BuildTreeFromFiles(filesForDisplay) } else { - m.tree = BuildFlatTreeFromFiles(m.files) + m.tree = BuildFlatTreeFromFiles(filesForDisplay) } } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 4b20bab95..4d593dbd0 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -381,6 +381,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Handler: gui.handleShowAllBranchLogs, Description: gui.Tr.LcAllBranchesLogGraph, }, + { + ViewName: "files", + Key: gui.getKey(""), + Handler: gui.handleStatusFilterPressed, + Description: gui.Tr.LcCommitFileFilter, + }, { ViewName: "files", Contexts: []string{string(FILES_CONTEXT_KEY)}, diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go index cd8e2160c..4cf5a91c7 100644 --- a/pkg/i18n/dutch.go +++ b/pkg/i18n/dutch.go @@ -42,6 +42,7 @@ func dutchTranslationSet() TranslationSet { LcScroll: "scroll", LcAbortMerge: "samenvoegen afbreken", LcResolveMergeConflicts: "los merge conflicten op", + LcCommitFileFilter: "Commit dossiers filteren", MergeConflictsTitle: "Merge Conflicten", LcCheckout: "uitchecken", FileHasNoUnstagedChanges: "Het bestand heeft geen unstaged veranderingen om toe te voegen", diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index e2a9f38de..529004319 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -55,6 +55,7 @@ type TranslationSet struct { LcScroll string LcAbortMerge string LcResolveMergeConflicts string + LcCommitFileFilter string MergeConflictsTitle string LcCheckout string NoChangedFiles string @@ -608,6 +609,7 @@ func englishTranslationSet() TranslationSet { LcResolveMergeConflicts: "resolve merge conflicts", MergeConflictsTitle: "Merge Conflicts", LcCheckout: "checkout", + LcCommitFileFilter: "Filter commit files", NoChangedFiles: "No changed files", FileHasNoUnstagedChanges: "File has no unstaged changes to add", CannotGitAdd: "Cannot git add --patch untracked files", diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go index 1420d2ef9..c40e889ba 100644 --- a/pkg/i18n/polish.go +++ b/pkg/i18n/polish.go @@ -37,6 +37,7 @@ func polishTranslationSet() TranslationSet { LcScroll: "przewiń", LcAbortMerge: "o scalaniu", LcResolveMergeConflicts: "rozwiąż konflikty scalania", + LcCommitFileFilter: "Filtrowanie plików commitować", LcCheckout: "przełącz", NoChangedFiles: "Brak zmienionych plików", FileHasNoUnstagedChanges: "Plik nie zawiera żadnych nieopublikowanych zmian do dodania",