update prompt. Fix #649
parent
31020fcbad
commit
a6ec74ff6c
|
|
@ -1,5 +1,5 @@
|
||||||
# Build...
|
# Build...
|
||||||
FROM golang:1.13.6-alpine3.11 AS build
|
FROM golang:1.14.1 AS build
|
||||||
|
|
||||||
WORKDIR /k9s
|
WORKDIR /k9s
|
||||||
COPY go.mod go.sum main.go Makefile ./
|
COPY go.mod go.sum main.go Makefile ./
|
||||||
|
|
|
||||||
6
go.mod
6
go.mod
|
|
@ -2,10 +2,12 @@ module github.com/derailed/k9s
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
|
replace helm.sh/helm/v3 => /Users/fernand/go_wk/derailed/src/github.com/derailed/tmp/helm
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/atotto/clipboard v0.1.2
|
github.com/atotto/clipboard v0.1.2
|
||||||
github.com/derailed/popeye v0.8.0
|
github.com/derailed/popeye v0.8.1
|
||||||
github.com/derailed/tview v0.3.9
|
github.com/derailed/tview v0.3.10
|
||||||
github.com/drone/envsubst v1.0.2 // indirect
|
github.com/drone/envsubst v1.0.2 // indirect
|
||||||
github.com/fatih/color v1.9.0
|
github.com/fatih/color v1.9.0
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
|
|
|
||||||
10
go.sum
10
go.sum
|
|
@ -126,8 +126,12 @@ github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC
|
||||||
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
||||||
github.com/derailed/popeye v0.8.0 h1:D+5fHiMmuXqaF5J2bJTI+YLrD77ag5Wb1dkAuR4bPGI=
|
github.com/derailed/popeye v0.8.0 h1:D+5fHiMmuXqaF5J2bJTI+YLrD77ag5Wb1dkAuR4bPGI=
|
||||||
github.com/derailed/popeye v0.8.0/go.mod h1:OBHcJDa50VpE9QNyOU243bNOtHb29MyLlVHJolwlwas=
|
github.com/derailed/popeye v0.8.0/go.mod h1:OBHcJDa50VpE9QNyOU243bNOtHb29MyLlVHJolwlwas=
|
||||||
|
github.com/derailed/popeye v0.8.1 h1:N69XH0NZTBkrNj8qvUzy6Z6bP7+jx0AwollETqvc3dc=
|
||||||
|
github.com/derailed/popeye v0.8.1/go.mod h1:OBHcJDa50VpE9QNyOU243bNOtHb29MyLlVHJolwlwas=
|
||||||
github.com/derailed/tview v0.3.9 h1:6iUtOmzN6gdk6yx1KNSwhMgrsLYjgldduulKPqHnqwk=
|
github.com/derailed/tview v0.3.9 h1:6iUtOmzN6gdk6yx1KNSwhMgrsLYjgldduulKPqHnqwk=
|
||||||
github.com/derailed/tview v0.3.9/go.mod h1:GJ3k/TIzEE+sj1L09/usk6HrkjsdadSsb03eHgPbcII=
|
github.com/derailed/tview v0.3.9/go.mod h1:GJ3k/TIzEE+sj1L09/usk6HrkjsdadSsb03eHgPbcII=
|
||||||
|
github.com/derailed/tview v0.3.10 h1:n+iQwYh9Ff9STdR5hBhp+rTJRlu59q2xP2pHvwQbYPw=
|
||||||
|
github.com/derailed/tview v0.3.10/go.mod h1:GJ3k/TIzEE+sj1L09/usk6HrkjsdadSsb03eHgPbcII=
|
||||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
|
@ -371,6 +375,7 @@ github.com/mattn/go-runewidth v0.0.5/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
|
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
|
|
@ -691,6 +696,7 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
|
|
@ -726,10 +732,13 @@ k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
|
||||||
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
|
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
|
||||||
k8s.io/apiextensions-apiserver v0.17.2 h1:cP579D2hSZNuO/rZj9XFRzwJNYb41DbNANJb6Kolpss=
|
k8s.io/apiextensions-apiserver v0.17.2 h1:cP579D2hSZNuO/rZj9XFRzwJNYb41DbNANJb6Kolpss=
|
||||||
k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs=
|
k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs=
|
||||||
|
k8s.io/apiextensions-apiserver v0.18.0 h1:HN4/P8vpGZFvB5SOMuPPH2Wt9Y/ryX+KRvIyAkchu1Q=
|
||||||
|
k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
|
||||||
k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||||
k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
|
k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
|
||||||
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
||||||
k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo=
|
k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo=
|
||||||
|
k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
|
||||||
k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI=
|
k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI=
|
||||||
k8s.io/cli-runtime v0.18.0 h1:jG8XpSqQ5TrV0N+EZ3PFz6+gqlCk71dkggWCCq9Mq34=
|
k8s.io/cli-runtime v0.18.0 h1:jG8XpSqQ5TrV0N+EZ3PFz6+gqlCk71dkggWCCq9Mq34=
|
||||||
k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ=
|
k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ=
|
||||||
|
|
@ -767,6 +776,7 @@ modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03
|
||||||
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||||
rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
|
rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
|
||||||
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
|
|
|
||||||
|
|
@ -1,124 +1,124 @@
|
||||||
package dao
|
package dao
|
||||||
|
|
||||||
// BOZO!! v1.18.0
|
// BOZO!! v1.18.0
|
||||||
// import (
|
import (
|
||||||
// "context"
|
"context"
|
||||||
// "fmt"
|
"fmt"
|
||||||
// "os"
|
"os"
|
||||||
|
|
||||||
// "github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
// "github.com/derailed/k9s/internal/render"
|
"github.com/derailed/k9s/internal/render"
|
||||||
// "github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
// "helm.sh/helm/v3/pkg/action"
|
"helm.sh/helm/v3/pkg/action"
|
||||||
// "k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
// )
|
)
|
||||||
|
|
||||||
// var (
|
var (
|
||||||
// _ Accessor = (*Chart)(nil)
|
_ Accessor = (*Chart)(nil)
|
||||||
// _ Nuker = (*Chart)(nil)
|
_ Nuker = (*Chart)(nil)
|
||||||
// _ Describer = (*Chart)(nil)
|
_ Describer = (*Chart)(nil)
|
||||||
// )
|
)
|
||||||
|
|
||||||
// // Chart represents a helm chart.
|
// Chart represents a helm chart.
|
||||||
// type Chart struct {
|
type Chart struct {
|
||||||
// NonResource
|
NonResource
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // List returns a collection of resources.
|
// List returns a collection of resources.
|
||||||
// func (c *Chart) List(ctx context.Context, ns string) ([]runtime.Object, error) {
|
func (c *Chart) List(ctx context.Context, ns string) ([]runtime.Object, error) {
|
||||||
// cfg, err := c.EnsureHelmConfig(ns)
|
cfg, err := c.EnsureHelmConfig(ns)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// rr, err := action.NewList(cfg).Run()
|
rr, err := action.NewList(cfg).Run()
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// oo := make([]runtime.Object, 0, len(rr))
|
oo := make([]runtime.Object, 0, len(rr))
|
||||||
// for _, r := range rr {
|
for _, r := range rr {
|
||||||
// oo = append(oo, render.ChartRes{Release: r})
|
oo = append(oo, render.ChartRes{Release: r})
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return oo, nil
|
return oo, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Get returns a resource.
|
// Get returns a resource.
|
||||||
// func (c *Chart) Get(_ context.Context, path string) (runtime.Object, error) {
|
func (c *Chart) Get(_ context.Context, path string) (runtime.Object, error) {
|
||||||
// ns, n := client.Namespaced(path)
|
ns, n := client.Namespaced(path)
|
||||||
// cfg, err := c.EnsureHelmConfig(ns)
|
cfg, err := c.EnsureHelmConfig(ns)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
// resp, err := action.NewGet(cfg).Run(n)
|
resp, err := action.NewGet(cfg).Run(n)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return render.ChartRes{Release: resp}, nil
|
return render.ChartRes{Release: resp}, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Describe returns the chart notes.
|
// Describe returns the chart notes.
|
||||||
// func (c *Chart) Describe(path string) (string, error) {
|
func (c *Chart) Describe(path string) (string, error) {
|
||||||
// ns, n := client.Namespaced(path)
|
ns, n := client.Namespaced(path)
|
||||||
// cfg, err := c.EnsureHelmConfig(ns)
|
cfg, err := c.EnsureHelmConfig(ns)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
// resp, err := action.NewGet(cfg).Run(n)
|
resp, err := action.NewGet(cfg).Run(n)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return resp.Info.Notes, nil
|
return resp.Info.Notes, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // ToYAML returns the chart manifest.
|
// ToYAML returns the chart manifest.
|
||||||
// func (c *Chart) ToYAML(path string) (string, error) {
|
func (c *Chart) ToYAML(path string) (string, error) {
|
||||||
// ns, n := client.Namespaced(path)
|
ns, n := client.Namespaced(path)
|
||||||
// cfg, err := c.EnsureHelmConfig(ns)
|
cfg, err := c.EnsureHelmConfig(ns)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
// resp, err := action.NewGet(cfg).Run(n)
|
resp, err := action.NewGet(cfg).Run(n)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return resp.Manifest, nil
|
return resp.Manifest, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Delete uninstall a Chart.
|
// Delete uninstall a Chart.
|
||||||
// func (c *Chart) Delete(path string, cascade, force bool) error {
|
func (c *Chart) Delete(path string, cascade, force bool) error {
|
||||||
// ns, n := client.Namespaced(path)
|
ns, n := client.Namespaced(path)
|
||||||
// cfg, err := c.EnsureHelmConfig(ns)
|
cfg, err := c.EnsureHelmConfig(ns)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return err
|
return err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// res, err := action.NewUninstall(cfg).Run(n)
|
res, err := action.NewUninstall(cfg).Run(n)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return err
|
return err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if res != nil && res.Info != "" {
|
if res != nil && res.Info != "" {
|
||||||
// return fmt.Errorf("%s", res.Info)
|
return fmt.Errorf("%s", res.Info)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// return nil
|
return nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // EnsureHelmConfig return a new configuration.
|
// EnsureHelmConfig return a new configuration.
|
||||||
// func (c *Chart) EnsureHelmConfig(ns string) (*action.Configuration, error) {
|
func (c *Chart) EnsureHelmConfig(ns string) (*action.Configuration, error) {
|
||||||
// cfg := new(action.Configuration)
|
cfg := new(action.Configuration)
|
||||||
// flags := c.Client().Config().Flags()
|
flags := c.Client().Config().Flags()
|
||||||
// if err := cfg.Init(flags, ns, os.Getenv("HELM_DRIVER"), helmLogger); err != nil {
|
if err := cfg.Init(flags, ns, os.Getenv("HELM_DRIVER"), helmLogger); err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
// return cfg, nil
|
return cfg, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// func helmLogger(s string, args ...interface{}) {
|
func helmLogger(s string, args ...interface{}) {
|
||||||
// log.Debug().Msgf("%s %v", s, args)
|
log.Debug().Msgf("%s %v", s, args)
|
||||||
// }
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ func (readWriteCloser) Close() error {
|
||||||
func (p *Popeye) List(ctx context.Context, _ string) ([]runtime.Object, error) {
|
func (p *Popeye) List(ctx context.Context, _ string) ([]runtime.Object, error) {
|
||||||
defer func(t time.Time) {
|
defer func(t time.Time) {
|
||||||
log.Debug().Msgf("Popeye -- Elapsed %v", time.Since(t))
|
log.Debug().Msgf("Popeye -- Elapsed %v", time.Since(t))
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
log.Debug().Msgf("POPEYE DIED!")
|
||||||
|
}
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
flags := config.NewFlags()
|
flags := config.NewFlags()
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ const maxBuff = 10
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Command represents a command buffer.
|
// Command represents a command buffer.
|
||||||
Command BufferKind = 1 << iota
|
CommandBuffer BufferKind = 1 << iota
|
||||||
// Filter represents a filter buffer.
|
// Filter represents a filter buffer.
|
||||||
Filter
|
FilterBuffer
|
||||||
)
|
)
|
||||||
|
|
||||||
// BufferKind indicates a buffer type
|
// BufferKind indicates a buffer type
|
||||||
|
|
@ -40,6 +40,29 @@ func NewCmdBuff(key rune, kind BufferKind) *CmdBuff {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CmdBuff) CurrentSuggestion() (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
func (c *CmdBuff) NextSuggestion() (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
func (c *CmdBuff) PrevSuggestion() (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
func (c *CmdBuff) ClearSuggestions() {}
|
||||||
|
|
||||||
|
func (c *CmdBuff) AutoSuggests() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggestions returns suggestions.
|
||||||
|
func (c *CmdBuff) Suggestions() []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify notifies all listener of current suggestions.
|
||||||
|
func (c *CmdBuff) Notify() {}
|
||||||
|
|
||||||
// InCmdMode checks if a command exists and the buffer is active.
|
// InCmdMode checks if a command exists and the buffer is active.
|
||||||
func (c *CmdBuff) InCmdMode() bool {
|
func (c *CmdBuff) InCmdMode() bool {
|
||||||
return c.active || len(c.buff) > 0
|
return c.active || len(c.buff) > 0
|
||||||
|
|
@ -56,21 +79,21 @@ func (c *CmdBuff) SetActive(b bool) {
|
||||||
c.fireActive(c.active)
|
c.fireActive(c.active)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String turns rune to string (Stringer protocol)
|
// GetText returns the current text.
|
||||||
func (c *CmdBuff) String() string {
|
func (c *CmdBuff) GetText() string {
|
||||||
return string(c.buff)
|
return string(c.buff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set initializes the buffer with a command.
|
// Set initializes the buffer with a command.
|
||||||
func (c *CmdBuff) Set(cmd string) {
|
func (c *CmdBuff) SetText(cmd string) {
|
||||||
c.buff = []rune(cmd)
|
c.buff = []rune(cmd)
|
||||||
c.fireChanged()
|
c.fireBufferChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a new charater to the buffer.
|
// Add adds a new charater to the buffer.
|
||||||
func (c *CmdBuff) Add(r rune) {
|
func (c *CmdBuff) Add(r rune) {
|
||||||
c.buff = append(c.buff, r)
|
c.buff = append(c.buff, r)
|
||||||
c.fireChanged()
|
c.fireBufferChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete removes the last character from the buffer.
|
// Delete removes the last character from the buffer.
|
||||||
|
|
@ -79,19 +102,19 @@ func (c *CmdBuff) Delete() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.buff = c.buff[:len(c.buff)-1]
|
c.buff = c.buff[:len(c.buff)-1]
|
||||||
c.fireChanged()
|
c.fireBufferChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears out command buffer.
|
// ClearText clears out command buffer.
|
||||||
func (c *CmdBuff) Clear() {
|
func (c *CmdBuff) ClearText() {
|
||||||
c.buff = make([]rune, 0, maxBuff)
|
c.buff = make([]rune, 0, maxBuff)
|
||||||
c.fireChanged()
|
c.fireBufferChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset clears out the command buffer and deactives it.
|
// Reset clears out the command buffer and deactivates it.
|
||||||
func (c *CmdBuff) Reset() {
|
func (c *CmdBuff) Reset() {
|
||||||
c.Clear()
|
c.ClearText()
|
||||||
c.fireChanged()
|
c.fireBufferChanged()
|
||||||
c.SetActive(false)
|
c.SetActive(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,8 +127,8 @@ func (c *CmdBuff) Empty() bool {
|
||||||
// Event Listeners...
|
// Event Listeners...
|
||||||
|
|
||||||
// AddListener registers a cmd buffer listener.
|
// AddListener registers a cmd buffer listener.
|
||||||
func (c *CmdBuff) AddListener(w ...BuffWatcher) {
|
func (c *CmdBuff) AddListener(w BuffWatcher) {
|
||||||
c.listeners = append(c.listeners, w...)
|
c.listeners = append(c.listeners, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveListener unregisters a listener.
|
// RemoveListener unregisters a listener.
|
||||||
|
|
@ -124,9 +147,9 @@ func (c *CmdBuff) RemoveListener(l BuffWatcher) {
|
||||||
c.listeners = append(c.listeners[:victim], c.listeners[victim+1:]...)
|
c.listeners = append(c.listeners[:victim], c.listeners[victim+1:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CmdBuff) fireChanged() {
|
func (c *CmdBuff) fireBufferChanged() {
|
||||||
for _, l := range c.listeners {
|
for _, l := range c.listeners {
|
||||||
l.BufferChanged(c.String())
|
l.BufferChanged(c.GetText())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func (l *testListener) BufferActive(s bool, _ model.BufferKind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffActivate(t *testing.T) {
|
func TestCmdBuffActivate(t *testing.T) {
|
||||||
b, l := model.NewCmdBuff('>', model.Command), testListener{}
|
b, l := model.NewCmdBuff('>', model.CommandBuffer), testListener{}
|
||||||
b.AddListener(&l)
|
b.AddListener(&l)
|
||||||
|
|
||||||
b.SetActive(true)
|
b.SetActive(true)
|
||||||
|
|
@ -36,7 +36,7 @@ func TestCmdBuffActivate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffDeactivate(t *testing.T) {
|
func TestCmdBuffDeactivate(t *testing.T) {
|
||||||
b, l := model.NewCmdBuff('>', model.Command), testListener{}
|
b, l := model.NewCmdBuff('>', model.CommandBuffer), testListener{}
|
||||||
b.AddListener(&l)
|
b.AddListener(&l)
|
||||||
|
|
||||||
b.SetActive(false)
|
b.SetActive(false)
|
||||||
|
|
@ -46,39 +46,39 @@ func TestCmdBuffDeactivate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffChanged(t *testing.T) {
|
func TestCmdBuffChanged(t *testing.T) {
|
||||||
b, l := model.NewCmdBuff('>', model.Command), testListener{}
|
b, l := model.NewCmdBuff('>', model.CommandBuffer), testListener{}
|
||||||
b.AddListener(&l)
|
b.AddListener(&l)
|
||||||
|
|
||||||
b.Add('b')
|
b.Add('b')
|
||||||
assert.Equal(t, 0, l.act)
|
assert.Equal(t, 0, l.act)
|
||||||
assert.Equal(t, 0, l.inact)
|
assert.Equal(t, 0, l.inact)
|
||||||
assert.Equal(t, "b", l.text)
|
assert.Equal(t, "b", l.text)
|
||||||
assert.Equal(t, "b", b.String())
|
assert.Equal(t, "b", b.GetText())
|
||||||
|
|
||||||
b.Delete()
|
b.Delete()
|
||||||
assert.Equal(t, 0, l.act)
|
assert.Equal(t, 0, l.act)
|
||||||
assert.Equal(t, 0, l.inact)
|
assert.Equal(t, 0, l.inact)
|
||||||
assert.Equal(t, "", l.text)
|
assert.Equal(t, "", l.text)
|
||||||
assert.Equal(t, "", b.String())
|
assert.Equal(t, "", b.GetText())
|
||||||
|
|
||||||
b.Add('c')
|
b.Add('c')
|
||||||
b.Clear()
|
b.ClearText()
|
||||||
assert.Equal(t, 0, l.act)
|
assert.Equal(t, 0, l.act)
|
||||||
assert.Equal(t, 0, l.inact)
|
assert.Equal(t, 0, l.inact)
|
||||||
assert.Equal(t, "", l.text)
|
assert.Equal(t, "", l.text)
|
||||||
assert.Equal(t, "", b.String())
|
assert.Equal(t, "", b.GetText())
|
||||||
|
|
||||||
b.Add('c')
|
b.Add('c')
|
||||||
b.Reset()
|
b.Reset()
|
||||||
assert.Equal(t, 0, l.act)
|
assert.Equal(t, 0, l.act)
|
||||||
assert.Equal(t, 1, l.inact)
|
assert.Equal(t, 1, l.inact)
|
||||||
assert.Equal(t, "", l.text)
|
assert.Equal(t, "", l.text)
|
||||||
assert.Equal(t, "", b.String())
|
assert.Equal(t, "", b.GetText())
|
||||||
assert.True(t, b.Empty())
|
assert.True(t, b.Empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffAdd(t *testing.T) {
|
func TestCmdBuffAdd(t *testing.T) {
|
||||||
b := model.NewCmdBuff('>', model.Command)
|
b := model.NewCmdBuff('>', model.CommandBuffer)
|
||||||
|
|
||||||
uu := []struct {
|
uu := []struct {
|
||||||
runes []rune
|
runes []rune
|
||||||
|
|
@ -93,13 +93,13 @@ func TestCmdBuffAdd(t *testing.T) {
|
||||||
for _, r := range u.runes {
|
for _, r := range u.runes {
|
||||||
b.Add(r)
|
b.Add(r)
|
||||||
}
|
}
|
||||||
assert.Equal(t, u.cmd, b.String())
|
assert.Equal(t, u.cmd, b.GetText())
|
||||||
b.Reset()
|
b.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffDel(t *testing.T) {
|
func TestCmdBuffDel(t *testing.T) {
|
||||||
b := model.NewCmdBuff('>', model.Command)
|
b := model.NewCmdBuff('>', model.CommandBuffer)
|
||||||
|
|
||||||
uu := []struct {
|
uu := []struct {
|
||||||
runes []rune
|
runes []rune
|
||||||
|
|
@ -115,13 +115,13 @@ func TestCmdBuffDel(t *testing.T) {
|
||||||
b.Add(r)
|
b.Add(r)
|
||||||
}
|
}
|
||||||
b.Delete()
|
b.Delete()
|
||||||
assert.Equal(t, u.cmd, b.String())
|
assert.Equal(t, u.cmd, b.GetText())
|
||||||
b.Reset()
|
b.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdBuffEmpty(t *testing.T) {
|
func TestCmdBuffEmpty(t *testing.T) {
|
||||||
b := model.NewCmdBuff('>', model.Command)
|
b := model.NewCmdBuff('>', model.CommandBuffer)
|
||||||
|
|
||||||
uu := []struct {
|
uu := []struct {
|
||||||
runes []rune
|
runes []rune
|
||||||
|
|
|
||||||
|
|
@ -9,22 +9,72 @@ type SuggestionListener interface {
|
||||||
BuffWatcher
|
BuffWatcher
|
||||||
|
|
||||||
// SuggestionChanged notifies suggestion changes.
|
// SuggestionChanged notifies suggestion changes.
|
||||||
SuggestionChanged([]string)
|
SuggestionChanged(text, sugg string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuggestionFunc produces suggestions.
|
// SuggestionFunc produces suggestions.
|
||||||
type SuggestionFunc func(s string) sort.StringSlice
|
type SuggestionFunc func(text string) sort.StringSlice
|
||||||
|
|
||||||
// FishBuff represents a suggestion buffer.
|
// FishBuff represents a suggestion buffer.
|
||||||
type FishBuff struct {
|
type FishBuff struct {
|
||||||
*CmdBuff
|
*CmdBuff
|
||||||
|
|
||||||
suggestionFn SuggestionFunc
|
suggestionFn SuggestionFunc
|
||||||
|
suggestion string
|
||||||
|
suggestions []string
|
||||||
|
suggestionIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFishBuff returns a new command buffer.
|
// NewFishBuff returns a new command buffer.
|
||||||
func NewFishBuff(key rune, kind BufferKind) *FishBuff {
|
func NewFishBuff(key rune, kind BufferKind) *FishBuff {
|
||||||
return &FishBuff{CmdBuff: NewCmdBuff(key, kind)}
|
return &FishBuff{
|
||||||
|
CmdBuff: NewCmdBuff(key, kind),
|
||||||
|
suggestionIndex: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FishBuff) PrevSuggestion() (string, bool) {
|
||||||
|
if c.suggestionIndex < 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
c.suggestionIndex--
|
||||||
|
if c.suggestionIndex < 0 {
|
||||||
|
c.suggestionIndex = len(c.suggestions) - 1
|
||||||
|
}
|
||||||
|
return c.suggestions[c.suggestionIndex], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FishBuff) NextSuggestion() (string, bool) {
|
||||||
|
if c.suggestionIndex < 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
c.suggestionIndex++
|
||||||
|
if c.suggestionIndex >= len(c.suggestions) {
|
||||||
|
c.suggestionIndex = 0
|
||||||
|
}
|
||||||
|
return c.suggestions[c.suggestionIndex], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FishBuff) ClearSuggestions() {
|
||||||
|
c.suggestion, c.suggestionIndex = "", -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FishBuff) CurrentSuggestion() (string, bool) {
|
||||||
|
if c.suggestionIndex < 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return c.suggestions[c.suggestionIndex], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FishBuff) AutoSuggests() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FishBuff) Suggestions() []string {
|
||||||
|
if f.suggestionFn != nil {
|
||||||
|
return f.suggestionFn(string(f.buff))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSuggestionFn sets up suggestions.
|
// SetSuggestionFn sets up suggestions.
|
||||||
|
|
@ -32,23 +82,13 @@ func (f *FishBuff) SetSuggestionFn(fn SuggestionFunc) {
|
||||||
f.suggestionFn = fn
|
f.suggestionFn = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate activates the command.
|
// Notify publish suggestions to all listeners.
|
||||||
func (f *FishBuff) Activate() {
|
func (f *FishBuff) Notify() {
|
||||||
if f.suggestionFn == nil {
|
if f.suggestionFn == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cc := f.suggestionFn(string(f.buff))
|
cc := f.suggestionFn(string(f.buff))
|
||||||
f.fireSuggest(cc)
|
f.fireSuggestionChanged(cc)
|
||||||
}
|
|
||||||
|
|
||||||
// Delete removes the last character from the buffer.
|
|
||||||
func (f *FishBuff) Delete() {
|
|
||||||
f.CmdBuff.Delete()
|
|
||||||
if f.suggestionFn == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cc := f.suggestionFn(string(f.buff))
|
|
||||||
f.fireSuggest(cc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a new charater to the buffer.
|
// Add adds a new charater to the buffer.
|
||||||
|
|
@ -58,13 +98,30 @@ func (f *FishBuff) Add(r rune) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cc := f.suggestionFn(string(f.buff))
|
cc := f.suggestionFn(string(f.buff))
|
||||||
f.fireSuggest(cc)
|
f.fireSuggestionChanged(cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FishBuff) fireSuggest(cc []string) {
|
// Delete removes the last character from the buffer.
|
||||||
|
func (f *FishBuff) Delete() {
|
||||||
|
f.CmdBuff.Delete()
|
||||||
|
if f.suggestionFn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cc := f.suggestionFn(string(f.buff))
|
||||||
|
f.fireSuggestionChanged(cc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FishBuff) fireSuggestionChanged(ss []string) {
|
||||||
|
f.suggestions, f.suggestionIndex = ss, 0
|
||||||
|
if ss == nil {
|
||||||
|
f.suggestionIndex, f.suggestion = -1, ""
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.suggestion = ss[f.suggestionIndex]
|
||||||
|
|
||||||
for _, l := range f.listeners {
|
for _, l := range f.listeners {
|
||||||
if s, ok := l.(SuggestionListener); ok {
|
if listener, ok := l.(SuggestionListener); ok {
|
||||||
s.SuggestionChanged(cc)
|
listener.SuggestionChanged(f.GetText(), f.suggestion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,31 +14,29 @@ type App struct {
|
||||||
*tview.Application
|
*tview.Application
|
||||||
Configurator
|
Configurator
|
||||||
|
|
||||||
Main *Pages
|
Main *Pages
|
||||||
flash *model.Flash
|
flash *model.Flash
|
||||||
actions KeyActions
|
actions KeyActions
|
||||||
views map[string]tview.Primitive
|
views map[string]tview.Primitive
|
||||||
cmdBuff *model.FishBuff
|
cmdModel *model.FishBuff
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewApp returns a new app.
|
// NewApp returns a new app.
|
||||||
func NewApp(cfg *config.Config, context string) *App {
|
func NewApp(cfg *config.Config, context string) *App {
|
||||||
a := App{
|
a := App{
|
||||||
Application: tview.NewApplication(),
|
Application: tview.NewApplication(),
|
||||||
actions: make(KeyActions),
|
actions: make(KeyActions),
|
||||||
Configurator: Configurator{
|
Configurator: Configurator{Config: cfg},
|
||||||
Config: cfg,
|
Main: NewPages(),
|
||||||
},
|
flash: model.NewFlash(model.DefaultFlashDelay),
|
||||||
Main: NewPages(),
|
cmdModel: model.NewFishBuff(':', model.CommandBuffer),
|
||||||
flash: model.NewFlash(model.DefaultFlashDelay),
|
|
||||||
cmdBuff: model.NewFishBuff(':', model.Command),
|
|
||||||
}
|
}
|
||||||
a.ReloadStyles(context)
|
a.ReloadStyles(context)
|
||||||
|
|
||||||
a.views = map[string]tview.Primitive{
|
a.views = map[string]tview.Primitive{
|
||||||
"menu": NewMenu(a.Styles),
|
"menu": NewMenu(a.Styles),
|
||||||
"logo": NewLogo(a.Styles),
|
"logo": NewLogo(a.Styles),
|
||||||
"cmd": NewCommand(a.Config.K9s.NoIcons, a.Styles, a.cmdBuff),
|
"prompt": NewPrompt(a.Config.K9s.NoIcons, a.Styles),
|
||||||
"crumbs": NewCrumbs(a.Styles),
|
"crumbs": NewCrumbs(a.Styles),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,9 +46,9 @@ func NewApp(cfg *config.Config, context string) *App {
|
||||||
// Init initializes the application.
|
// Init initializes the application.
|
||||||
func (a *App) Init() {
|
func (a *App) Init() {
|
||||||
a.bindKeys()
|
a.bindKeys()
|
||||||
a.cmdBuff.AddListener(a.Cmd())
|
a.Prompt().SetModel(a.cmdModel)
|
||||||
|
a.cmdModel.AddListener(a)
|
||||||
a.Styles.AddListener(a)
|
a.Styles.AddListener(a)
|
||||||
a.CmdBuff().AddListener(a)
|
|
||||||
|
|
||||||
a.SetRoot(a.Main, true)
|
a.SetRoot(a.Main, true)
|
||||||
}
|
}
|
||||||
|
|
@ -59,16 +57,17 @@ func (a *App) Init() {
|
||||||
func (a *App) BufferChanged(s string) {}
|
func (a *App) BufferChanged(s string) {}
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
// BufferActive indicates the buff activity changed.
|
||||||
func (a *App) BufferActive(state bool, _ model.BufferKind) {
|
func (a *App) BufferActive(state bool, kind model.BufferKind) {
|
||||||
flex, ok := a.Main.GetPrimitive("main").(*tview.Flex)
|
flex, ok := a.Main.GetPrimitive("main").(*tview.Flex)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if state && flex.ItemAt(1) != a.Cmd() {
|
if state && flex.ItemAt(1) != a.Prompt() {
|
||||||
flex.AddItemAtIndex(1, a.Cmd(), 3, 1, false)
|
flex.AddItemAtIndex(1, a.Prompt(), 3, 1, false)
|
||||||
} else if !state && flex.ItemAt(1) == a.Cmd() {
|
} else if !state && flex.ItemAt(1) == a.Prompt() {
|
||||||
flex.RemoveItemAtIndex(1)
|
flex.RemoveItemAtIndex(1)
|
||||||
|
a.SetFocus(flex)
|
||||||
}
|
}
|
||||||
a.Draw()
|
a.Draw()
|
||||||
}
|
}
|
||||||
|
|
@ -103,15 +102,11 @@ func (a *App) Conn() client.Connection {
|
||||||
|
|
||||||
func (a *App) bindKeys() {
|
func (a *App) bindKeys() {
|
||||||
a.actions = KeyActions{
|
a.actions = KeyActions{
|
||||||
KeyColon: NewKeyAction("Cmd", a.activateCmd, false),
|
KeyColon: NewKeyAction("Cmd", a.activateCmd, false),
|
||||||
tcell.KeyCtrlR: NewKeyAction("Redraw", a.redrawCmd, false),
|
tcell.KeyCtrlR: NewKeyAction("Redraw", a.redrawCmd, false),
|
||||||
tcell.KeyCtrlC: NewKeyAction("Quit", a.quitCmd, false),
|
tcell.KeyCtrlC: NewKeyAction("Quit", a.quitCmd, false),
|
||||||
tcell.KeyEscape: NewKeyAction("Escape", a.escapeCmd, false),
|
tcell.KeyCtrlU: NewSharedKeyAction("Clear Filter", a.clearCmd, false),
|
||||||
tcell.KeyBackspace2: NewKeyAction("Erase", a.eraseCmd, false),
|
tcell.KeyCtrlQ: NewSharedKeyAction("Clear Filter", a.clearCmd, false),
|
||||||
tcell.KeyBackspace: NewKeyAction("Erase", a.eraseCmd, false),
|
|
||||||
tcell.KeyDelete: NewKeyAction("Erase", a.eraseCmd, false),
|
|
||||||
tcell.KeyCtrlU: NewSharedKeyAction("Clear Filter", a.clearCmd, false),
|
|
||||||
tcell.KeyCtrlQ: NewSharedKeyAction("Clear Filter", a.clearCmd, false),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,29 +115,35 @@ func (a *App) BailOut() {
|
||||||
a.Stop()
|
a.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) ResetPrompt(m PromptModel) {
|
||||||
|
a.Prompt().SetModel(m)
|
||||||
|
a.SetFocus(a.Prompt())
|
||||||
|
m.SetActive(true)
|
||||||
|
}
|
||||||
|
|
||||||
// ResetCmd clear out user command.
|
// ResetCmd clear out user command.
|
||||||
func (a *App) ResetCmd() {
|
func (a *App) ResetCmd() {
|
||||||
a.cmdBuff.Reset()
|
a.cmdModel.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActivateCmd toggle command mode.
|
// ActivateCmd toggle command mode.
|
||||||
func (a *App) ActivateCmd(b bool) {
|
func (a *App) ActivateCmd(b bool) {
|
||||||
a.cmdBuff.SetActive(b)
|
a.cmdModel.SetActive(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCmd retrieves user command.
|
// GetCmd retrieves user command.
|
||||||
func (a *App) GetCmd() string {
|
func (a *App) GetCmd() string {
|
||||||
return a.cmdBuff.String()
|
return a.cmdModel.GetText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdBuff returns a cmd buffer.
|
// CmdBuff returns a cmd buffer.
|
||||||
func (a *App) CmdBuff() *model.FishBuff {
|
func (a *App) CmdBuff() *model.FishBuff {
|
||||||
return a.cmdBuff
|
return a.cmdModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasCmd check if cmd buffer is active and has a command.
|
// HasCmd check if cmd buffer is active and has a command.
|
||||||
func (a *App) HasCmd() bool {
|
func (a *App) HasCmd() bool {
|
||||||
return a.cmdBuff.IsActive() && !a.cmdBuff.Empty()
|
return a.cmdModel.IsActive() && !a.cmdModel.Empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) quitCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) quitCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
@ -156,7 +157,7 @@ func (a *App) quitCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
// InCmdMode check if command mode is active.
|
// InCmdMode check if command mode is active.
|
||||||
func (a *App) InCmdMode() bool {
|
func (a *App) InCmdMode() bool {
|
||||||
return a.Cmd().InCmdMode()
|
return a.Prompt().InCmdMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasAction checks if key matches a registered binding.
|
// HasAction checks if key matches a registered binding.
|
||||||
|
|
@ -186,7 +187,7 @@ func (a *App) clearCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if !a.CmdBuff().IsActive() {
|
if !a.CmdBuff().IsActive() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
a.CmdBuff().Clear()
|
a.CmdBuff().ClearText()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -195,38 +196,19 @@ func (a *App) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if a.InCmdMode() {
|
if a.InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
a.cmdBuff.SetActive(true)
|
a.ResetPrompt(a.cmdModel)
|
||||||
a.cmdBuff.Clear()
|
a.cmdModel.ClearText()
|
||||||
a.SetFocus(a.Cmd())
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EraseCmd removes the last char from a command.
|
|
||||||
func (a *App) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if a.cmdBuff.IsActive() {
|
|
||||||
a.cmdBuff.Delete()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
|
|
||||||
// EscapeCmd dismiss cmd mode.
|
|
||||||
func (a *App) escapeCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if a.cmdBuff.IsActive() {
|
|
||||||
a.cmdBuff.Reset()
|
|
||||||
a.SetFocus(a.Main.GetPrimitive("main"))
|
|
||||||
}
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
|
|
||||||
// RedrawCmd forces a redraw.
|
// RedrawCmd forces a redraw.
|
||||||
func (a *App) redrawCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) redrawCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
a.Draw()
|
a.Draw()
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
// View Accessora...
|
// View Accessors...
|
||||||
|
|
||||||
// Crumbs return app crumba.
|
// Crumbs return app crumba.
|
||||||
func (a *App) Crumbs() *Crumbs {
|
func (a *App) Crumbs() *Crumbs {
|
||||||
|
|
@ -239,8 +221,8 @@ func (a *App) Logo() *Logo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cmd returns app cmd.
|
// Cmd returns app cmd.
|
||||||
func (a *App) Cmd() *Command {
|
func (a *App) Prompt() *Prompt {
|
||||||
return a.views["cmd"].(*Command)
|
return a.views["prompt"].(*Prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menu returns app menu.
|
// Menu returns app menu.
|
||||||
|
|
@ -258,6 +240,9 @@ func (a *App) Flash() *model.Flash {
|
||||||
|
|
||||||
// AsKey converts rune to keyboard key.,
|
// AsKey converts rune to keyboard key.,
|
||||||
func AsKey(evt *tcell.EventKey) tcell.Key {
|
func AsKey(evt *tcell.EventKey) tcell.Key {
|
||||||
|
if evt.Key() != tcell.KeyRune {
|
||||||
|
return evt.Key()
|
||||||
|
}
|
||||||
key := tcell.Key(evt.Rune())
|
key := tcell.Key(evt.Rune())
|
||||||
if evt.Modifiers() == tcell.ModAlt {
|
if evt.Modifiers() == tcell.ModAlt {
|
||||||
key = tcell.Key(int16(evt.Rune()) * int16(evt.Modifiers()))
|
key = tcell.Key(int16(evt.Rune()) * int16(evt.Modifiers()))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
func TestAppGetCmd(t *testing.T) {
|
func TestAppGetCmd(t *testing.T) {
|
||||||
a := ui.NewApp(config.NewConfig(nil), "")
|
a := ui.NewApp(config.NewConfig(nil), "")
|
||||||
a.Init()
|
a.Init()
|
||||||
a.CmdBuff().Set("blee")
|
a.CmdBuff().SetText("blee")
|
||||||
|
|
||||||
assert.Equal(t, "blee", a.GetCmd())
|
assert.Equal(t, "blee", a.GetCmd())
|
||||||
}
|
}
|
||||||
|
|
@ -19,21 +19,21 @@ func TestAppGetCmd(t *testing.T) {
|
||||||
func TestAppInCmdMode(t *testing.T) {
|
func TestAppInCmdMode(t *testing.T) {
|
||||||
a := ui.NewApp(config.NewConfig(nil), "")
|
a := ui.NewApp(config.NewConfig(nil), "")
|
||||||
a.Init()
|
a.Init()
|
||||||
a.CmdBuff().Set("blee")
|
a.CmdBuff().SetText("blee")
|
||||||
assert.False(t, a.InCmdMode())
|
assert.False(t, a.InCmdMode())
|
||||||
|
|
||||||
a.CmdBuff().SetActive(true)
|
a.CmdBuff().SetActive(false)
|
||||||
assert.True(t, a.InCmdMode())
|
assert.False(t, a.InCmdMode())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppResetCmd(t *testing.T) {
|
func TestAppResetCmd(t *testing.T) {
|
||||||
a := ui.NewApp(config.NewConfig(nil), "")
|
a := ui.NewApp(config.NewConfig(nil), "")
|
||||||
a.Init()
|
a.Init()
|
||||||
a.CmdBuff().Set("blee")
|
a.CmdBuff().SetText("blee")
|
||||||
|
|
||||||
a.ResetCmd()
|
a.ResetCmd()
|
||||||
|
|
||||||
assert.Equal(t, "", a.CmdBuff().String())
|
assert.Equal(t, "", a.CmdBuff().GetText())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppHasCmd(t *testing.T) {
|
func TestAppHasCmd(t *testing.T) {
|
||||||
|
|
@ -43,7 +43,7 @@ func TestAppHasCmd(t *testing.T) {
|
||||||
a.ActivateCmd(true)
|
a.ActivateCmd(true)
|
||||||
assert.False(t, a.HasCmd())
|
assert.False(t, a.HasCmd())
|
||||||
|
|
||||||
a.CmdBuff().Set("blee")
|
a.CmdBuff().SetText("blee")
|
||||||
assert.True(t, a.InCmdMode())
|
assert.True(t, a.InCmdMode())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,14 +53,14 @@ func TestAppGetActions(t *testing.T) {
|
||||||
|
|
||||||
a.AddActions(ui.KeyActions{ui.KeyZ: ui.KeyAction{Description: "zorg"}})
|
a.AddActions(ui.KeyActions{ui.KeyZ: ui.KeyAction{Description: "zorg"}})
|
||||||
|
|
||||||
assert.Equal(t, 10, len(a.GetActions()))
|
assert.Equal(t, 6, len(a.GetActions()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppViews(t *testing.T) {
|
func TestAppViews(t *testing.T) {
|
||||||
a := ui.NewApp(config.NewConfig(nil), "")
|
a := ui.NewApp(config.NewConfig(nil), "")
|
||||||
a.Init()
|
a.Init()
|
||||||
|
|
||||||
vv := []string{"crumbs", "logo", "cmd", "menu"}
|
vv := []string{"crumbs", "logo", "prompt", "menu"}
|
||||||
for i := range vv {
|
for i := range vv {
|
||||||
v := vv[i]
|
v := vv[i]
|
||||||
t.Run(v, func(t *testing.T) {
|
t.Run(v, func(t *testing.T) {
|
||||||
|
|
@ -70,6 +70,6 @@ func TestAppViews(t *testing.T) {
|
||||||
|
|
||||||
assert.NotNil(t, a.Crumbs())
|
assert.NotNil(t, a.Crumbs())
|
||||||
assert.NotNil(t, a.Logo())
|
assert.NotNil(t, a.Logo())
|
||||||
assert.NotNil(t, a.Cmd())
|
assert.NotNil(t, a.Prompt())
|
||||||
assert.NotNil(t, a.Menu())
|
assert.NotNil(t, a.Menu())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/config"
|
|
||||||
"github.com/derailed/k9s/internal/model"
|
|
||||||
"github.com/derailed/tview"
|
|
||||||
"github.com/gdamore/tcell"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultPrompt = "%c> [::b]%s"
|
|
||||||
defaultSpacer = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command captures users free from command input.
|
|
||||||
type Command struct {
|
|
||||||
*tview.TextView
|
|
||||||
|
|
||||||
activated bool
|
|
||||||
noIcons bool
|
|
||||||
icon rune
|
|
||||||
text string
|
|
||||||
suggestion string
|
|
||||||
styles *config.Styles
|
|
||||||
model *model.FishBuff
|
|
||||||
suggestions []string
|
|
||||||
suggestionIndex int
|
|
||||||
spacer int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCommand returns a new command view.
|
|
||||||
func NewCommand(noIcons bool, styles *config.Styles, m *model.FishBuff) *Command {
|
|
||||||
c := Command{
|
|
||||||
styles: styles,
|
|
||||||
noIcons: noIcons,
|
|
||||||
TextView: tview.NewTextView(),
|
|
||||||
spacer: defaultSpacer,
|
|
||||||
model: m,
|
|
||||||
suggestionIndex: -1,
|
|
||||||
}
|
|
||||||
if noIcons {
|
|
||||||
c.spacer--
|
|
||||||
}
|
|
||||||
c.SetWordWrap(true)
|
|
||||||
c.ShowCursor(true)
|
|
||||||
c.SetWrap(true)
|
|
||||||
c.SetDynamicColors(true)
|
|
||||||
c.SetBorder(true)
|
|
||||||
c.SetBorderPadding(0, 0, 1, 1)
|
|
||||||
c.SetBackgroundColor(styles.BgColor())
|
|
||||||
c.SetTextColor(styles.FgColor())
|
|
||||||
styles.AddListener(&c)
|
|
||||||
c.SetInputCapture(c.keyboard)
|
|
||||||
|
|
||||||
return &c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
switch evt.Key() {
|
|
||||||
case tcell.KeyEnter, tcell.KeyCtrlE:
|
|
||||||
if c.suggestionIndex >= 0 {
|
|
||||||
c.model.Set(c.text + c.suggestions[c.suggestionIndex])
|
|
||||||
}
|
|
||||||
case tcell.KeyCtrlW, tcell.KeyCtrlU:
|
|
||||||
c.model.Clear()
|
|
||||||
case tcell.KeyDown:
|
|
||||||
if c.suggestionIndex < 0 {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
c.suggestionIndex++
|
|
||||||
if c.suggestionIndex >= len(c.suggestions) {
|
|
||||||
c.suggestionIndex = 0
|
|
||||||
}
|
|
||||||
c.suggest(c.model.String(), c.suggestions[c.suggestionIndex])
|
|
||||||
case tcell.KeyUp:
|
|
||||||
if c.suggestionIndex < 0 {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
c.suggestionIndex--
|
|
||||||
if c.suggestionIndex < 0 {
|
|
||||||
c.suggestionIndex = len(c.suggestions) - 1
|
|
||||||
}
|
|
||||||
c.suggest(c.model.String(), c.suggestions[c.suggestionIndex])
|
|
||||||
case tcell.KeyTab, tcell.KeyRight, tcell.KeyCtrlF:
|
|
||||||
if c.suggestionIndex >= 0 {
|
|
||||||
c.model.Set(c.model.String() + c.suggestions[c.suggestionIndex])
|
|
||||||
c.suggestionIndex = -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
|
|
||||||
// StylesChanged notifies skin changed.
|
|
||||||
func (c *Command) StylesChanged(s *config.Styles) {
|
|
||||||
c.styles = s
|
|
||||||
c.SetBackgroundColor(s.BgColor())
|
|
||||||
c.SetTextColor(s.FgColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
// InCmdMode returns true if command is active, false otherwise.
|
|
||||||
func (c *Command) InCmdMode() bool {
|
|
||||||
return c.activated
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) activate() {
|
|
||||||
c.SetCursorIndex(len(c.text))
|
|
||||||
c.write(false, c.text, "")
|
|
||||||
c.model.Activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) update(s string) {
|
|
||||||
if c.text == s {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.text = s
|
|
||||||
c.Clear()
|
|
||||||
c.write(false, s, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) suggest(text, suggestion string) {
|
|
||||||
c.Clear()
|
|
||||||
c.write(false, text, suggestion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) write(append bool, text, suggest string) {
|
|
||||||
c.suggestion = suggest
|
|
||||||
c.SetCursorIndex(c.spacer + len(text))
|
|
||||||
txt := text
|
|
||||||
if suggest != "" {
|
|
||||||
txt += "[gray::-]" + suggest
|
|
||||||
}
|
|
||||||
if append {
|
|
||||||
fmt.Fprintf(c, "[gray::-]%s", suggest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Fprintf(c, defaultPrompt, c.icon, txt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Event Listener protocol...
|
|
||||||
|
|
||||||
// SuggestionChanged indicates the suggestions changed.
|
|
||||||
func (c *Command) SuggestionChanged(ss []string) {
|
|
||||||
c.suggestions, c.suggestionIndex = ss, 0
|
|
||||||
if ss == nil {
|
|
||||||
c.suggestionIndex = -1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.suggestion == ss[c.suggestionIndex] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.write(true, c.text, ss[c.suggestionIndex])
|
|
||||||
}
|
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
|
||||||
func (c *Command) BufferChanged(s string) {
|
|
||||||
c.update(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
|
||||||
func (c *Command) BufferActive(f bool, k model.BufferKind) {
|
|
||||||
if c.activated = f; f {
|
|
||||||
c.SetBorder(true)
|
|
||||||
c.SetTextColor(c.styles.FgColor())
|
|
||||||
c.SetBorderColor(colorFor(k))
|
|
||||||
c.icon = c.iconFor(k)
|
|
||||||
c.activate()
|
|
||||||
} else {
|
|
||||||
c.SetBorder(false)
|
|
||||||
c.SetBackgroundColor(c.styles.BgColor())
|
|
||||||
c.Clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Command) iconFor(k model.BufferKind) rune {
|
|
||||||
if c.noIcons {
|
|
||||||
return ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
switch k {
|
|
||||||
case model.Command:
|
|
||||||
return '🐶'
|
|
||||||
default:
|
|
||||||
return '🐩'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Helpers...
|
|
||||||
|
|
||||||
func colorFor(k model.BufferKind) tcell.Color {
|
|
||||||
switch k {
|
|
||||||
case model.Command:
|
|
||||||
return tcell.ColorAqua
|
|
||||||
default:
|
|
||||||
return tcell.ColorSeaGreen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/derailed/k9s/internal/config"
|
||||||
|
"github.com/derailed/k9s/internal/model"
|
||||||
|
"github.com/derailed/tview"
|
||||||
|
"github.com/gdamore/tcell"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultPrompt = "%c> [::b]%s"
|
||||||
|
defaultSpacer = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ PromptModel = (*model.CmdBuff)(nil)
|
||||||
|
var _ Suggester = (*model.CmdBuff)(nil)
|
||||||
|
var _ PromptModel = (*model.FishBuff)(nil)
|
||||||
|
var _ Suggester = (*model.FishBuff)(nil)
|
||||||
|
|
||||||
|
type Suggester interface {
|
||||||
|
CurrentSuggestion() (string, bool)
|
||||||
|
NextSuggestion() (string, bool)
|
||||||
|
PrevSuggestion() (string, bool)
|
||||||
|
ClearSuggestions()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PromptModel interface {
|
||||||
|
// AutoSuggests returns true if model implements auto suggestions.
|
||||||
|
AutoSuggests() bool
|
||||||
|
|
||||||
|
// Suggestions returns suggestions.
|
||||||
|
Suggestions() []string
|
||||||
|
|
||||||
|
// SetText sets the model text.
|
||||||
|
SetText(string)
|
||||||
|
|
||||||
|
// GetText returns the current text.
|
||||||
|
GetText() string
|
||||||
|
|
||||||
|
// ClearText clears out model text.
|
||||||
|
ClearText()
|
||||||
|
|
||||||
|
// Notify notifies all listener of current suggestions.
|
||||||
|
Notify()
|
||||||
|
|
||||||
|
// AddListener registers a command listener.
|
||||||
|
AddListener(model.BuffWatcher)
|
||||||
|
|
||||||
|
// RemoveListener removes a listener.
|
||||||
|
RemoveListener(model.BuffWatcher)
|
||||||
|
|
||||||
|
IsActive() bool
|
||||||
|
SetActive(bool)
|
||||||
|
Add(rune)
|
||||||
|
Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompt captures users free from command input.
|
||||||
|
type Prompt struct {
|
||||||
|
*tview.TextView
|
||||||
|
|
||||||
|
noIcons bool
|
||||||
|
icon rune
|
||||||
|
styles *config.Styles
|
||||||
|
model PromptModel
|
||||||
|
spacer int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPrompt returns a new command view.
|
||||||
|
func NewPrompt(noIcons bool, styles *config.Styles) *Prompt {
|
||||||
|
c := Prompt{
|
||||||
|
styles: styles,
|
||||||
|
noIcons: noIcons,
|
||||||
|
TextView: tview.NewTextView(),
|
||||||
|
spacer: defaultSpacer,
|
||||||
|
}
|
||||||
|
if noIcons {
|
||||||
|
c.spacer--
|
||||||
|
}
|
||||||
|
c.SetWordWrap(true)
|
||||||
|
c.SetWrap(true)
|
||||||
|
c.SetDynamicColors(true)
|
||||||
|
c.SetBorder(true)
|
||||||
|
c.SetBorderPadding(0, 0, 1, 1)
|
||||||
|
c.SetBackgroundColor(styles.BgColor())
|
||||||
|
c.SetTextColor(styles.FgColor())
|
||||||
|
styles.AddListener(&c)
|
||||||
|
c.SetInputCapture(c.keyboard)
|
||||||
|
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendKey sends an keyboard event (testing only!).
|
||||||
|
func (p *Prompt) SendKey(evt *tcell.EventKey) {
|
||||||
|
p.keyboard(evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendStrokes (testing only!)
|
||||||
|
func (p *Prompt) SendStrokes(s string) {
|
||||||
|
for _, r := range s {
|
||||||
|
p.keyboard(tcell.NewEventKey(tcell.KeyRune, r, tcell.ModNone))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) SetModel(m PromptModel) {
|
||||||
|
if c.model != nil {
|
||||||
|
c.model.RemoveListener(c)
|
||||||
|
}
|
||||||
|
c.model = m
|
||||||
|
c.model.AddListener(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
m, ok := c.model.(Suggester)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch evt.Key() {
|
||||||
|
case tcell.KeyBackspace2, tcell.KeyBackspace, tcell.KeyDelete:
|
||||||
|
c.model.Delete()
|
||||||
|
case tcell.KeyRune:
|
||||||
|
c.model.Add(evt.Rune())
|
||||||
|
case tcell.KeyEscape:
|
||||||
|
c.model.ClearText()
|
||||||
|
c.model.SetActive(false)
|
||||||
|
case tcell.KeyEnter, tcell.KeyCtrlE:
|
||||||
|
if curr, ok := m.CurrentSuggestion(); ok {
|
||||||
|
c.model.SetText(c.model.GetText() + curr)
|
||||||
|
}
|
||||||
|
c.model.SetActive(false)
|
||||||
|
case tcell.KeyCtrlW, tcell.KeyCtrlU:
|
||||||
|
c.model.ClearText()
|
||||||
|
case tcell.KeyDown:
|
||||||
|
if next, ok := m.NextSuggestion(); ok {
|
||||||
|
c.suggest(c.model.GetText(), next)
|
||||||
|
}
|
||||||
|
case tcell.KeyUp:
|
||||||
|
if prev, ok := m.PrevSuggestion(); ok {
|
||||||
|
c.suggest(c.model.GetText(), prev)
|
||||||
|
}
|
||||||
|
case tcell.KeyTab, tcell.KeyRight, tcell.KeyCtrlF:
|
||||||
|
if curr, ok := m.CurrentSuggestion(); ok {
|
||||||
|
c.model.SetText(c.model.GetText() + curr)
|
||||||
|
m.ClearSuggestions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return evt
|
||||||
|
}
|
||||||
|
|
||||||
|
// StylesChanged notifies skin changed.
|
||||||
|
func (c *Prompt) StylesChanged(s *config.Styles) {
|
||||||
|
c.styles = s
|
||||||
|
c.SetBackgroundColor(s.BgColor())
|
||||||
|
c.SetTextColor(s.FgColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
// InCmdMode returns true if command is active, false otherwise.
|
||||||
|
func (c *Prompt) InCmdMode() bool {
|
||||||
|
if c.model == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return c.model.IsActive()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) activate() {
|
||||||
|
c.SetCursorIndex(len(c.model.GetText()))
|
||||||
|
c.write(c.model.GetText(), "")
|
||||||
|
c.model.Notify()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) update(s string) {
|
||||||
|
c.Clear()
|
||||||
|
c.write(s, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) suggest(text, suggestion string) {
|
||||||
|
c.Clear()
|
||||||
|
c.write(text, suggestion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) write(text, suggest string) {
|
||||||
|
c.SetCursorIndex(c.spacer + len(text))
|
||||||
|
txt := text
|
||||||
|
if suggest != "" {
|
||||||
|
txt += "[gray::-]" + suggest
|
||||||
|
}
|
||||||
|
fmt.Fprintf(c, defaultPrompt, c.icon, txt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Event Listener protocol...
|
||||||
|
|
||||||
|
// BufferChanged indicates the buffer was changed.
|
||||||
|
func (c *Prompt) BufferChanged(s string) {
|
||||||
|
c.update(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) SuggestionChanged(text, sugg string) {
|
||||||
|
c.Clear()
|
||||||
|
c.write(text, sugg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BufferActive indicates the buff activity changed.
|
||||||
|
func (c *Prompt) BufferActive(activate bool, kind model.BufferKind) {
|
||||||
|
if activate {
|
||||||
|
c.ShowCursor(true)
|
||||||
|
c.SetBorder(true)
|
||||||
|
c.SetTextColor(c.styles.FgColor())
|
||||||
|
c.SetBorderColor(colorFor(kind))
|
||||||
|
c.icon = c.iconFor(kind)
|
||||||
|
c.activate()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ShowCursor(false)
|
||||||
|
c.SetBorder(false)
|
||||||
|
c.SetBackgroundColor(c.styles.BgColor())
|
||||||
|
c.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Prompt) iconFor(k model.BufferKind) rune {
|
||||||
|
if c.noIcons {
|
||||||
|
return ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
switch k {
|
||||||
|
case model.CommandBuffer:
|
||||||
|
return '🐶'
|
||||||
|
default:
|
||||||
|
return '🐩'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helpers...
|
||||||
|
|
||||||
|
func colorFor(k model.BufferKind) tcell.Color {
|
||||||
|
switch k {
|
||||||
|
case model.CommandBuffer:
|
||||||
|
return tcell.ColorAqua
|
||||||
|
default:
|
||||||
|
return tcell.ColorSeaGreen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,21 +10,22 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCmdNew(t *testing.T) {
|
func TestCmdNew(t *testing.T) {
|
||||||
model := model.NewFishBuff(':', model.Command)
|
v := ui.NewPrompt(true, config.NewStyles())
|
||||||
v := ui.NewCommand(true, config.NewStyles(), model)
|
model := model.NewFishBuff(':', model.CommandBuffer)
|
||||||
|
v.SetModel(model)
|
||||||
model.AddListener(v)
|
model.AddListener(v)
|
||||||
model.Set("blee")
|
model.SetText("blee")
|
||||||
|
|
||||||
assert.Equal(t, "\x00> [::b]blee\n", v.GetText(false))
|
assert.Equal(t, "\x00> [::b]blee\n", v.GetText(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdUpdate(t *testing.T) {
|
func TestCmdUpdate(t *testing.T) {
|
||||||
model := model.NewFishBuff(':', model.Command)
|
model := model.NewFishBuff(':', model.CommandBuffer)
|
||||||
v := ui.NewCommand(true, config.NewStyles(), model)
|
v := ui.NewPrompt(true, config.NewStyles())
|
||||||
|
v.SetModel(model)
|
||||||
|
|
||||||
model.AddListener(v)
|
model.AddListener(v)
|
||||||
model.Set("blee")
|
model.SetText("blee")
|
||||||
model.Add('!')
|
model.Add('!')
|
||||||
|
|
||||||
assert.Equal(t, "\x00> [::b]blee!\n", v.GetText(false))
|
assert.Equal(t, "\x00> [::b]blee!\n", v.GetText(false))
|
||||||
|
|
@ -32,8 +33,9 @@ func TestCmdUpdate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmdMode(t *testing.T) {
|
func TestCmdMode(t *testing.T) {
|
||||||
model := model.NewFishBuff(':', model.Command)
|
model := model.NewFishBuff(':', model.CommandBuffer)
|
||||||
v := ui.NewCommand(true, config.NewStyles(), model)
|
v := ui.NewPrompt(true, config.NewStyles())
|
||||||
|
v.SetModel(model)
|
||||||
model.AddListener(v)
|
model.AddListener(v)
|
||||||
|
|
||||||
for _, f := range []bool{false, true} {
|
for _, f := range []bool{false, true} {
|
||||||
|
|
@ -57,7 +57,7 @@ func NewTable(gvr client.GVR) *Table {
|
||||||
},
|
},
|
||||||
gvr: gvr,
|
gvr: gvr,
|
||||||
actions: make(KeyActions),
|
actions: make(KeyActions),
|
||||||
cmdBuff: model.NewCmdBuff('/', model.Filter),
|
cmdBuff: model.NewCmdBuff('/', model.FilterBuffer),
|
||||||
sortCol: SortColumn{asc: true},
|
sortCol: SortColumn{asc: true},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -148,6 +148,13 @@ func (t *Table) FilterInput(r rune) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Table) Filter(s string) {
|
||||||
|
t.ClearSelection()
|
||||||
|
t.doUpdate(t.filtered(t.GetModel().Peek()))
|
||||||
|
t.UpdateTitle()
|
||||||
|
t.SelectFirstRow()
|
||||||
|
}
|
||||||
|
|
||||||
// Hints returns the view hints.
|
// Hints returns the view hints.
|
||||||
func (t *Table) Hints() model.MenuHints {
|
func (t *Table) Hints() model.MenuHints {
|
||||||
return t.actions.Hints()
|
return t.actions.Hints()
|
||||||
|
|
@ -363,26 +370,26 @@ func (t *Table) filtered(data render.TableData) render.TableData {
|
||||||
if t.toast {
|
if t.toast {
|
||||||
filtered = filterToast(data)
|
filtered = filterToast(data)
|
||||||
}
|
}
|
||||||
if t.cmdBuff.Empty() || IsLabelSelector(t.cmdBuff.String()) {
|
if t.cmdBuff.Empty() || IsLabelSelector(t.cmdBuff.GetText()) {
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
q := t.cmdBuff.String()
|
q := t.cmdBuff.GetText()
|
||||||
if IsFuzzySelector(q) {
|
if IsFuzzySelector(q) {
|
||||||
return fuzzyFilter(q[2:], filtered)
|
return fuzzyFilter(q[2:], filtered)
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered, err := rxFilter(t.cmdBuff.String(), filtered)
|
filtered, err := rxFilter(t.cmdBuff.GetText(), 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.Clear()
|
t.cmdBuff.ClearText()
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchBuff returns the associated command buffer.
|
// CmdBuff returns the associated command buffer.
|
||||||
func (t *Table) SearchBuff() *model.CmdBuff {
|
func (t *Table) CmdBuff() *model.CmdBuff {
|
||||||
return t.cmdBuff
|
return t.cmdBuff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,7 +437,7 @@ func (t *Table) styleTitle() string {
|
||||||
title = SkinTitle(fmt.Sprintf(NSTitleFmt, base, ns, rc), t.styles.Frame())
|
title = SkinTitle(fmt.Sprintf(NSTitleFmt, base, ns, rc), t.styles.Frame())
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := t.cmdBuff.String()
|
buff := t.cmdBuff.GetText()
|
||||||
if buff == "" {
|
if buff == "" {
|
||||||
return title
|
return title
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ func NewTree() *Tree {
|
||||||
TreeView: tview.NewTreeView(),
|
TreeView: tview.NewTreeView(),
|
||||||
expandNodes: true,
|
expandNodes: true,
|
||||||
actions: make(KeyActions),
|
actions: make(KeyActions),
|
||||||
cmdBuff: model.NewCmdBuff('/', model.Filter),
|
cmdBuff: model.NewCmdBuff('/', model.FilterBuffer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,20 +95,7 @@ func (t *Tree) BindKeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tree) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (t *Tree) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
key := evt.Key()
|
if a, ok := t.actions[AsKey(evt)]; ok {
|
||||||
if key == tcell.KeyRune {
|
|
||||||
if t.cmdBuff.IsActive() {
|
|
||||||
t.cmdBuff.Add(evt.Rune())
|
|
||||||
t.ClearSelection()
|
|
||||||
if t.keyListener != nil {
|
|
||||||
t.keyListener()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
key = mapKey(evt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a, ok := t.actions[key]; ok {
|
|
||||||
return a.Action(evt)
|
return a.Action(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,14 +122,3 @@ func (t *Tree) ClearSelection() {
|
||||||
t.selectedItem = ""
|
t.selectedItem = ""
|
||||||
t.SetCurrentNode(nil)
|
t.SetCurrentNode(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Helpers...
|
|
||||||
|
|
||||||
func mapKey(evt *tcell.EventKey) tcell.Key {
|
|
||||||
key := tcell.Key(evt.Rune())
|
|
||||||
if evt.Modifiers() == tcell.ModAlt {
|
|
||||||
key = tcell.Key(int16(evt.Rune()) * int16(evt.Modifiers()))
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func (a *Alias) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.GetTable().SearchBuff().IsActive() {
|
if a.GetTable().CmdBuff().IsActive() {
|
||||||
return a.GetTable().activateCmd(evt)
|
return a.GetTable().activateCmd(evt)
|
||||||
}
|
}
|
||||||
return evt
|
return evt
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,9 @@ func TestAliasSearch(t *testing.T) {
|
||||||
v := view.NewAlias(client.NewGVR("aliases"))
|
v := view.NewAlias(client.NewGVR("aliases"))
|
||||||
assert.Nil(t, v.Init(makeContext()))
|
assert.Nil(t, v.Init(makeContext()))
|
||||||
v.GetTable().SetModel(&testModel{})
|
v.GetTable().SetModel(&testModel{})
|
||||||
v.GetTable().SearchBuff().SetActive(true)
|
v.GetTable().Refresh()
|
||||||
v.GetTable().SearchBuff().Set("dump")
|
v.App().Prompt().SetModel(v.GetTable().CmdBuff())
|
||||||
|
v.App().Prompt().SendStrokes("blee")
|
||||||
v.GetTable().SendKey(tcell.NewEventKey(tcell.KeyRune, 'd', tcell.ModNone))
|
|
||||||
|
|
||||||
assert.Equal(t, 3, v.GetTable().GetColumnCount())
|
assert.Equal(t, 3, v.GetTable().GetColumnCount())
|
||||||
assert.Equal(t, 1, v.GetTable().GetRowCount())
|
assert.Equal(t, 1, v.GetTable().GetRowCount())
|
||||||
|
|
@ -45,11 +44,11 @@ func TestAliasGoto(t *testing.T) {
|
||||||
v.GetTable().Select(0, 0)
|
v.GetTable().Select(0, 0)
|
||||||
|
|
||||||
b := buffL{}
|
b := buffL{}
|
||||||
v.GetTable().SearchBuff().SetActive(true)
|
v.GetTable().CmdBuff().SetActive(true)
|
||||||
v.GetTable().SearchBuff().AddListener(&b)
|
v.GetTable().CmdBuff().AddListener(&b)
|
||||||
v.GetTable().SendKey(tcell.NewEventKey(tcell.KeyEnter, 256, tcell.ModNone))
|
v.GetTable().SendKey(tcell.NewEventKey(tcell.KeyEnter, 256, tcell.ModNone))
|
||||||
|
|
||||||
assert.True(t, v.GetTable().SearchBuff().IsActive())
|
assert.True(t, v.GetTable().CmdBuff().IsActive())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -97,7 +96,13 @@ func (k ks) NamespaceNames(nn []v1.Namespace) []string {
|
||||||
|
|
||||||
type testModel struct{}
|
type testModel struct{}
|
||||||
|
|
||||||
var _ ui.Tabular = &testModel{}
|
var _ ui.Tabular = (*testModel)(nil)
|
||||||
|
var _ ui.Suggester = (*testModel)(nil)
|
||||||
|
|
||||||
|
func (t *testModel) CurrentSuggestion() (string, bool) { return "", false }
|
||||||
|
func (t *testModel) NextSuggestion() (string, bool) { return "", false }
|
||||||
|
func (t *testModel) PrevSuggestion() (string, bool) { return "", false }
|
||||||
|
func (t *testModel) ClearSuggestions() {}
|
||||||
|
|
||||||
func (t *testModel) SetInstance(string) {}
|
func (t *testModel) SetInstance(string) {}
|
||||||
func (t *testModel) Empty() bool { return false }
|
func (t *testModel) Empty() bool { return false }
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ type App struct {
|
||||||
func NewApp(cfg *config.Config) *App {
|
func NewApp(cfg *config.Config) *App {
|
||||||
a := App{
|
a := App{
|
||||||
App: ui.NewApp(cfg, cfg.K9s.CurrentContext),
|
App: ui.NewApp(cfg, cfg.K9s.CurrentContext),
|
||||||
Content: NewPageStack(),
|
|
||||||
history: model.NewHistory(model.MaxHistory),
|
history: model.NewHistory(model.MaxHistory),
|
||||||
|
Content: NewPageStack(),
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Views()["statusIndicator"] = ui.NewStatusIndicator(a.App, a.Styles)
|
a.Views()["statusIndicator"] = ui.NewStatusIndicator(a.App, a.Styles)
|
||||||
|
|
@ -94,14 +94,14 @@ func (a *App) Init(version string, rate int) error {
|
||||||
a.clusterModel.AddListener(a.clusterInfo())
|
a.clusterModel.AddListener(a.clusterInfo())
|
||||||
a.clusterModel.AddListener(a.statusIndicator())
|
a.clusterModel.AddListener(a.statusIndicator())
|
||||||
a.clusterModel.Refresh()
|
a.clusterModel.Refresh()
|
||||||
|
a.clusterInfo().Init()
|
||||||
|
|
||||||
a.command = NewCommand(a)
|
a.command = NewCommand(a)
|
||||||
if err := a.command.Init(); err != nil {
|
if err := a.command.Init(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.CmdBuff().SetSuggestionFn(a.suggestCommand())
|
a.CmdBuff().SetSuggestionFn(a.suggestCommand())
|
||||||
|
a.CmdBuff().AddListener(a)
|
||||||
a.clusterInfo().Init()
|
|
||||||
|
|
||||||
flash := ui.NewFlash(a.App)
|
flash := ui.NewFlash(a.App)
|
||||||
go flash.Watch(ctx, a.Flash().Channel())
|
go flash.Watch(ctx, a.Flash().Channel())
|
||||||
|
|
@ -119,7 +119,7 @@ func (a *App) Init(version string, rate int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) suggestCommand() func(s string) (entries sort.StringSlice) {
|
func (a *App) suggestCommand() model.SuggestionFunc {
|
||||||
return func(s string) (entries sort.StringSlice) {
|
return func(s string) (entries sort.StringSlice) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
if a.history.Empty() {
|
if a.history.Empty() {
|
||||||
|
|
@ -147,16 +147,7 @@ func (a *App) suggestCommand() func(s string) (entries sort.StringSlice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
key := evt.Key()
|
if k, ok := a.HasAction(ui.AsKey(evt)); ok && !a.Content.IsTopDialog() {
|
||||||
if key == tcell.KeyRune {
|
|
||||||
if a.CmdBuff().IsActive() && evt.Modifiers() == tcell.ModNone {
|
|
||||||
a.CmdBuff().Add(evt.Rune())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
key = ui.AsKey(evt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if k, ok := a.HasAction(key); ok && !a.Content.IsTopDialog() {
|
|
||||||
return k.Action(evt)
|
return k.Action(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,7 +422,7 @@ func (a *App) PrevCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) toggleHeaderCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) toggleHeaderCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if a.Cmd().InCmdMode() {
|
if a.Prompt().InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,5 @@ func TestAppNew(t *testing.T) {
|
||||||
a := view.NewApp(config.NewConfig(ks{}))
|
a := view.NewApp(config.NewConfig(ks{}))
|
||||||
a.Init("blee", 10)
|
a.Init("blee", 10)
|
||||||
|
|
||||||
assert.Equal(t, 13, len(a.GetActions()))
|
assert.Equal(t, 9, len(a.GetActions()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,32 +183,28 @@ func (b *Browser) viewCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Browser) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (b *Browser) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if !b.SearchBuff().InCmdMode() {
|
if !b.CmdBuff().InCmdMode() {
|
||||||
b.SearchBuff().Reset()
|
b.CmdBuff().Reset()
|
||||||
return b.App().PrevCmd(evt)
|
return b.App().PrevCmd(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := b.SearchBuff().String()
|
b.CmdBuff().Reset()
|
||||||
b.SearchBuff().Reset()
|
if ui.IsLabelSelector(b.CmdBuff().GetText()) {
|
||||||
|
|
||||||
if ui.IsLabelSelector(cmd) {
|
|
||||||
b.Start()
|
b.Start()
|
||||||
} else {
|
return nil
|
||||||
b.Refresh()
|
|
||||||
}
|
}
|
||||||
|
b.Refresh()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Browser) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (b *Browser) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if !b.SearchBuff().IsActive() {
|
if !b.CmdBuff().IsActive() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
b.SearchBuff().SetActive(false)
|
b.CmdBuff().SetActive(false)
|
||||||
|
if ui.IsLabelSelector(b.CmdBuff().GetText()) {
|
||||||
cmd := b.SearchBuff().String()
|
|
||||||
if ui.IsLabelSelector(cmd) {
|
|
||||||
b.Start()
|
b.Start()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -355,8 +351,8 @@ func (b *Browser) defaultContext() context.Context {
|
||||||
ctx = context.WithValue(ctx, internal.KeyPath, b.Path)
|
ctx = context.WithValue(ctx, internal.KeyPath, b.Path)
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
||||||
if ui.IsLabelSelector(b.SearchBuff().String()) {
|
if ui.IsLabelSelector(b.CmdBuff().GetText()) {
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(b.SearchBuff().String()))
|
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(b.CmdBuff().GetText()))
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, internal.KeyFields, "")
|
ctx = context.WithValue(ctx, internal.KeyFields, "")
|
||||||
ctx = context.WithValue(ctx, internal.KeyNamespace, client.CleanseNamespace(b.App().Config.ActiveNamespace()))
|
ctx = context.WithValue(ctx, internal.KeyNamespace, client.CleanseNamespace(b.App().Config.ActiveNamespace()))
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ func NewDetails(app *App, title, subject string, searchable bool) *Details {
|
||||||
title: title,
|
title: title,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
actions: make(ui.KeyActions),
|
actions: make(ui.KeyActions),
|
||||||
cmdBuff: model.NewCmdBuff('/', model.Filter),
|
cmdBuff: model.NewCmdBuff('/', model.FilterBuffer),
|
||||||
model: model.NewText(),
|
model: model.NewText(),
|
||||||
searchable: searchable,
|
searchable: searchable,
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +63,7 @@ func (d *Details) Init(_ context.Context) error {
|
||||||
d.app.Styles.AddListener(d)
|
d.app.Styles.AddListener(d)
|
||||||
d.StylesChanged(d.app.Styles)
|
d.StylesChanged(d.app.Styles)
|
||||||
|
|
||||||
d.cmdBuff.AddListener(d.app.Cmd())
|
d.app.Prompt().SetModel(d.cmdBuff)
|
||||||
d.cmdBuff.AddListener(d)
|
d.cmdBuff.AddListener(d)
|
||||||
|
|
||||||
d.bindKeys()
|
d.bindKeys()
|
||||||
|
|
@ -100,7 +100,10 @@ func (d *Details) TextFiltered(lines []string, matches fuzzy.Matches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (d *Details) BufferChanged(s string) {}
|
func (d *Details) BufferChanged(s string) {
|
||||||
|
d.model.Filter(s)
|
||||||
|
d.updateTitle()
|
||||||
|
}
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
// BufferActive indicates the buff activity changed.
|
||||||
func (d *Details) BufferActive(state bool, k model.BufferKind) {
|
func (d *Details) BufferActive(state bool, k model.BufferKind) {
|
||||||
|
|
@ -109,18 +112,14 @@ func (d *Details) BufferActive(state bool, k model.BufferKind) {
|
||||||
|
|
||||||
func (d *Details) bindKeys() {
|
func (d *Details) bindKeys() {
|
||||||
d.actions.Set(ui.KeyActions{
|
d.actions.Set(ui.KeyActions{
|
||||||
tcell.KeyEnter: ui.NewSharedKeyAction("Filter", d.filterCmd, false),
|
tcell.KeyEnter: ui.NewSharedKeyAction("Filter", d.filterCmd, false),
|
||||||
tcell.KeyEscape: ui.NewKeyAction("Back", d.resetCmd, false),
|
tcell.KeyEscape: ui.NewKeyAction("Back", d.resetCmd, false),
|
||||||
tcell.KeyCtrlS: ui.NewKeyAction("Save", d.saveCmd, false),
|
tcell.KeyCtrlS: ui.NewKeyAction("Save", d.saveCmd, false),
|
||||||
ui.KeyC: ui.NewKeyAction("Copy", d.cpCmd, true),
|
ui.KeyC: ui.NewKeyAction("Copy", d.cpCmd, true),
|
||||||
ui.KeyN: ui.NewKeyAction("Next Match", d.nextCmd, true),
|
ui.KeyN: ui.NewKeyAction("Next Match", d.nextCmd, true),
|
||||||
ui.KeyShiftN: ui.NewKeyAction("Prev Match", d.prevCmd, true),
|
ui.KeyShiftN: ui.NewKeyAction("Prev Match", d.prevCmd, true),
|
||||||
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", d.activateCmd, false),
|
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", d.activateCmd, false),
|
||||||
tcell.KeyCtrlU: ui.NewSharedKeyAction("Clear Filter", d.clearCmd, false),
|
tcell.KeyDelete: ui.NewSharedKeyAction("Erase", d.eraseCmd, false),
|
||||||
tcell.KeyCtrlW: ui.NewSharedKeyAction("Clear Filter", d.clearCmd, false),
|
|
||||||
tcell.KeyBackspace2: ui.NewSharedKeyAction("Erase", d.eraseCmd, false),
|
|
||||||
tcell.KeyBackspace: ui.NewSharedKeyAction("Erase", d.eraseCmd, false),
|
|
||||||
tcell.KeyDelete: ui.NewSharedKeyAction("Erase", d.eraseCmd, false),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if !d.searchable {
|
if !d.searchable {
|
||||||
|
|
@ -129,35 +128,13 @@ func (d *Details) bindKeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Details) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (d *Details) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
key := evt.Key()
|
if a, ok := d.actions[ui.AsKey(evt)]; ok {
|
||||||
if key == tcell.KeyUp || key == tcell.KeyDown {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
|
|
||||||
if key == tcell.KeyRune {
|
|
||||||
if d.filterInput(evt.Rune()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
key = ui.AsKey(evt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a, ok := d.actions[key]; ok {
|
|
||||||
return a.Action(evt)
|
return a.Action(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Details) filterInput(r rune) bool {
|
|
||||||
if !d.cmdBuff.IsActive() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
d.cmdBuff.Add(r)
|
|
||||||
d.updateTitle()
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// StylesChanged notifies the skin changed.
|
// StylesChanged notifies the skin changed.
|
||||||
func (d *Details) StylesChanged(s *config.Styles) {
|
func (d *Details) StylesChanged(s *config.Styles) {
|
||||||
d.SetBackgroundColor(d.app.Styles.BgColor())
|
d.SetBackgroundColor(d.app.Styles.BgColor())
|
||||||
|
|
@ -236,7 +213,7 @@ func (d *Details) prevCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Details) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (d *Details) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
d.model.Filter(d.cmdBuff.String())
|
d.model.Filter(d.cmdBuff.GetText())
|
||||||
d.cmdBuff.SetActive(false)
|
d.cmdBuff.SetActive(false)
|
||||||
d.updateTitle()
|
d.updateTitle()
|
||||||
|
|
||||||
|
|
@ -247,16 +224,7 @@ func (d *Details) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if d.app.InCmdMode() {
|
if d.app.InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
d.cmdBuff.SetActive(true)
|
d.app.ResetPrompt(d.cmdBuff)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Details) clearCmd(*tcell.EventKey) *tcell.EventKey {
|
|
||||||
if !d.app.InCmdMode() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
d.cmdBuff.Clear()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +244,7 @@ func (d *Details) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return d.app.PrevCmd(evt)
|
return d.app.PrevCmd(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.cmdBuff.String() != "" {
|
if d.cmdBuff.GetText() != "" {
|
||||||
d.model.ClearFilter()
|
d.model.ClearFilter()
|
||||||
}
|
}
|
||||||
d.cmdBuff.SetActive(false)
|
d.cmdBuff.SetActive(false)
|
||||||
|
|
@ -311,16 +279,15 @@ func (d *Details) updateTitle() {
|
||||||
}
|
}
|
||||||
fmat := fmt.Sprintf(detailsTitleFmt, d.title, d.subject)
|
fmat := fmt.Sprintf(detailsTitleFmt, d.title, d.subject)
|
||||||
|
|
||||||
buff := d.cmdBuff.String()
|
buff := d.cmdBuff.GetText()
|
||||||
if buff == "" {
|
if buff == "" {
|
||||||
d.SetTitle(ui.SkinTitle(fmat, d.app.Styles.Frame()))
|
d.SetTitle(ui.SkinTitle(fmat, d.app.Styles.Frame()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
search := d.cmdBuff.String()
|
|
||||||
if d.maxRegions != 0 {
|
if d.maxRegions != 0 {
|
||||||
search += fmt.Sprintf("[%d:%d]", d.currentRegion+1, d.maxRegions)
|
buff += fmt.Sprintf("[%d:%d]", d.currentRegion+1, d.maxRegions)
|
||||||
}
|
}
|
||||||
fmat += fmt.Sprintf(ui.SearchFmt, search)
|
fmat += fmt.Sprintf(ui.SearchFmt, buff)
|
||||||
d.SetTitle(ui.SkinTitle(fmat, d.app.Styles.Frame()))
|
d.SetTitle(ui.SkinTitle(fmat, d.app.Styles.Frame()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ func (h *Help) Init(ctx context.Context) error {
|
||||||
func (h *Help) bindKeys() {
|
func (h *Help) bindKeys() {
|
||||||
h.Actions().Delete(ui.KeySpace, tcell.KeyCtrlSpace, tcell.KeyCtrlS)
|
h.Actions().Delete(ui.KeySpace, tcell.KeyCtrlSpace, tcell.KeyCtrlS)
|
||||||
h.Actions().Set(ui.KeyActions{
|
h.Actions().Set(ui.KeyActions{
|
||||||
tcell.KeyEsc: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
tcell.KeyEscape: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
||||||
ui.KeyHelp: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
ui.KeyHelp: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
||||||
tcell.KeyEnter: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
tcell.KeyEnter: ui.NewKeyAction("Back", h.app.PrevCmd, false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ func (l *Log) LogChanged(lines dao.LogItems) {
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (l *Log) BufferChanged(s string) {
|
func (l *Log) BufferChanged(s string) {
|
||||||
if err := l.model.Filter(l.logs.cmdBuff.String()); err != nil {
|
if err := l.model.Filter(l.logs.cmdBuff.GetText()); err != nil {
|
||||||
l.app.Flash().Err(err)
|
l.app.Flash().Err(err)
|
||||||
}
|
}
|
||||||
l.updateTitle()
|
l.updateTitle()
|
||||||
|
|
@ -167,7 +167,7 @@ func (l *Log) Stop() {
|
||||||
l.model.RemoveListener(l)
|
l.model.RemoveListener(l)
|
||||||
l.app.Styles.RemoveListener(l)
|
l.app.Styles.RemoveListener(l)
|
||||||
l.logs.cmdBuff.RemoveListener(l)
|
l.logs.cmdBuff.RemoveListener(l)
|
||||||
l.logs.cmdBuff.RemoveListener(l.app.Cmd())
|
l.logs.cmdBuff.RemoveListener(l.app.Prompt())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the component name.
|
// Name returns the component name.
|
||||||
|
|
@ -193,9 +193,7 @@ func (l *Log) bindKeys() {
|
||||||
|
|
||||||
// SendStrokes (testing only!)
|
// SendStrokes (testing only!)
|
||||||
func (l *Log) SendStrokes(s string) {
|
func (l *Log) SendStrokes(s string) {
|
||||||
for _, r := range s {
|
l.app.Prompt().SendStrokes(s)
|
||||||
l.logs.keyboard(tcell.NewEventKey(tcell.KeyRune, r, tcell.ModNone))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendKeys (testing only!)
|
// SendKeys (testing only!)
|
||||||
|
|
@ -226,7 +224,7 @@ func (l *Log) updateTitle() {
|
||||||
title = ui.SkinTitle(fmt.Sprintf(logCoFmt, path, co, since), l.app.Styles.Frame())
|
title = ui.SkinTitle(fmt.Sprintf(logCoFmt, path, co, since), l.app.Styles.Frame())
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := l.logs.cmdBuff.String()
|
buff := l.logs.cmdBuff.GetText()
|
||||||
if buff != "" {
|
if buff != "" {
|
||||||
title += ui.SkinTitle(fmt.Sprintf(ui.SearchFmt, buff), l.app.Styles.Frame())
|
title += ui.SkinTitle(fmt.Sprintf(ui.SearchFmt, buff), l.app.Styles.Frame())
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +268,7 @@ func (l *Log) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
l.logs.cmdBuff.SetActive(false)
|
l.logs.cmdBuff.SetActive(false)
|
||||||
if err := l.model.Filter(l.logs.cmdBuff.String()); err != nil {
|
if err := l.model.Filter(l.logs.cmdBuff.GetText()); err != nil {
|
||||||
l.app.Flash().Err(err)
|
l.app.Flash().Err(err)
|
||||||
}
|
}
|
||||||
l.updateTitle()
|
l.updateTitle()
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ func (p *PortForward) runBenchmark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PortForward) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (p *PortForward) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if !p.GetTable().SearchBuff().Empty() {
|
if !p.GetTable().CmdBuff().Empty() {
|
||||||
p.GetTable().SearchBuff().Reset()
|
p.GetTable().CmdBuff().Reset()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,14 +97,9 @@ func (s *Sanitizer) SetInstance(string) {}
|
||||||
|
|
||||||
func (s *Sanitizer) bindKeys() {
|
func (s *Sanitizer) bindKeys() {
|
||||||
s.Actions().Add(ui.KeyActions{
|
s.Actions().Add(ui.KeyActions{
|
||||||
tcell.KeyEnter: ui.NewKeyAction("Goto", s.gotoCmd, true),
|
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", s.activateCmd, false),
|
||||||
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", s.activateCmd, false),
|
tcell.KeyEscape: ui.NewSharedKeyAction("Filter Reset", s.resetCmd, false),
|
||||||
tcell.KeyBackspace2: ui.NewSharedKeyAction("Erase", s.eraseCmd, false),
|
tcell.KeyEnter: ui.NewKeyAction("Goto", s.gotoCmd, true),
|
||||||
tcell.KeyBackspace: ui.NewSharedKeyAction("Erase", s.eraseCmd, false),
|
|
||||||
tcell.KeyDelete: ui.NewSharedKeyAction("Erase", s.eraseCmd, false),
|
|
||||||
tcell.KeyCtrlU: ui.NewSharedKeyAction("Clear Filter", s.clearCmd, false),
|
|
||||||
tcell.KeyCtrlW: ui.NewSharedKeyAction("Clear Filter", s.clearCmd, false),
|
|
||||||
tcell.KeyEscape: ui.NewSharedKeyAction("Filter Reset", s.resetCmd, false),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,8 +108,7 @@ func (s *Sanitizer) keyEntered() {
|
||||||
s.update(s.filter(s.model.Peek()))
|
s.update(s.filter(s.model.Peek()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sanitizer) refreshActions() {
|
func (s *Sanitizer) refreshActions() {}
|
||||||
}
|
|
||||||
|
|
||||||
// GetSelectedPath returns the current selection as string.
|
// GetSelectedPath returns the current selection as string.
|
||||||
func (s *Sanitizer) GetSelectedPath() string {
|
func (s *Sanitizer) GetSelectedPath() string {
|
||||||
|
|
@ -153,7 +147,7 @@ func (s *Sanitizer) k9sEnv() Env {
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
env["FILTER"] = s.CmdBuff().String()
|
env["FILTER"] = s.CmdBuff().GetText()
|
||||||
if env["FILTER"] == "" {
|
if env["FILTER"] == "" {
|
||||||
ns, n := client.Namespaced(spec.Path())
|
ns, n := client.Namespaced(spec.Path())
|
||||||
env["NAMESPACE"], env["FILTER"] = ns, n
|
env["NAMESPACE"], env["FILTER"] = ns, n
|
||||||
|
|
@ -182,27 +176,7 @@ func (s *Sanitizer) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if s.app.InCmdMode() {
|
if s.app.InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
s.CmdBuff().SetActive(true)
|
s.app.ResetPrompt(s.CmdBuff())
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sanitizer) clearCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if !s.CmdBuff().IsActive() {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
s.CmdBuff().Clear()
|
|
||||||
s.model.ClearFilter()
|
|
||||||
s.Start()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sanitizer) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if s.CmdBuff().IsActive() {
|
|
||||||
s.CmdBuff().Delete()
|
|
||||||
}
|
|
||||||
s.UpdateTitle()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +195,7 @@ func (s *Sanitizer) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
func (s *Sanitizer) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (s *Sanitizer) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if s.CmdBuff().IsActive() {
|
if s.CmdBuff().IsActive() {
|
||||||
if ui.IsLabelSelector(s.CmdBuff().String()) {
|
if ui.IsLabelSelector(s.CmdBuff().GetText()) {
|
||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
s.CmdBuff().SetActive(false)
|
s.CmdBuff().SetActive(false)
|
||||||
|
|
@ -251,7 +225,7 @@ func (s *Sanitizer) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sanitizer) filter(root *xray.TreeNode) *xray.TreeNode {
|
func (s *Sanitizer) filter(root *xray.TreeNode) *xray.TreeNode {
|
||||||
q := s.CmdBuff().String()
|
q := s.CmdBuff().GetText()
|
||||||
if s.CmdBuff().Empty() || ui.IsLabelSelector(q) {
|
if s.CmdBuff().Empty() || ui.IsLabelSelector(q) {
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
@ -338,11 +312,12 @@ func (s *Sanitizer) hydrate(parent *tview.TreeNode, n *xray.TreeNode) {
|
||||||
func (s *Sanitizer) SetEnvFn(EnvFunc) {}
|
func (s *Sanitizer) SetEnvFn(EnvFunc) {}
|
||||||
|
|
||||||
// Refresh updates the view
|
// Refresh updates the view
|
||||||
func (s *Sanitizer) Refresh() {
|
func (s *Sanitizer) Refresh() {}
|
||||||
}
|
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (s *Sanitizer) BufferChanged(t string) {}
|
func (s *Sanitizer) BufferChanged(q string) {
|
||||||
|
s.update(s.filter(s.model.Peek()))
|
||||||
|
}
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
// BufferActive indicates the buff activity changed.
|
||||||
func (s *Sanitizer) BufferActive(state bool, k model.BufferKind) {
|
func (s *Sanitizer) BufferActive(state bool, k model.BufferKind) {
|
||||||
|
|
@ -355,7 +330,7 @@ func (s *Sanitizer) defaultContext() context.Context {
|
||||||
if s.CmdBuff().Empty() {
|
if s.CmdBuff().Empty() {
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
||||||
} else {
|
} else {
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(s.CmdBuff().String()))
|
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(s.CmdBuff().GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
@ -364,8 +339,6 @@ func (s *Sanitizer) defaultContext() context.Context {
|
||||||
// Start initializes resource watch loop.
|
// Start initializes resource watch loop.
|
||||||
func (s *Sanitizer) Start() {
|
func (s *Sanitizer) Start() {
|
||||||
s.Stop()
|
s.Stop()
|
||||||
|
|
||||||
s.CmdBuff().AddListener(s.app.Cmd())
|
|
||||||
s.CmdBuff().AddListener(s)
|
s.CmdBuff().AddListener(s)
|
||||||
|
|
||||||
ctx := s.defaultContext()
|
ctx := s.defaultContext()
|
||||||
|
|
@ -384,8 +357,6 @@ func (s *Sanitizer) Stop() {
|
||||||
}
|
}
|
||||||
s.cancelFn()
|
s.cancelFn()
|
||||||
s.cancelFn = nil
|
s.cancelFn = nil
|
||||||
|
|
||||||
s.CmdBuff().RemoveListener(s.app.Cmd())
|
|
||||||
s.CmdBuff().RemoveListener(s)
|
s.CmdBuff().RemoveListener(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,17 +397,17 @@ func (s *Sanitizer) styleTitle() string {
|
||||||
ns = client.NamespaceAll
|
ns = client.NamespaceAll
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := s.CmdBuff().String()
|
|
||||||
var title string
|
var title string
|
||||||
if ns == client.ClusterScope {
|
if ns == client.ClusterScope {
|
||||||
title = ui.SkinTitle(fmt.Sprintf(ui.TitleFmt, base, s.Count), s.app.Styles.Frame())
|
title = ui.SkinTitle(fmt.Sprintf(ui.TitleFmt, base, s.Count), s.app.Styles.Frame())
|
||||||
} else {
|
} else {
|
||||||
title = ui.SkinTitle(fmt.Sprintf(ui.NSTitleFmt, base, ns, s.Count), s.app.Styles.Frame())
|
title = ui.SkinTitle(fmt.Sprintf(ui.NSTitleFmt, base, ns, s.Count), s.app.Styles.Frame())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buff := s.CmdBuff().GetText()
|
||||||
if buff == "" {
|
if buff == "" {
|
||||||
return title
|
return title
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.IsLabelSelector(buff) {
|
if ui.IsLabelSelector(buff) {
|
||||||
buff = ui.TrimLabelSelector(buff)
|
buff = ui.TrimLabelSelector(buff)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,14 @@ func (t *Table) Init(ctx context.Context) (err error) {
|
||||||
t.SetInputCapture(t.keyboard)
|
t.SetInputCapture(t.keyboard)
|
||||||
t.bindKeys()
|
t.bindKeys()
|
||||||
t.GetModel().SetRefreshRate(time.Duration(t.app.Config.K9s.GetRefreshRate()) * time.Second)
|
t.GetModel().SetRefreshRate(time.Duration(t.app.Config.K9s.GetRefreshRate()) * time.Second)
|
||||||
|
t.CmdBuff().AddListener(t)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendKey sends an keyboard event (testing only!).
|
// SendKey sends an keyboard event (testing only!).
|
||||||
func (t *Table) SendKey(evt *tcell.EventKey) {
|
func (t *Table) SendKey(evt *tcell.EventKey) {
|
||||||
t.keyboard(evt)
|
t.app.Prompt().SendKey(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (t *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
@ -62,14 +63,7 @@ func (t *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == tcell.KeyRune {
|
if a, ok := t.Actions()[ui.AsKey(evt)]; ok && !t.app.Content.IsTopDialog() {
|
||||||
if t.FilterInput(evt.Rune()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
key = ui.AsKey(evt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a, ok := t.Actions()[key]; ok && !t.app.Content.IsTopDialog() {
|
|
||||||
return a.Action(evt)
|
return a.Action(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +91,7 @@ func (t *Table) defaultEnv() Env {
|
||||||
log.Error().Msgf("unable to locate selected row for %q", path)
|
log.Error().Msgf("unable to locate selected row for %q", path)
|
||||||
}
|
}
|
||||||
env := defaultEnv(t.app.Conn().Config(), path, t.GetModel().Peek().Header, row)
|
env := defaultEnv(t.app.Conn().Config(), path, t.GetModel().Peek().Header, row)
|
||||||
env["FILTER"] = t.SearchBuff().String()
|
env["FILTER"] = t.CmdBuff().GetText()
|
||||||
if env["FILTER"] == "" {
|
if env["FILTER"] == "" {
|
||||||
env["NAMESPACE"], env["FILTER"] = client.Namespaced(path)
|
env["NAMESPACE"], env["FILTER"] = client.Namespaced(path)
|
||||||
}
|
}
|
||||||
|
|
@ -113,15 +107,13 @@ func (t *Table) App() *App {
|
||||||
// Start runs the component.
|
// Start runs the component.
|
||||||
func (t *Table) Start() {
|
func (t *Table) Start() {
|
||||||
t.Stop()
|
t.Stop()
|
||||||
t.SearchBuff().AddListener(t.app.Cmd())
|
t.CmdBuff().AddListener(t)
|
||||||
t.SearchBuff().AddListener(t)
|
|
||||||
t.Styles().AddListener(t.Table)
|
t.Styles().AddListener(t.Table)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop terminates the component.
|
// Stop terminates the component.
|
||||||
func (t *Table) Stop() {
|
func (t *Table) Stop() {
|
||||||
t.SearchBuff().RemoveListener(t.app.Cmd())
|
t.CmdBuff().RemoveListener(t)
|
||||||
t.SearchBuff().RemoveListener(t)
|
|
||||||
t.Styles().RemoveListener(t.Table)
|
t.Styles().RemoveListener(t.Table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,11 +126,16 @@ func (t *Table) SetEnterFn(f EnterFunc) {
|
||||||
func (t *Table) SetExtraActionsFn(BoostActionsFunc) {}
|
func (t *Table) SetExtraActionsFn(BoostActionsFunc) {}
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (t *Table) BufferChanged(s string) {}
|
func (t *Table) BufferChanged(s string) {
|
||||||
|
t.Filter(s)
|
||||||
|
}
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
// BufferActive indicates the buff activity changed.
|
||||||
func (t *Table) BufferActive(state bool, k model.BufferKind) {
|
func (t *Table) BufferActive(state bool, k model.BufferKind) {
|
||||||
t.app.BufferActive(state, k)
|
t.app.BufferActive(state, k)
|
||||||
|
if !state {
|
||||||
|
t.app.SetFocus(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (t *Table) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
@ -153,18 +150,14 @@ func (t *Table) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
func (t *Table) bindKeys() {
|
func (t *Table) bindKeys() {
|
||||||
t.Actions().Add(ui.KeyActions{
|
t.Actions().Add(ui.KeyActions{
|
||||||
ui.KeySpace: ui.NewSharedKeyAction("Mark", t.markCmd, false),
|
ui.KeySpace: ui.NewSharedKeyAction("Mark", t.markCmd, false),
|
||||||
tcell.KeyCtrlSpace: ui.NewSharedKeyAction("Marks Clear", t.clearMarksCmd, false),
|
tcell.KeyCtrlSpace: ui.NewSharedKeyAction("Marks Clear", t.clearMarksCmd, false),
|
||||||
tcell.KeyCtrlS: ui.NewSharedKeyAction("Save", t.saveCmd, false),
|
tcell.KeyCtrlS: ui.NewSharedKeyAction("Save", t.saveCmd, false),
|
||||||
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", t.activateCmd, false),
|
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", t.activateCmd, false),
|
||||||
tcell.KeyCtrlU: ui.NewSharedKeyAction("Clear Filter", t.clearCmd, false),
|
tcell.KeyCtrlZ: ui.NewKeyAction("Toggle Faults", t.toggleFaultCmd, false),
|
||||||
tcell.KeyBackspace2: ui.NewSharedKeyAction("Erase", t.eraseCmd, false),
|
tcell.KeyCtrlW: ui.NewKeyAction("Show Wide", t.toggleWideCmd, false),
|
||||||
tcell.KeyBackspace: ui.NewSharedKeyAction("Erase", t.eraseCmd, false),
|
ui.KeyShiftN: ui.NewKeyAction("Sort Name", t.SortColCmd(nameCol, true), false),
|
||||||
tcell.KeyDelete: ui.NewSharedKeyAction("Erase", t.eraseCmd, false),
|
ui.KeyShiftA: ui.NewKeyAction("Sort Age", t.SortColCmd(ageCol, true), false),
|
||||||
tcell.KeyCtrlZ: ui.NewKeyAction("Toggle Faults", t.toggleFaultCmd, false),
|
|
||||||
tcell.KeyCtrlW: ui.NewKeyAction("Show Wide", t.toggleWideCmd, false),
|
|
||||||
ui.KeyShiftN: ui.NewKeyAction("Sort Name", t.SortColCmd(nameCol, true), false),
|
|
||||||
ui.KeyShiftA: ui.NewKeyAction("Sort Age", t.SortColCmd(ageCol, true), false),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,28 +210,11 @@ func (t *Table) clearMarksCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) clearCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if !t.SearchBuff().IsActive() {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
t.SearchBuff().Clear()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if t.SearchBuff().IsActive() {
|
|
||||||
t.SearchBuff().Delete()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (t *Table) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if t.app.InCmdMode() {
|
if t.app.InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
t.SearchBuff().SetActive(true)
|
t.App().ResetPrompt(t.CmdBuff())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ func TestTableViewFilter(t *testing.T) {
|
||||||
v := NewTable(client.NewGVR("test"))
|
v := NewTable(client.NewGVR("test"))
|
||||||
v.Init(makeContext())
|
v.Init(makeContext())
|
||||||
v.SetModel(&testTableModel{})
|
v.SetModel(&testTableModel{})
|
||||||
v.SearchBuff().SetActive(true)
|
v.CmdBuff().SetActive(true)
|
||||||
v.SearchBuff().Set("blee")
|
v.CmdBuff().SetText("blee")
|
||||||
v.Refresh()
|
v.Refresh()
|
||||||
assert.Equal(t, 1, v.GetRowCount())
|
assert.Equal(t, 1, v.GetRowCount())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,14 +105,9 @@ func (x *Xray) SetInstance(string) {}
|
||||||
|
|
||||||
func (x *Xray) bindKeys() {
|
func (x *Xray) bindKeys() {
|
||||||
x.Actions().Add(ui.KeyActions{
|
x.Actions().Add(ui.KeyActions{
|
||||||
tcell.KeyEnter: ui.NewKeyAction("Goto", x.gotoCmd, true),
|
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", x.activateCmd, false),
|
||||||
ui.KeySlash: ui.NewSharedKeyAction("Filter Mode", x.activateCmd, false),
|
tcell.KeyEscape: ui.NewSharedKeyAction("Filter Reset", x.resetCmd, false),
|
||||||
tcell.KeyBackspace2: ui.NewSharedKeyAction("Erase", x.eraseCmd, false),
|
tcell.KeyEnter: ui.NewKeyAction("Goto", x.gotoCmd, true),
|
||||||
tcell.KeyBackspace: ui.NewSharedKeyAction("Erase", x.eraseCmd, false),
|
|
||||||
tcell.KeyDelete: ui.NewSharedKeyAction("Erase", x.eraseCmd, false),
|
|
||||||
tcell.KeyCtrlU: ui.NewSharedKeyAction("Clear Filter", x.clearCmd, false),
|
|
||||||
tcell.KeyCtrlW: ui.NewSharedKeyAction("Clear Filter", x.clearCmd, false),
|
|
||||||
tcell.KeyEscape: ui.NewSharedKeyAction("Filter Reset", x.resetCmd, false),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +209,7 @@ func (x *Xray) k9sEnv() Env {
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
env["FILTER"] = x.CmdBuff().String()
|
env["FILTER"] = x.CmdBuff().GetText()
|
||||||
if env["FILTER"] == "" {
|
if env["FILTER"] == "" {
|
||||||
ns, n := client.Namespaced(spec.Path())
|
ns, n := client.Namespaced(spec.Path())
|
||||||
env["NAMESPACE"], env["FILTER"] = ns, n
|
env["NAMESPACE"], env["FILTER"] = ns, n
|
||||||
|
|
@ -418,27 +413,7 @@ func (x *Xray) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if x.app.InCmdMode() {
|
if x.app.InCmdMode() {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
x.CmdBuff().SetActive(true)
|
x.app.ResetPrompt(x.CmdBuff())
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Xray) clearCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if !x.CmdBuff().IsActive() {
|
|
||||||
return evt
|
|
||||||
}
|
|
||||||
x.CmdBuff().Clear()
|
|
||||||
x.model.ClearFilter()
|
|
||||||
x.Start()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Xray) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|
||||||
if x.CmdBuff().IsActive() {
|
|
||||||
x.CmdBuff().Delete()
|
|
||||||
}
|
|
||||||
x.UpdateTitle()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +432,7 @@ func (x *Xray) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
func (x *Xray) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (x *Xray) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if x.CmdBuff().IsActive() {
|
if x.CmdBuff().IsActive() {
|
||||||
if ui.IsLabelSelector(x.CmdBuff().String()) {
|
if ui.IsLabelSelector(x.CmdBuff().GetText()) {
|
||||||
x.Start()
|
x.Start()
|
||||||
}
|
}
|
||||||
x.CmdBuff().SetActive(false)
|
x.CmdBuff().SetActive(false)
|
||||||
|
|
@ -481,7 +456,7 @@ func (x *Xray) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Xray) filter(root *xray.TreeNode) *xray.TreeNode {
|
func (x *Xray) filter(root *xray.TreeNode) *xray.TreeNode {
|
||||||
q := x.CmdBuff().String()
|
q := x.CmdBuff().GetText()
|
||||||
if x.CmdBuff().Empty() || ui.IsLabelSelector(q) {
|
if x.CmdBuff().Empty() || ui.IsLabelSelector(q) {
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
@ -568,11 +543,12 @@ func (x *Xray) hydrate(parent *tview.TreeNode, n *xray.TreeNode) {
|
||||||
func (x *Xray) SetEnvFn(EnvFunc) {}
|
func (x *Xray) SetEnvFn(EnvFunc) {}
|
||||||
|
|
||||||
// Refresh updates the view
|
// Refresh updates the view
|
||||||
func (x *Xray) Refresh() {
|
func (x *Xray) Refresh() {}
|
||||||
}
|
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (x *Xray) BufferChanged(s string) {}
|
func (x *Xray) BufferChanged(s string) {
|
||||||
|
x.update(x.filter(x.model.Peek()))
|
||||||
|
}
|
||||||
|
|
||||||
// BufferActive indicates the buff activity changed.
|
// BufferActive indicates the buff activity changed.
|
||||||
func (x *Xray) BufferActive(state bool, k model.BufferKind) {
|
func (x *Xray) BufferActive(state bool, k model.BufferKind) {
|
||||||
|
|
@ -585,7 +561,7 @@ func (x *Xray) defaultContext() context.Context {
|
||||||
if x.CmdBuff().Empty() {
|
if x.CmdBuff().Empty() {
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
ctx = context.WithValue(ctx, internal.KeyLabels, "")
|
||||||
} else {
|
} else {
|
||||||
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(x.CmdBuff().String()))
|
ctx = context.WithValue(ctx, internal.KeyLabels, ui.TrimLabelSelector(x.CmdBuff().GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
@ -594,8 +570,6 @@ func (x *Xray) defaultContext() context.Context {
|
||||||
// Start initializes resource watch loop.
|
// Start initializes resource watch loop.
|
||||||
func (x *Xray) Start() {
|
func (x *Xray) Start() {
|
||||||
x.Stop()
|
x.Stop()
|
||||||
|
|
||||||
x.CmdBuff().AddListener(x.app.Cmd())
|
|
||||||
x.CmdBuff().AddListener(x)
|
x.CmdBuff().AddListener(x)
|
||||||
|
|
||||||
ctx := x.defaultContext()
|
ctx := x.defaultContext()
|
||||||
|
|
@ -611,8 +585,6 @@ func (x *Xray) Stop() {
|
||||||
}
|
}
|
||||||
x.cancelFn()
|
x.cancelFn()
|
||||||
x.cancelFn = nil
|
x.cancelFn = nil
|
||||||
|
|
||||||
x.CmdBuff().RemoveListener(x.app.Cmd())
|
|
||||||
x.CmdBuff().RemoveListener(x)
|
x.CmdBuff().RemoveListener(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -651,17 +623,17 @@ func (x *Xray) styleTitle() string {
|
||||||
ns = client.NamespaceAll
|
ns = client.NamespaceAll
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := x.CmdBuff().String()
|
|
||||||
var title string
|
var title string
|
||||||
if ns == client.ClusterScope {
|
if ns == client.ClusterScope {
|
||||||
title = ui.SkinTitle(fmt.Sprintf(ui.TitleFmt, base, x.Count), x.app.Styles.Frame())
|
title = ui.SkinTitle(fmt.Sprintf(ui.TitleFmt, base, x.Count), x.app.Styles.Frame())
|
||||||
} else {
|
} else {
|
||||||
title = ui.SkinTitle(fmt.Sprintf(ui.NSTitleFmt, base, ns, x.Count), x.app.Styles.Frame())
|
title = ui.SkinTitle(fmt.Sprintf(ui.NSTitleFmt, base, ns, x.Count), x.app.Styles.Frame())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buff := x.CmdBuff().GetText()
|
||||||
if buff == "" {
|
if buff == "" {
|
||||||
return title
|
return title
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.IsLabelSelector(buff) {
|
if ui.IsLabelSelector(buff) {
|
||||||
buff = ui.TrimLabelSelector(buff)
|
buff = ui.TrimLabelSelector(buff)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue