commit
705174cc6f
|
|
@ -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 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⏎ | |
|
| 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 |
|
| 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⏎ | |
|
| Filter resource view by labels | `/`-l label-selector⏎ | |
|
||||||
| Fuzzy find a resource given a filter | `/`-f filter⏎ | |
|
| Fuzzy find a resource given a filter | `/`-f filter⏎ | |
|
||||||
| Bails out of view/command/filter mode | `<esc>` | |
|
| 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` | |
|
| To kill a resource (no confirmation dialog!) | `ctrl-k` | |
|
||||||
| Launch pulses view | `:`pulses or pu⏎ | |
|
| 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 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 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,7 @@ func (t *Table) filtered(data render.TableData) render.TableData {
|
||||||
return fuzzyFilter(q[2:], filtered)
|
return fuzzyFilter(q[2:], filtered)
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered, err := rxFilter(t.cmdBuff.GetText(), filtered)
|
filtered, err := rxFilter(q, IsInverseSelector(q), filtered)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(errors.New("Invalid filter expression")).Msg("Regexp")
|
log.Error().Err(errors.New("Invalid filter expression")).Msg("Regexp")
|
||||||
t.cmdBuff.ClearText(true)
|
t.cmdBuff.ClearText(true)
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// LableRx identifies a label query
|
// LabelRx identifies a label query
|
||||||
LableRx = regexp.MustCompile(`\A\-l`)
|
LabelRx = regexp.MustCompile(`\A\-l`)
|
||||||
|
|
||||||
|
inverseRx = regexp.MustCompile(`\A\!`)
|
||||||
|
|
||||||
fuzzyRx = regexp.MustCompile(`\A\-f`)
|
fuzzyRx = regexp.MustCompile(`\A\-f`)
|
||||||
)
|
)
|
||||||
|
|
@ -66,7 +68,7 @@ func IsLabelSelector(s string) bool {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return LableRx.MatchString(s)
|
return LabelRx.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFuzzySelector checks if query is fuzzy.
|
// IsFuzzySelector checks if query is fuzzy.
|
||||||
|
|
@ -77,6 +79,13 @@ func IsFuzzySelector(s string) bool {
|
||||||
return fuzzyRx.MatchString(s)
|
return fuzzyRx.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsInverseSelector(s string) bool {
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return inverseRx.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
// TrimLabelSelector extracts label query.
|
// TrimLabelSelector extracts label query.
|
||||||
func TrimLabelSelector(s string) string {
|
func TrimLabelSelector(s string) string {
|
||||||
return strings.TrimSpace(s[2:])
|
return strings.TrimSpace(s[2:])
|
||||||
|
|
@ -137,7 +146,10 @@ func filterToast(data render.TableData) render.TableData {
|
||||||
return toast
|
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 + `)`)
|
rx, err := regexp.Compile(`(?i)(` + q + `)`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, err
|
return data, err
|
||||||
|
|
@ -150,7 +162,8 @@ func rxFilter(q string, data render.TableData) (render.TableData, error) {
|
||||||
}
|
}
|
||||||
for _, re := range data.RowEvents {
|
for _, re := range data.RowEvents {
|
||||||
fields := strings.Join(re.Row.Fields, " ")
|
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)
|
filtered.RowEvents = append(filtered.RowEvents, re)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,10 @@ func (s *Sanitizer) filter(root *xray.TreeNode) *xray.TreeNode {
|
||||||
return root.Filter(q, fuzzyFilter)
|
return root.Filter(q, fuzzyFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui.IsInverseSelector(q) {
|
||||||
|
return root.Filter(q, rxInverseFilter)
|
||||||
|
}
|
||||||
|
|
||||||
return root.Filter(q, rxFilter)
|
return root.Filter(q, rxFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,10 @@ func (x *Xray) filter(root *xray.TreeNode) *xray.TreeNode {
|
||||||
return root.Filter(q, fuzzyFilter)
|
return root.Filter(q, fuzzyFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui.IsInverseSelector(q) {
|
||||||
|
return root.Filter(q, rxInverseFilter)
|
||||||
|
}
|
||||||
|
|
||||||
return root.Filter(q, rxFilter)
|
return root.Filter(q, rxFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -687,6 +691,19 @@ func rxFilter(q, path string) bool {
|
||||||
return false
|
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 {
|
func makeTreeNode(node *xray.TreeNode, expanded bool, showIcons bool, styles *config.Styles) *tview.TreeNode {
|
||||||
n := tview.NewTreeNode("No data...")
|
n := tview.NewTreeNode("No data...")
|
||||||
if node != nil {
|
if node != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue