Add a -n flag to :search to select the immediate next search result from
the current position in the messsage list. If not set, the (current)
default behavior for :search is to jump to the very first search result.
In my opinion, it makes more sense to have this -n behavior be the
default and add a separate flag for the current default behavior. If
we're opposed to changing the default then I definitely think this flag
is a good addition.
The following example will select the immediate next unread message:
:search -nu
Fixes: https://todo.sr.ht/~rjarry/aerc/168
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Thanks for remembering this -- and thanks the patch! :)
Please, note that it doesn't apply to the latest master, so I had to
roll back 73dc39c6 to test it. Once applied, it works as advertised,
I haven't faced any problems.
However, wouldn't it be logical also to add `-p` to go to the previous
search result?
And maybe also options to go to the first / last search results? What do
you think?
Otherwise, as said, everything looks nice, and thanks again :)
---
commands/account/search.go | 3 +-doc/aerc-search.1.scd | 3 ++lib/msgstore.go | 84 +++++++++++++++++---------------------
3 files changed, 42 insertions(+), 48 deletions(-)
diff --git a/commands/account/search.go b/commands/account/search.go
index 5c2eaec7..dee52f06 100644
--- a/commands/account/search.go+++ b/commands/account/search.go
@@ -24,6 +24,7 @@ type SearchFilter struct {
Body bool `opt:"-b"`
All bool `opt:"-a"`
UseExtension bool `opt:"-e"`
+ NextResult bool `opt:"-n"` Headers textproto.MIMEHeader `opt:"-H" action:"ParseHeader" metavar:"<header>:<value>"`
WithFlags models.Flags `opt:"-x" action:"ParseFlag" complete:"CompleteFlag"`
WithoutFlags models.Flags `opt:"-X" action:"ParseNotFlag" complete:"CompleteFlag"`
@@ -194,7 +195,7 @@ func (s SearchFilter) Execute(args []string) error {
cb := func(uids []uint32) {
acct.SetStatus(state.Search(strings.Join(args, " ")))
log.Tracef("Search results: %v", uids)
- store.ApplySearch(uids)+ store.ApplySearch(uids, s.NextResult) // TODO: Remove when stores have multiple OnUpdate handlers
ui.Invalidate()
}
diff --git a/doc/aerc-search.1.scd b/doc/aerc-search.1.scd
index 6ec4e53d..b2d83772 100644
--- a/doc/aerc-search.1.scd+++ b/doc/aerc-search.1.scd
@@ -53,6 +53,9 @@ This syntax is common to all backends.
(such as the X-GM-EXT if available). Search terms are expected
in _<terms>_; other flags will be ignored.
+ *-n*: Select the immediate next search result from the current position+ in the messsage list (only for *:search*).+
This description is a bit confusing to me. Perhaps something like "Start
the search at the current position in the message list" would be more
clear. It might be also helpful to add a note above the flags specifying
that searches start at the beginning of the message list by default.
*-f* _<from>_: Search for messages from _<from>_
*-t* _<to>_: Search for messages to _<to>_
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 5c8b3ef1..6212bb31 100644
--- a/lib/msgstore.go+++ b/lib/msgstore.go
@@ -44,9 +44,8 @@ type MessageStore struct {
marker marker.Marker
// Search/filter results
- results []uint32- resultIndex int- filter *types.SearchCriteria+ results map[uint32]struct{}+ filter *types.SearchCriteria sortCriteria []*types.SortCriterion
sortDefault []*types.SortCriterion
@@ -125,6 +124,7 @@ func NewMessageStore(worker *types.Worker, name string,
triggerFlagChanged: triggerFlagChanged,
onSelect: onSelect,
+ results: make(map[uint32]struct{}), }
}
@@ -356,6 +356,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
toDelete[uid] = nil
delete(store.Messages, uid)
delete(store.Deleted, uid)
+ delete(store.results, uid) }
uids := make([]uint32, 0, len(store.uids)-len(msg.Uids))
for _, uid := range store.uids {
@@ -369,14 +370,6 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
store.Select(MagicUid)
}
- var newResults []uint32- for _, res := range store.results {- if _, deleted := toDelete[res]; !deleted {- newResults = append(newResults, res)- }- }- store.results = newResults- for uid := range toDelete {
thread, err := store.Thread(uid)
if err != nil {
@@ -833,7 +826,6 @@ func (store *MessageStore) NextPrev(delta int) {
if store.marker != nil {
store.marker.UpdateVisualMark()
}
- store.updateResults()}
func (store *MessageStore) Next() {
@@ -866,20 +858,31 @@ func (store *MessageStore) Search(terms *types.SearchCriteria, cb func([]uint32)
})
}
-func (store *MessageStore) ApplySearch(results []uint32) {- store.results = results- store.resultIndex = -1- store.NextResult()+func (store *MessageStore) ApplySearch(results []uint32, nextResult bool) {+ if len(results) == 0 {+ return+ }+ store.results = make(map[uint32]struct{}, len(results))+ for _, u := range results {+ store.results[u] = struct{}{}+ }+ if nextResult {+ store.NextResult()+ } else if len(results) > 0 {+ it := store.iterFactory.NewIterator(results)+ idx := it.StartIndex()+ if store.ui().SelectLast {+ idx = it.EndIndex()+ }+ store.Select(results[idx])+ store.update(false)+ }}
// IsResult returns true if uid is a search result
func (store *MessageStore) IsResult(uid uint32) bool {
- for _, hit := range store.results {- if hit == uid {- return true- }- }- return false+ _, ok := store.results[uid]+ return ok}
func (store *MessageStore) SetFilter(terms *types.SearchCriteria) {
@@ -895,36 +898,23 @@ func (store *MessageStore) ApplyClear() {
store.Sort(store.sortDefault, nil)
}
-func (store *MessageStore) updateResults() {- if len(store.results) == 0 || store.resultIndex < 0 {- return- }- uid := store.SelectedUid()- for i, u := range store.results {- if uid == u {- store.resultIndex = i- break- }- }-}-func (store *MessageStore) nextPrevResult(delta int) {
if len(store.results) == 0 {
return
}
- iter := store.iterFactory.NewIterator(store.results)- if store.resultIndex < 0 {- store.resultIndex = iter.StartIndex()- } else {- store.resultIndex = iterator.MoveIndex(- store.resultIndex,- delta,- iter,- iterator.WrapBounds,- )+ uids := store.Uids()+ iter := store.iterFactory.NewIterator(uids)+ nextIndex := store.SelectedIndex()+ for i := 0; i < len(uids); i++ {+ nextIndex = iterator.MoveIndex(nextIndex, delta, iter,+ iterator.WrapBounds)+ u := uids[nextIndex]+ if _, ok := store.results[u]; ok {+ store.Select(u)+ store.update(false)+ return+ } }
- store.Select(store.results[store.resultIndex])- store.update(false)}
func (store *MessageStore) NextResult() {
--
2.45.2