1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
package msg
import (
"fmt"
"strings"
"time"
"git.sr.ht/~rjarry/aerc/app"
"git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/types"
)
type FlagMsg struct {
Toggle bool `opt:"-t" desc:"Toggle between set and unset."`
Answered bool `opt:"-a" aliases:"flag,unflag" desc:"Set/unset the answered flag."`
Forwarded bool `opt:"-f" aliases:"flag,unflag" desc:"Set/unset the forwarded flag."`
Flag models.Flags `opt:"-x" aliases:"flag,unflag" action:"ParseFlag" complete:"CompleteFlag" desc:"Flag name."`
FlagName string
}
func init() {
commands.Register(FlagMsg{})
}
func (FlagMsg) Description() string {
return "Set or unset a flag on the marked or selected messages."
}
func (FlagMsg) Context() commands.CommandContext {
return commands.MESSAGE_LIST | commands.MESSAGE_VIEWER
}
func (FlagMsg) Aliases() []string {
return []string{"flag", "unflag", "read", "unread"}
}
func (f *FlagMsg) ParseFlag(arg string) error {
switch strings.ToLower(arg) {
case "seen":
f.Flag = models.SeenFlag
f.FlagName = "seen"
case "answered":
f.Flag = models.AnsweredFlag
f.FlagName = "answered"
case "forwarded":
f.Flag = models.ForwardedFlag
f.FlagName = "forwarded"
case "flagged":
f.Flag = models.FlaggedFlag
f.FlagName = "flagged"
case "draft":
f.Flag = models.DraftFlag
f.FlagName = "draft"
default:
return fmt.Errorf("Unknown flag %q", arg)
}
return nil
}
var validFlags = []string{"seen", "answered", "forwarded", "flagged", "draft"}
func (*FlagMsg) CompleteFlag(arg string) []string {
return commands.FilterList(validFlags, arg, nil)
}
// If this was called as 'flag' or 'unflag', without the toggle (-t)
// option, then it will flag the corresponding messages with the given
// flag. If the toggle option was given, it will individually toggle
// the given flag for the corresponding messages.
//
// If this was called as 'read' or 'unread', it has the same effect as
// 'flag' or 'unflag', respectively, but the 'Seen' flag is affected.
func (f FlagMsg) Execute(args []string) error {
// User-readable name for the action being performed
var actionName string
switch args[0] {
case "read", "unread":
f.Flag = models.SeenFlag
f.FlagName = "seen"
case "flag", "unflag":
if f.Answered {
f.Flag = models.AnsweredFlag
f.FlagName = "answered"
}
if f.Forwarded {
f.Flag = models.ForwardedFlag
f.FlagName = "forwarded"
}
if f.Flag == 0 {
f.Flag = models.FlaggedFlag
f.FlagName = "flagged"
}
}
h := newHelper()
store, err := h.store()
if err != nil {
return err
}
// UIDs of messages to enable or disable the flag for.
var toEnable []models.UID
var toDisable []models.UID
if f.Toggle {
// If toggling, split messages into those that need to
// be enabled / disabled.
msgs, err := h.messages()
if err != nil {
return err
}
for _, m := range msgs {
if m.Flags.Has(f.Flag) {
toDisable = append(toDisable, m.Uid)
} else {
toEnable = append(toEnable, m.Uid)
}
}
actionName = "Toggling"
} else {
msgUids, err := h.markedOrSelectedUids()
if err != nil {
return err
}
switch args[0] {
case "read", "flag":
toEnable = msgUids
actionName = "Setting"
default:
toDisable = msgUids
actionName = "Unsetting"
}
}
status := fmt.Sprintf("%s flag %q successful", actionName, f.FlagName)
if len(toEnable) != 0 {
store.Flag(toEnable, f.Flag, true, func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
app.PushStatus(status, 10*time.Second)
store.Marker().ClearVisualMark()
case *types.Error:
app.PushError(msg.Error.Error())
}
})
}
if len(toDisable) != 0 {
store.Flag(toDisable, f.Flag, false, func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
app.PushStatus(status, 10*time.Second)
store.Marker().ClearVisualMark()
case *types.Error:
app.PushError(msg.Error.Error())
}
})
}
return nil
}
|