/
text.go
122 lines (100 loc) 路 2.51 KB
/
text.go
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
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of K9s
package model
import (
"strings"
"github.com/derailed/k9s/internal"
"github.com/sahilm/fuzzy"
)
// Filterable represents an entity that can be filtered.
type Filterable interface {
Filter(string)
ClearFilter()
}
// Textable represents a text resource.
type Textable interface {
Peek() []string
SetText(string)
AddListener(TextListener)
RemoveListener(TextListener)
}
// TextListener represents a text model listener.
type TextListener interface {
// TextChanged notifies the model changed.
TextChanged([]string)
// TextFiltered notifies when the filter changed.
TextFiltered([]string, fuzzy.Matches)
}
// Text represents a text model.
type Text struct {
lines []string
listeners []TextListener
query string
}
// NewText returns a new model.
func NewText() *Text {
return &Text{}
}
// Peek returns the current model state.
func (t *Text) Peek() []string {
return t.lines
}
// ClearFilter clear out filter.
func (t *Text) ClearFilter() {
t.query = ""
t.filterChanged(t.lines)
}
// Filter filters out the text.
func (t *Text) Filter(q string) {
t.query = q
t.filterChanged(t.lines)
}
// SetText sets the current model content.
func (t *Text) SetText(buff string) {
t.lines = strings.Split(buff, "\n")
t.fireTextChanged(t.lines)
}
// AddListener adds a new model listener.
func (t *Text) AddListener(listener TextListener) {
t.listeners = append(t.listeners, listener)
}
// RemoveListener delete a listener from the list.
func (t *Text) RemoveListener(listener TextListener) {
victim := -1
for i, lis := range t.listeners {
if lis == listener {
victim = i
break
}
}
if victim >= 0 {
t.listeners = append(t.listeners[:victim], t.listeners[victim+1:]...)
}
}
func (t *Text) filterChanged(lines []string) {
t.fireTextFiltered(lines, t.filter(t.query, lines))
}
func (t *Text) fireTextChanged(lines []string) {
for _, lis := range t.listeners {
lis.TextChanged(lines)
}
}
func (t *Text) fireTextFiltered(lines []string, matches fuzzy.Matches) {
for _, lis := range t.listeners {
lis.TextFiltered(lines, matches)
}
}
// ----------------------------------------------------------------------------
// Helpers...
func (t *Text) filter(q string, lines []string) fuzzy.Matches {
if q == "" {
return nil
}
if f, ok := internal.IsFuzzySelector(q); ok {
return t.fuzzyFilter(strings.TrimSpace(f), lines)
}
return rxFilter(q, lines)
}
func (*Text) fuzzyFilter(q string, lines []string) fuzzy.Matches {
return fuzzy.Find(q, lines)
}