Merge pull request #909 from michaeljohnalbers/inverse-filter

Fix #848 Add inverse filtering
mine
Fernand Galiana 2020-10-26 21:04:32 -06:00 committed by GitHub
commit 705174cc6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 6 deletions

View File

@ -208,6 +208,7 @@ K9s uses aliases to navigate most K8s resources.
| View a Kubernetes resource using singular/plural or short-name | `:`po⏎ | accepts singular, plural, short-name or alias ie pod or pods |
| View a Kubernetes resource in a given namespace | `:`alias namespace⏎ | |
| Filter out a resource view given a filter | `/`filter⏎ | Regex2 supported ie `fred|blee` to filter resources named fred or blee |
| Inverse regex filer | `/`! filter⏎ | Keep everything that *doesn't* match. Not implemented for logs. |
| Filter resource view by labels | `/`-l label-selector⏎ | |
| Fuzzy find a resource given a filter | `/`-f filter⏎ | |
| Bails out of view/command/filter mode | `<esc>` | |
@ -220,6 +221,7 @@ K9s uses aliases to navigate most K8s resources.
| To kill a resource (no confirmation dialog!) | `ctrl-k` | |
| Launch pulses view | `:`pulses or pu⏎ | |
| Launch XRay view | `:`xray RESOURCE [NAMESPACE]⏎ | RESOURCE can be one of po, svc, dp, rs, sts, ds, NAMESPACE is optional |
| Launch Popeye view | `:`popeye or pop⏎ | See https://popeyecli.io |
---

View File

@ -380,7 +380,7 @@ func (t *Table) filtered(data render.TableData) render.TableData {
return fuzzyFilter(q[2:], filtered)
}
filtered, err := rxFilter(t.cmdBuff.GetText(), filtered)
filtered, err := rxFilter(q, IsInverseSelector(q), filtered)
if err != nil {
log.Error().Err(errors.New("Invalid filter expression")).Msg("Regexp")
t.cmdBuff.ClearText(true)

View File

@ -37,8 +37,10 @@ const (
)
var (
// LableRx identifies a label query
LableRx = regexp.MustCompile(`\A\-l`)
// LabelRx identifies a label query
LabelRx = regexp.MustCompile(`\A\-l`)
inverseRx = regexp.MustCompile(`\A\!`)
fuzzyRx = regexp.MustCompile(`\A\-f`)
)
@ -66,7 +68,7 @@ func IsLabelSelector(s string) bool {
if s == "" {
return false
}
return LableRx.MatchString(s)
return LabelRx.MatchString(s)
}
// IsFuzzySelector checks if query is fuzzy.
@ -77,6 +79,13 @@ func IsFuzzySelector(s string) bool {
return fuzzyRx.MatchString(s)
}
func IsInverseSelector(s string) bool {
if s == "" {
return false
}
return inverseRx.MatchString(s)
}
// TrimLabelSelector extracts label query.
func TrimLabelSelector(s string) string {
return strings.TrimSpace(s[2:])
@ -137,7 +146,10 @@ func filterToast(data render.TableData) render.TableData {
return toast
}
func rxFilter(q string, data render.TableData) (render.TableData, error) {
func rxFilter(q string, inverse bool, data render.TableData) (render.TableData, error) {
if inverse {
q = q[1:]
}
rx, err := regexp.Compile(`(?i)(` + q + `)`)
if err != nil {
return data, err
@ -150,7 +162,8 @@ func rxFilter(q string, data render.TableData) (render.TableData, error) {
}
for _, re := range data.RowEvents {
fields := strings.Join(re.Row.Fields, " ")
if rx.MatchString(fields) {
if (inverse && ! rx.MatchString(fields)) ||
((! inverse) && rx.MatchString(fields)) {
filtered.RowEvents = append(filtered.RowEvents, re)
}
}

View File

@ -235,6 +235,10 @@ func (s *Sanitizer) filter(root *xray.TreeNode) *xray.TreeNode {
return root.Filter(q, fuzzyFilter)
}
if ui.IsInverseSelector(q) {
return root.Filter(q, rxInverseFilter)
}
return root.Filter(q, rxFilter)
}

View File

@ -466,6 +466,10 @@ func (x *Xray) filter(root *xray.TreeNode) *xray.TreeNode {
return root.Filter(q, fuzzyFilter)
}
if ui.IsInverseSelector(q) {
return root.Filter(q, rxInverseFilter)
}
return root.Filter(q, rxFilter)
}
@ -687,6 +691,19 @@ func rxFilter(q, path string) bool {
return false
}
func rxInverseFilter(q, path string) bool {
q = strings.TrimSpace(q[1:])
rx := regexp.MustCompile(`(?i)` + q)
tokens := strings.Split(path, xray.PathSeparator)
for _, t := range tokens {
if rx.MatchString(t) {
return false
}
}
return true
}
func makeTreeNode(node *xray.TreeNode, expanded bool, showIcons bool, styles *config.Styles) *tview.TreeNode {
n := tview.NewTreeNode("No data...")
if node != nil {