65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package filter
|
|
|
|
import "slices"
|
|
|
|
// PinSet is the pin buffer: record indices the user marked. It is owned by the
|
|
// app and outlives every filter change, which is the point — pins are
|
|
// assembled across successive filters. Not registered: it has no meaningful
|
|
// construction from a string argument.
|
|
type PinSet struct{ m map[int32]struct{} }
|
|
|
|
// NewPinSet returns an empty pin buffer.
|
|
func NewPinSet() *PinSet { return &PinSet{m: make(map[int32]struct{})} }
|
|
|
|
// Has reports whether record i is pinned.
|
|
func (p *PinSet) Has(i int32) bool { _, ok := p.m[i]; return ok }
|
|
|
|
// Toggle flips record i, returning its new state.
|
|
func (p *PinSet) Toggle(i int32) bool {
|
|
if _, ok := p.m[i]; ok {
|
|
delete(p.m, i)
|
|
return false
|
|
}
|
|
p.m[i] = struct{}{}
|
|
return true
|
|
}
|
|
|
|
// Clear empties the buffer.
|
|
func (p *PinSet) Clear() { clear(p.m) }
|
|
|
|
// Len returns the pin count.
|
|
func (p *PinSet) Len() int { return len(p.m) }
|
|
|
|
// Sorted returns the pinned record indices in file order.
|
|
func (p *PinSet) Sorted() []int32 {
|
|
out := make([]int32, 0, len(p.m))
|
|
for i := range p.m {
|
|
out = append(out, i)
|
|
}
|
|
slices.Sort(out)
|
|
return out
|
|
}
|
|
|
|
// Pinned restricts the view to the pin buffer.
|
|
type Pinned struct {
|
|
Set *PinSet
|
|
On bool
|
|
}
|
|
|
|
// NewPinned wraps a pin buffer as a filter.
|
|
func NewPinned(s *PinSet) *Pinned { return &Pinned{Set: s} }
|
|
|
|
func (f *Pinned) Kind() string { return "pin" }
|
|
func (f *Pinned) Needs() Need { return 0 }
|
|
|
|
func (f *Pinned) Match(c *Ctx) bool {
|
|
return !f.On || f.Set.Has(int32(c.I))
|
|
}
|
|
|
|
func (f *Pinned) Label() string {
|
|
if !f.On {
|
|
return ""
|
|
}
|
|
return "pinned-only"
|
|
}
|