summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Déplantes <3098462+part22@users.noreply.github.com>2024-01-21 22:55:26 -0500
committerStefan Haller <stefan@haller-berlin.de>2024-02-21 09:58:09 +0100
commit503422a72ec0dffbb1ade37ae75e24e48f9f94f0 (patch)
treebd3a102d96cf0edda899d317413eb037e780358c
parent329b4349156d290b9ad2ea95ac86c382c362b28f (diff)
Add author filtering to commit view
This commit introduces a new feature to the commit view, allowing users to filter commits based on the author's name or email address. Similar to the existing path filtering functionality, accessible through <c-s>, this feature allows users to filter the commit history by the currently selected commit's author if the commit view is focused, or by typing in the author's name or email address. This feature adds an entry to the filtering menu, to provide users with a familiar and intuitive experience
-rw-r--r--docs/keybindings/Keybindings_en.md2
-rw-r--r--docs/keybindings/Keybindings_ja.md2
-rw-r--r--docs/keybindings/Keybindings_ko.md2
-rw-r--r--docs/keybindings/Keybindings_nl.md2
-rw-r--r--docs/keybindings/Keybindings_pl.md2
-rw-r--r--docs/keybindings/Keybindings_ru.md2
-rw-r--r--docs/keybindings/Keybindings_zh-CN.md2
-rw-r--r--docs/keybindings/Keybindings_zh-TW.md2
-rw-r--r--pkg/commands/git_commands/commit_loader.go2
-rw-r--r--pkg/commands/git_commands/reflog_commit_loader.go3
-rw-r--r--pkg/commands/git_commands/reflog_commit_loader_test.go28
-rw-r--r--pkg/gui/controllers/filtering_menu_action.go52
-rw-r--r--pkg/gui/controllers/helpers/mode_helper.go3
-rw-r--r--pkg/gui/controllers/helpers/refresh_helper.go12
-rw-r--r--pkg/gui/controllers/helpers/sub_commits_helper.go1
-rw-r--r--pkg/gui/gui.go2
-rw-r--r--pkg/gui/modes/filtering/filtering.go18
-rw-r--r--pkg/i18n/english.go13
-rw-r--r--pkg/integration/tests/filter_by_author/select_author.go70
-rw-r--r--pkg/integration/tests/filter_by_author/shared.go30
-rw-r--r--pkg/integration/tests/filter_by_author/type_author.go66
-rw-r--r--pkg/integration/tests/test_list.go3
22 files changed, 292 insertions, 27 deletions
diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md
index 550b3640f..a5a09b236 100644
--- a/docs/keybindings/Keybindings_en.md
+++ b/docs/keybindings/Keybindings_en.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | Next screen mode (normal/half/fullscreen) | |
| `` _ `` | Prev screen mode | |
| `` ? `` | Open keybindings menu | |
-| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Quit | |
diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md
index b19f42fe7..9c1c2661a 100644
--- a/docs/keybindings/Keybindings_ja.md
+++ b/docs/keybindings/Keybindings_ja.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | 次のスクリーンモード (normal/half/fullscreen) | |
| `` _ `` | 前のスクリーンモード | |
| `` ? `` | メニューを開く | |
-| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 終了 | |
diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md
index deb40f5e4..cb3339618 100644
--- a/docs/keybindings/Keybindings_ko.md
+++ b/docs/keybindings/Keybindings_ko.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | 다음 스크린 모드 (normal/half/fullscreen) | |
| `` _ `` | 이전 스크린 모드 | |
| `` ? `` | 매뉴 열기 | |
-| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 종료 | |
diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md
index fb978f8a1..37cac5a7f 100644
--- a/docs/keybindings/Keybindings_nl.md
+++ b/docs/keybindings/Keybindings_nl.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | Volgende scherm modus (normaal/half/groot) | |
| `` _ `` | Vorige scherm modus | |
| `` ? `` | Open menu | |
-| `` <c-s> `` | Bekijk scoping opties | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | Bekijk scoping opties | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Quit | |
diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md
index 87693d9b0..18a4ca0fc 100644
--- a/docs/keybindings/Keybindings_pl.md
+++ b/docs/keybindings/Keybindings_pl.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | Next screen mode (normal/half/fullscreen) | |
| `` _ `` | Prev screen mode | |
| `` ? `` | Open keybindings menu | |
-| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | View filter options | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Quit | |
diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md
index f1e0ade98..2206ed4a0 100644
--- a/docs/keybindings/Keybindings_ru.md
+++ b/docs/keybindings/Keybindings_ru.md
@@ -23,7 +23,7 @@ _Связки клавиш_
| `` + `` | Следующий режим экрана (нормальный/полуэкранный/полноэкранный) | |
| `` _ `` | Предыдущий режим экрана | |
| `` ? `` | Открыть меню | |
-| `` <c-s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | Выйти | |
diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md
index 2c54d9e86..a81925852 100644
--- a/docs/keybindings/Keybindings_zh-CN.md
+++ b/docs/keybindings/Keybindings_zh-CN.md
@@ -23,7 +23,7 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
| `` + `` | 下一屏模式(正常/半屏/全屏) | |
| `` _ `` | 上一屏模式 | |
| `` ? `` | 打开菜单 | |
-| `` <c-s> `` | 查看按路径过滤选项 | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | 查看按路径过滤选项 | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 退出 | |
diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md
index 73061e5cb..8edabd1c7 100644
--- a/docs/keybindings/Keybindings_zh-TW.md
+++ b/docs/keybindings/Keybindings_zh-TW.md
@@ -23,7 +23,7 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
| `` + `` | 下一個螢幕模式(常規/半螢幕/全螢幕) | |
| `` _ `` | 上一個螢幕模式 | |
| `` ? `` | 開啟選單 | |
-| `` <c-s> `` | 檢視篩選路徑選項 | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
+| `` <c-s> `` | 檢視篩選路徑選項 | View options for filtering the commit log, so that only commits matching the filter are shown. |
| `` W `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` <c-e> `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
| `` q `` | 結束 | |
diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go
index 7c385d2fa..2acde9da5 100644
--- a/pkg/commands/git_commands/commit_loader.go
+++ b/pkg/commands/git_commands/commit_loader.go
@@ -64,6 +64,7 @@ func NewCommitLoader(
type GetCommitsOptions struct {
Limit bool
FilterPath string
+ FilterAuthor string
IncludeRebaseCommits bool
RefName string // e.g. "HEAD" or "my_branch"
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
@@ -664,6 +665,7 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
Arg("--oneline").
Arg(prettyFormat).
Arg("--abbrev=40").
+ ArgIf(opts.FilterAuthor != "", "--author="+opts.FilterAuthor).
ArgIf(opts.Limit, "-300").
ArgIf(opts.FilterPath != "", "--follow").
Arg("--no-show-signature").
diff --git a/pkg/commands/git_commands/reflog_commit_loader.go b/pkg/commands/git_commands/reflog_commit_loader.go
index 1160839d6..b8682241a 100644
--- a/pkg/commands/git_commands/reflog_commit_loader.go
+++ b/pkg/commands/git_commands/reflog_commit_loader.go
@@ -23,7 +23,7 @@ func NewReflogCommitLoader(common *common.Common, cmd oscommands.ICmdObjBuilder)
// GetReflogCommits only returns the new reflog commits since the given lastReflogCommit
// if none is passed (i.e. it's value is nil) then we get all the reflog commits
-func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string) ([]*models.Commit, bool, error) {
+func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string, filterAuthor string) ([]*models.Commit, bool, error) {
commits := make([]*models.Commit, 0)
cmdArgs := NewGitCmd("log").
@@ -31,6 +31,7 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
Arg("-g").
Arg("--abbrev=40").
Arg("--format=%h%x00%ct%x00%gs%x00%p").
+ ArgIf(filterAuthor != "", "--author="+filterAuthor).
ArgIf(filterPath != "", "--follow", "--", filterPath).
ToArgv()
diff --git a/pkg/commands/git_commands/reflog_commit_loader_test.go b/pkg/commands/git_commands/reflog_commit_loader_test.go
index c17f7e2ba..a8a249588 100644
--- a/pkg/commands/git_commands/reflog_commit_loader_test.go
+++ b/pkg/commands/git_commands/reflog_commit_loader_test.go
@@ -25,6 +25,7 @@ func TestGetReflogCommits(t *testing.T) {
runner *oscommands.FakeCmdObjRunner
lastReflogCommit *models.Commit
filterPath string
+ filterAuthor string
expectedCommits []*models.Commit
expectedOnlyObtainedNew bool
expectedError error
@@ -137,6 +138,31 @@ func TestGetReflogCommits(t *testing.T) {
expectedError: nil,
},
{
+ testName: "when passing filterAuthor",
+ runner: oscommands.NewFakeRunner(t).
+ ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p", "--author=John Doe <john@doe.com>"}, reflogOutput, nil),
+
+ lastReflogCommit: &models.Commit{
+ Sha: "c3c4b66b64c97ffeecde",
+ Name: "checkout: moving from B to A",
+ Status: models.StatusReflog,
+ UnixTimestamp: 1643150483,
+ Parents: []string{"51baa8c1"},
+ },
+ filterAuthor: "John Doe <john@doe.com>",
+ expectedCommits: []*models.Commit{
+ {
+ Sha: "c3c4b66b64c97ffeecde",
+ Name: "checkout: moving from A to B",
+ Status: models.StatusReflog,
+ UnixTimestamp: 1643150483,
+ Parents: []string{"51baa8c1"},
+ },
+ },
+ expectedOnlyObtainedNew: true,
+ expectedError: nil,
+ },
+ {
testName: "when command returns error",
runner: oscommands.NewFakeRunner(t).
ExpectGitArgs([]string{"-c", "log.showSignature=false", "log", "-g", "--abbrev=40", "--format=%h%x00%ct%x00%gs%x00%p"}, "", errors.New("haha")),
@@ -157,7 +183,7 @@ func TestGetReflogCommits(t *testing.T) {
cmd: oscommands.NewDummyCmdObjBuilder(scenario.runner),
}
- commits, onlyObtainednew, err := builder.GetReflogCommits(scenario.lastReflogCommit, scenario.filterPath)
+ commits, onlyObtainednew, err := builder.GetReflogCommits(scenario.lastReflogCommit, scenario.filterPath, scenario.filterAuthor)
assert.Equal(t, scenario.expectedOnlyObtainedNew, onlyObtainednew)
assert.Equal(t, scenario.expectedError, err)
t.Logf("actual commits: \n%s", litter.Sdump(commits))
diff --git a/pkg/gui/controllers/filtering_menu_action.go b/pkg/gui/controllers/filtering_menu_action.go
index d8525b99d..9af0276e5 100644
--- a/pkg/gui/controllers/filtering_menu_action.go
+++ b/pkg/gui/controllers/filtering_menu_action.go
@@ -13,6 +13,7 @@ type FilteringMenuAction struct {
func (self *FilteringMenuAction) Call() error {
fileName := ""
+ author := ""
switch self.c.CurrentSideContext() {
case self.c.Contexts().Files:
node := self.c.Contexts().Files.GetSelected()
@@ -24,16 +25,36 @@ func (self *FilteringMenuAction) Call() error {
if node != nil {
fileName = node.GetPath()
}
+ case self.c.Contexts().LocalCommits:
+ commit := self.c.Contexts().LocalCommits.GetSelected()
+ if commit != nil {
+ author = fmt.Sprintf("%s <%s>", commit.AuthorName, commit.AuthorEmail)
+ }
}
menuItems := []*types.MenuItem{}
+ tooltip := ""
+ if self.c.Modes().Filtering.Active() {
+ tooltip = self.c.Tr.WillCancelExistingFilterTooltip
+ }
if fileName != "" {
menuItems = append(menuItems, &types.MenuItem{
Label: fmt.Sprintf("%s '%s'", self.c.Tr.FilterBy, fileName),
OnPress: func() error {
- return self.setFiltering(fileName)
+ return self.setFilteringPath(fileName)
},
+ Tooltip: tooltip,
+ })
+ }
+
+ if author != "" {
+ menuItems = append(menuItems, &types.MenuItem{
+ Label: fmt.Sprintf("%s '%s'", self.c.Tr.FilterBy, author),
+ OnPress: func() error {
+ return self.setFilteringAuthor(author)
+ },
+ Tooltip: tooltip,
})
}
@@ -44,10 +65,25 @@ func (self *FilteringMenuAction) Call() error {
FindSuggestionsFunc: self.c.Helpers().Suggestions.GetFilePathSuggestionsFunc(),
Title: self.c.Tr.EnterFileName,
HandleConfirm: func(response string) error {
- return self.setFiltering(strings.TrimSpace(response))
+ return self.setFilteringPath(strings.TrimSpace(response))
},
})
},
+ Tooltip: tooltip,
+ })
+
+ menuItems = append(menuItems, &types.MenuItem{
+ Label: self.c.Tr.FilterAuthorOption,
+ OnPress: func() error {
+ return self.c.Prompt(types.PromptOpts{
+ FindSuggestionsFunc: self.c.Helpers().Suggestions.GetAuthorsSuggestionsFunc(),
+ Title: self.c.Tr.EnterAuthor,
+ HandleConfirm: func(response string) error {
+ return self.setFilteringAuthor(strings.TrimSpace(response))
+ },
+ })
+ },
+ Tooltip: tooltip,
})
if self.c.Modes().Filtering.Active() {
@@ -60,9 +96,19 @@ func (self *FilteringMenuAction) Call() error {
return self.c.Menu(types.CreateMenuOptions{Title: self.c.Tr.FilteringMenuTitle, Items: menuItems})
}
-func (self *FilteringMenuAction) setFiltering(path string) error {
+func (self *FilteringMenuAction) setFilteringPath(path string) error {
+ self.c.Modes().Filtering.Reset()
self.c.Modes().Filtering.SetPath(path)
+ return self.setFiltering()
+}
+
+func (self *FilteringMenuAction) setFilteringAuthor(author string) error {
+ self.c.Modes().Filtering.Reset()
+ self.c.Modes().Filtering.SetAuthor(author)
+ return self.setFiltering()
+}
+func (self *FilteringMenuAction) setFiltering() error {
repoState := self.c.State().GetRepoState()
if repoState.GetScreenMode() == types.SCREEN_NORMAL {
repoState.SetScreenMode(types.SCREEN_HALF)
diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go
index 27c2b9aec..a25862252 100644
--- a/pkg/gui/controllers/helpers/mode_helper.go
+++ b/pkg/gui/controllers/helpers/mode_helper.go
@@ -72,11 +72,12 @@ func (self *ModeHelper) Statuses() []ModeStatus {
{
IsActive: self.c.Modes().Filtering.Active,
Description: func() string {
+ filterContent := lo.Ternary(self.c.Modes().Filtering.GetPath() != "", self.c.Modes().Filtering.GetPath(), self.c.Modes().Filtering.GetAuthor())
return self.withResetButton(
fmt.Sprintf(
"%s '%s'",
self.c.Tr.FilteringBy,
- self.c.Modes().Filtering.GetPath(),
+ filterContent,
),
style.FgRed,
)
diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go
index 04b741b56..da43c47bb 100644
--- a/pkg/gui/controllers/helpers/refresh_helper.go
+++ b/pkg/gui/controllers/helpers/refresh_helper.go
@@ -317,6 +317,7 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
git_commands.GetCommitsOptions{
Limit: self.c.Contexts().LocalCommits.GetLimitCommits(),
FilterPath: self.c.Modes().Filtering.GetPath(),
+ FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
IncludeRebaseCommits: true,
RefName: self.refForLog(),
RefForPushedStatus: checkedOutBranchName,
@@ -342,6 +343,7 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
git_commands.GetCommitsOptions{
Limit: self.c.Contexts().SubCommits.GetLimitCommits(),
FilterPath: self.c.Modes().Filtering.GetPath(),
+ FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
IncludeRebaseCommits: false,
RefName: self.c.Contexts().SubCommits.GetRef().FullRefName(),
RefToShowDivergenceFrom: self.c.Contexts().SubCommits.GetRefToShowDivergenceFrom(),
@@ -438,7 +440,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
// which allows us to order them correctly. So if we're filtering we'll just
// manually load all the reflog commits here
var err error
- reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "")
+ reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "", "")
if err != nil {
self.c.Log.Error(err)
}
@@ -597,9 +599,9 @@ func (self *RefreshHelper) refreshReflogCommits() error {
lastReflogCommit = model.ReflogCommits[0]
}
- refresh := func(stateCommits *[]*models.Commit, filterPath string) error {
+ refresh := func(stateCommits *[]*models.Commit, filterPath string, filterAuthor string) error {
commits, onlyObtainedNewReflogCommits, err := self.c.Git().Loaders.ReflogCommitLoader.
- GetReflogCommits(lastReflogCommit, filterPath)
+ GetReflogCommits(lastReflogCommit, filterPath, filterAuthor)
if err != nil {
return self.c.Error(err)
}
@@ -612,12 +614,12 @@ func (self *RefreshHelper) refreshReflogCommits() error {
return nil
}
- if err := refresh(&model.ReflogCommits, ""); err != nil {
+ if err := refresh(&model.ReflogCommits, "", ""); err != nil {
return err
}
if self.c.Modes().Filtering.Active() {
- if err := refresh(&model.FilteredReflogCommits, self.c.Modes().Filtering.GetPath()); err != nil {
+ if err := refresh(&model.FilteredReflogCommits, self.c.Modes().Filtering.GetPath(), self.c.Modes().Filtering.GetAuthor()); err != nil {
return err
}
} else {
diff --git a/pkg/gui/controllers/helpers/sub_commits_helper.go b/pkg/gui/controllers/helpers/sub_commits_helper.go
index b572aa45b..c31d50937 100644
--- a/pkg/gui/controllers/helpers/sub_commits_helper.go
+++ b/pkg/gui/controllers/helpers/sub_commits_helper.go
@@ -39,6 +39,7 @@ func (self *SubCommitsHelper) ViewSubCommits(opts ViewSubCommitsOpts) error {
git_commands.GetCommitsOptions{
Limit: true,
FilterPath: self.c.Modes().Filtering.GetPath(),
+ FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
IncludeRebaseCommits: false,
RefName: opts.Ref.FullRefName(),
RefForPushedStatus: opts.Ref.FullRefName(),
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 66ef453da..4544d5f0b 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -386,7 +386,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context {
Authors: map[string]*models.Author{},
},
Modes: &types.Modes{
- Filtering: filtering.New(startArgs.FilterPath),
+ Filtering: filtering.New(startArgs.FilterPath, ""),
CherryPicking: cherrypicking.New(),
Diffing: diffing.New(),
MarkedBaseCommit: marked_base_commit.New(),
diff --git a/pkg/gui/modes/filtering/filtering.go b/pkg/gui/modes/filtering/filtering.go
index ca8026dc0..368df31f2 100644
--- a/pkg/gui/modes/filtering/filtering.go
+++ b/pkg/gui/modes/filtering/filtering.go
@@ -1,19 +1,21 @@
package filtering
type Filtering struct {
- path string // the filename that gets passed to git log
+ path string // the filename that gets passed to git log
+ author string // the author that gets passed to git log
}
-func New(path string) Filtering {
- return Filtering{path: path}
+func New(path string, author string) Filtering {
+ return Filtering{path: path, author: author}
}
func (m *Filtering) Active() bool {
- return m.path != ""
+ return m.path != "" || m.author != ""
}
func (m *Filtering) Reset() {
m.path = ""
+ m.author = ""
}
func (m *Filtering) SetPath(path string) {
@@ -23,3 +25,11 @@ func (m *Filtering) SetPath(path string) {
func (m *Filtering) GetPath() string {
return m.path
}
+
+func (m *Filtering) SetAuthor(author string) {
+ m.author = author
+}
+
+func (m *Filtering) GetAuthor() string {
+ return m.author
+}
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index 3813a8c30..c05033834 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -536,9 +536,13 @@ type TranslationSet struct {
OpenFilteringMenuTooltip string
FilterBy string
ExitFilterMode string
+ ExitFilterModeAuthor string
FilterPathOption string
+ FilterAuthorOption string
EnterFileName string
+ EnterAuthor string
FilteringMenuTitle string
+ WillCancelExistingFilterTooltip string
MustExitFilterModeTitle string
MustExitFilterModePrompt string
Diff string
@@ -1475,13 +1479,16 @@ func EnglishTranslationSet() TranslationSet {
GotoBottom: "Scroll to bottom",
FilteringBy: "Filtering by",
ResetInParentheses: "(Reset)",
- OpenFilteringMenu: "View filter-by-path options",
- OpenFilteringMenuTooltip: "View options for filtering the commit log by a file path, so that only commits relating to that path are shown.",
+ OpenFilteringMenu: "View filter options",
+ OpenFilteringMenuTooltip: "View options for filtering the commit log, so that only commits matching the filter are shown.",
FilterBy: "Filter by",
- ExitFilterMode: "Stop filtering by path",
+ ExitFilterMode: "Stop filtering",
FilterPathOption: "Enter path to filter by",
+ FilterAuthorOption: "Enter author to filter by",
EnterFileName: "Enter path:",
+ EnterAuthor: "Enter author:",
FilteringMenuTitle: "Filtering",
+ WillCancelExistingFilterTooltip: "Note: this will cancel the existing filter",
MustExitFilterModeTitle: "Command not available",
MustExitFilterModePrompt: "Command not available in filter-by-path mode. Exit filter-by-path mode?",
Diff: "Diff",
diff --git a/pkg/integration/tests/filter_by_author/select_author.go b/pkg/integration/tests/filter_by_author/select_author.go
new file mode 100644
index 000000000..692b4dca9
--- /dev/null
+++ b/pkg/integration/tests/filter_by_author/select_author.go
@@ -0,0 +1,70 @@
+package filter_by_author
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var SelectAuthor = NewIntegrationTest(NewIntegrationTestArgs{
+ Description: "Filter commits using the currently highlighted commit's author when the commit view is active",
+ ExtraCmdArgs: []string{},
+ Skip: false,
+ SetupConfig: func(config *config.AppConfig) {
+ config.AppState.GitLogShowGraph = "never"
+ },
+ SetupRepo: func(shell *Shell) {
+ commonSetup(shell)
+ },
+ Run: func(t *TestDriver, keys config.KeybindingConfig) {
+ t.Views().Commits().
+ Focus().
+ SelectedLineIdx(0).
+ Press(keys.Universal.FilteringMenu)
+
+ t.ExpectPopup().Menu().
+ Title(Equals("Filtering")).
+ Select(Contains("Filter by 'Paul Oberstein <paul.oberstein@email.com>'")).
+ Confirm()
+
+ t.Views().Commits().
+ IsFocused().
+ Lines(
+ Contains("commit 7"),
+ Contains("commit 6"),
+ Contains("commit 5"),
+ Contains("commit 4"),
+ Contains("commit 3"),
+ Contains("commit 2"),
+ Contains("commit 1"),
+ Contains("commit 0"),
+ )
+
+ t.Views().Information().Content(Contains("Filtering by 'Paul Oberstein <paul.oberstein@email.com>'"))
+
+ t.Views().Commits().
+ Press(keys.Universal.FilteringMenu)
+
+ t.ExpectPopup().Menu().
+ Title(Equals("Filtering")).
+ Select(Contains("Stop filtering")).
+ Confirm()
+
+ t.Views().Commits().
+ IsFocused().
+ NavigateToLine(Contains("SK commit 0")).
+ Press(keys.Universal.FilteringMenu)
+
+ t.ExpectPopup().Menu().
+ Title(Equals("Filtering")).
+ Select(Contains("Filter by 'Siegfried Kircheis <siegfried.kircheis@email.com>'")).
+ Confirm()
+
+ t.Views().Commits().
+ IsFocused().
+ Lines(
+ Contains("commit 0"),
+ )
+
+ t.Views().Information().Content(Contains("Filtering by 'Siegfried Kircheis <siegfried.kircheis@email.com>'"))
+ },
+})
diff --git a/pkg/integration/tests/filter_by_author/shared.go b/pkg/integration/tests/filter_by_author/shared.go
new file mode 100644
index 000000000..160bde1c0
--- /dev/null
+++ b/pkg/integration/tests/filter_by_author/shared.go
@@ -0,0 +1,30 @@
+package filter_by_author
+
+import (
+ "fmt"
+ "strings"
+
+ . "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+type AuthorInfo struct {
+ name string
+ numberOfCommits int
+}
+
+func commonSetup(shell *Shell) {
+ authors := []AuthorInfo{{"Yang Wen-li", 3}, {"Siegfried Kircheis", 1}, {"Paul Oberstein", 8}}
+ totalCommits := 0
+ repoStartDaysAgo := 100
+
+ for _, authorInfo := range authors {
+ for i := 0; i < authorInfo.numberOfCommits; i++ {
+ authorEmail := strings.ToLower(strings.ReplaceAll(authorInfo.name, " ", ".")) + "@email.com"
+ commitMessage := fmt.Sprintf("commit %d", i)
+
+ shell.SetAuthor(authorInfo.name, authorEmail)
+ shell.EmptyCommitDaysAgo(commitMessage, repoStartDaysAgo-totalCommits)
+ totalCommits++
+ }
+ }
+}
diff --git a/pkg/integration/tests/filter_by_author/type_author.go b/pkg/integration/tests/filter_by_author/type_author.go
new file mode 100644
index 000000000..cb84d5757
--- /dev/null
+++ b/pkg/integration/tests/filter_by_author/type_author.go
@@ -0,0 +1,66 @@
+package filter_by_author
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/config"
+ . "github.com/jesseduffield/l