diff --git a/commands/msg/mark.go b/commands/msg/mark.go index 13d6c92..939d456 100644 --- a/commands/msg/mark.go +++ b/commands/msg/mark.go @@ -32,19 +32,23 @@ func (Mark) Execute(aerc *widgets.Aerc, args []string) error { return err } marker := store.Marker() - opts, _, err := getopt.Getopts(args, "atv") + opts, _, err := getopt.Getopts(args, "atvV") if err != nil { return err } var all bool var toggle bool var visual bool + var clearVisual bool for _, opt := range opts { switch opt.Option { case 'a': all = true case 'v': visual = true + clearVisual = true + case 'V': + visual = true case 't': toggle = true } @@ -70,7 +74,7 @@ func (Mark) Execute(aerc *widgets.Aerc, args []string) error { } return nil case visual: - marker.ToggleVisualMark() + marker.ToggleVisualMark(clearVisual) return nil default: modFunc(selected.Uid) diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index 17e25c2..b5edc32 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -412,6 +412,8 @@ message list, the message in the message viewer, etc). *-v*: Enter / leave visual mark mode + *-V*: Same as -v but does not clear existing selection + *unmark* [-at] Unmarks messages. The flags below can be combined as needed. diff --git a/lib/marker/marker.go b/lib/marker/marker.go index 46400f1..21c151f 100644 --- a/lib/marker/marker.go +++ b/lib/marker/marker.go @@ -8,7 +8,7 @@ type Marker interface { Remark() Marked() []uint32 IsMarked(uint32) bool - ToggleVisualMark() + ToggleVisualMark(bool) UpdateVisualMark() ClearVisualMark() } @@ -25,6 +25,7 @@ type controller struct { lastMarked map[uint32]struct{} visualStartUID uint32 visualMarkMode bool + visualBase map[uint32]struct{} } // New returns a new Marker @@ -114,15 +115,21 @@ func (mc *controller) Marked() []uint32 { } // ToggleVisualMark enters or leaves the visual marking mode -func (mc *controller) ToggleVisualMark() { +func (mc *controller) ToggleVisualMark(clear bool) { mc.visualMarkMode = !mc.visualMarkMode if mc.visualMarkMode { // just entered visual mode, reset whatever marking was already done - mc.resetMark() + if clear { + mc.resetMark() + } uids := mc.uidProvider.Uids() if idx := mc.uidProvider.SelectedIndex(); idx >= 0 && idx < len(uids) { mc.visualStartUID = uids[idx] mc.marked[mc.visualStartUID] = struct{}{} + mc.visualBase = make(map[uint32]struct{}) + for key, value := range mc.marked { + mc.visualBase[key] = value + } } } } @@ -160,7 +167,10 @@ func (mc *controller) UpdateVisualMark() { } else { visUids = uids[selectedIdx : startIdx+1] } - mc.resetMark() + mc.marked = make(map[uint32]struct{}) + for uid := range mc.visualBase { + mc.marked[uid] = struct{}{} + } for _, uid := range visUids { mc.marked[uid] = struct{}{} } diff --git a/lib/marker/marker_test.go b/lib/marker/marker_test.go index 1611623..df9eb2a 100644 --- a/lib/marker/marker_test.go +++ b/lib/marker/marker_test.go @@ -90,7 +90,7 @@ func TestMarker_VisualMode(t *testing.T) { m, up := createMarker() // activate visual mode - m.ToggleVisualMark() + m.ToggleVisualMark(false) // marking should now fail silently because we're in visual mode m.Mark(1)