mark: allow multiple visual selections
When entering visual selection mode, the current selection is deleted. This patch extends the visual mode behavior to select multiple blocks of messages. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
16dbb94221
commit
b12dd9f926
4 changed files with 23 additions and 7 deletions
|
@ -32,19 +32,23 @@ func (Mark) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
marker := store.Marker()
|
marker := store.Marker()
|
||||||
opts, _, err := getopt.Getopts(args, "atv")
|
opts, _, err := getopt.Getopts(args, "atvV")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var all bool
|
var all bool
|
||||||
var toggle bool
|
var toggle bool
|
||||||
var visual bool
|
var visual bool
|
||||||
|
var clearVisual bool
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch opt.Option {
|
switch opt.Option {
|
||||||
case 'a':
|
case 'a':
|
||||||
all = true
|
all = true
|
||||||
case 'v':
|
case 'v':
|
||||||
visual = true
|
visual = true
|
||||||
|
clearVisual = true
|
||||||
|
case 'V':
|
||||||
|
visual = true
|
||||||
case 't':
|
case 't':
|
||||||
toggle = true
|
toggle = true
|
||||||
}
|
}
|
||||||
|
@ -70,7 +74,7 @@ func (Mark) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case visual:
|
case visual:
|
||||||
marker.ToggleVisualMark()
|
marker.ToggleVisualMark(clearVisual)
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
modFunc(selected.Uid)
|
modFunc(selected.Uid)
|
||||||
|
|
|
@ -412,6 +412,8 @@ message list, the message in the message viewer, etc).
|
||||||
|
|
||||||
*-v*: Enter / leave visual mark mode
|
*-v*: Enter / leave visual mark mode
|
||||||
|
|
||||||
|
*-V*: Same as -v but does not clear existing selection
|
||||||
|
|
||||||
*unmark* [-at]
|
*unmark* [-at]
|
||||||
Unmarks messages. The flags below can be combined as needed.
|
Unmarks messages. The flags below can be combined as needed.
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ type Marker interface {
|
||||||
Remark()
|
Remark()
|
||||||
Marked() []uint32
|
Marked() []uint32
|
||||||
IsMarked(uint32) bool
|
IsMarked(uint32) bool
|
||||||
ToggleVisualMark()
|
ToggleVisualMark(bool)
|
||||||
UpdateVisualMark()
|
UpdateVisualMark()
|
||||||
ClearVisualMark()
|
ClearVisualMark()
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ type controller struct {
|
||||||
lastMarked map[uint32]struct{}
|
lastMarked map[uint32]struct{}
|
||||||
visualStartUID uint32
|
visualStartUID uint32
|
||||||
visualMarkMode bool
|
visualMarkMode bool
|
||||||
|
visualBase map[uint32]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Marker
|
// New returns a new Marker
|
||||||
|
@ -114,15 +115,21 @@ func (mc *controller) Marked() []uint32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToggleVisualMark enters or leaves the visual marking mode
|
// ToggleVisualMark enters or leaves the visual marking mode
|
||||||
func (mc *controller) ToggleVisualMark() {
|
func (mc *controller) ToggleVisualMark(clear bool) {
|
||||||
mc.visualMarkMode = !mc.visualMarkMode
|
mc.visualMarkMode = !mc.visualMarkMode
|
||||||
if mc.visualMarkMode {
|
if mc.visualMarkMode {
|
||||||
// just entered visual mode, reset whatever marking was already done
|
// just entered visual mode, reset whatever marking was already done
|
||||||
mc.resetMark()
|
if clear {
|
||||||
|
mc.resetMark()
|
||||||
|
}
|
||||||
uids := mc.uidProvider.Uids()
|
uids := mc.uidProvider.Uids()
|
||||||
if idx := mc.uidProvider.SelectedIndex(); idx >= 0 && idx < len(uids) {
|
if idx := mc.uidProvider.SelectedIndex(); idx >= 0 && idx < len(uids) {
|
||||||
mc.visualStartUID = uids[idx]
|
mc.visualStartUID = uids[idx]
|
||||||
mc.marked[mc.visualStartUID] = struct{}{}
|
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 {
|
} else {
|
||||||
visUids = uids[selectedIdx : startIdx+1]
|
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 {
|
for _, uid := range visUids {
|
||||||
mc.marked[uid] = struct{}{}
|
mc.marked[uid] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ func TestMarker_VisualMode(t *testing.T) {
|
||||||
m, up := createMarker()
|
m, up := createMarker()
|
||||||
|
|
||||||
// activate visual mode
|
// activate visual mode
|
||||||
m.ToggleVisualMark()
|
m.ToggleVisualMark(false)
|
||||||
|
|
||||||
// marking should now fail silently because we're in visual mode
|
// marking should now fail silently because we're in visual mode
|
||||||
m.Mark(1)
|
m.Mark(1)
|
||||||
|
|
Loading…
Reference in a new issue