clean up + fix toast skinner

mine
derailed 2019-12-30 15:08:42 -07:00
parent b536767a1f
commit 60cb53b8c2
38 changed files with 104 additions and 46 deletions

View File

@ -7,6 +7,7 @@ import (
"k8s.io/kubectl/pkg/describe/versioned" "k8s.io/kubectl/pkg/describe/versioned"
) )
// Describe describes a resource.
func Describe(c client.Connection, gvr client.GVR, ns, n string) (string, error) { func Describe(c client.Connection, gvr client.GVR, ns, n string) (string, error) {
mapper := RestMapper{Connection: c} mapper := RestMapper{Connection: c}
m, err := mapper.ToRESTMapper() m, err := mapper.ToRESTMapper()

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubectl/pkg/polymorphichelpers" "k8s.io/kubectl/pkg/polymorphichelpers"
) )
// DaemonSet represents a K8s daemonset.
type DaemonSet struct { type DaemonSet struct {
Generic Generic
} }

View File

@ -14,8 +14,8 @@ type Generic struct {
} }
// Init initializes the resource. // Init initializes the resource.
func (r *Generic) Init(f Factory, gvr client.GVR) { func (g *Generic) Init(f Factory, gvr client.GVR) {
r.Factory, r.gvr = f, gvr g.Factory, g.gvr = f, gvr
} }
// Delete a Generic. // Delete a Generic.

View File

@ -64,7 +64,7 @@ func (p *Pod) Containers(path string, includeInit bool) ([]string, error) {
return cc, nil return cc, nil
} }
// Logs tails a given container logs // TailLogs tails a given container logs
func (p *Pod) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error { func (p *Pod) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error {
if !opts.HasContainer() { if !opts.HasContainer() {
return p.logs(ctx, c, opts) return p.logs(ctx, c, opts)
@ -72,7 +72,6 @@ func (p *Pod) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) er
return tailLogs(ctx, p, c, opts) return tailLogs(ctx, p, c, opts)
} }
// PodLogs tail logs for all containers in a running Pod.
func (p *Pod) logs(ctx context.Context, c chan<- string, opts LogOptions) error { func (p *Pod) logs(ctx context.Context, c chan<- string, opts LogOptions) error {
fac, ok := ctx.Value(internal.KeyFactory).(*watch.Factory) fac, ok := ctx.Value(internal.KeyFactory).(*watch.Factory)
if !ok { if !ok {

View File

@ -12,7 +12,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
// MetaViewers represents a collection of meta viewers. // ResourceMetas represents a collection of resource metadata.
type ResourceMetas map[client.GVR]metav1.APIResource type ResourceMetas map[client.GVR]metav1.APIResource
// Accessors represents a collection of dao accessors. // Accessors represents a collection of dao accessors.
@ -55,6 +55,7 @@ func RegisterMeta(gvr string, res metav1.APIResource) {
resMetas[client.GVR(gvr)] = res resMetas[client.GVR(gvr)] = res
} }
// AllGVRs returns all cluster resources.
func AllGVRs() client.GVRs { func AllGVRs() client.GVRs {
kk := make(client.GVRs, 0, len(resMetas)) kk := make(client.GVRs, 0, len(resMetas))
for k := range resMetas { for k := range resMetas {
@ -85,7 +86,7 @@ func IsK9sMeta(m metav1.APIResource) bool {
return false return false
} }
// Load hydrates server preferred+CRDs resource metadata. // LoadResources hydrates server preferred+CRDs resource metadata.
func LoadResources(f Factory) error { func LoadResources(f Factory) error {
resMetas = make(ResourceMetas, 100) resMetas = make(ResourceMetas, 100)
if err := loadPreferred(f, resMetas); err != nil { if err := loadPreferred(f, resMetas); err != nil {

View File

@ -4,6 +4,7 @@ import (
"os" "os"
) )
// ScreenDump represents a scraped resources.
type ScreenDump struct { type ScreenDump struct {
Generic Generic
} }

View File

@ -11,6 +11,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
// Service represents a k8s service.
type Service struct { type Service struct {
Generic Generic
} }
@ -18,7 +19,7 @@ type Service struct {
var _ Accessor = &Service{} var _ Accessor = &Service{}
var _ Loggable = &Service{} var _ Loggable = &Service{}
// Logs tail logs for all pods represented by this Service. // TailLogs tail logs for all pods represented by this Service.
func (s *Service) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error { func (s *Service) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error {
o, err := s.Get(string(s.gvr), opts.Path, labels.Everything()) o, err := s.Get(string(s.gvr), opts.Path, labels.Everything())
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ import (
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
) )
// Factory represents a resource factory.
type Factory interface { type Factory interface {
// Client retrieves an api client. // Client retrieves an api client.
Client() client.Connection Client() client.Connection
@ -49,7 +50,9 @@ type Loggable interface {
TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error
} }
// Scalable represents resources that can scale.
type Scalable interface { type Scalable interface {
// Scale scales a resource up or down.
Scale(path string, replicas int32) error Scale(path string, replicas int32) error
} }
@ -79,5 +82,6 @@ type Runnable interface {
// Loggers represents a resource that exposes logs. // Loggers represents a resource that exposes logs.
type Logger interface { type Logger interface {
// Logs tails a resource logs.
Logs(path string, opts *v1.PodLogOptions) *restclient.Request Logs(path string, opts *v1.PodLogOptions) *restclient.Request
} }

View File

@ -54,7 +54,7 @@ func (p *Pod) List(ctx context.Context) ([]runtime.Object, error) {
return res, nil return res, nil
} }
// Render returns pod resources as rows. // Hydrate returns pod resources as rows.
func (p *Pod) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error { func (p *Pod) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error {
mx := client.NewMetricsServer(p.factory.Client()) mx := client.NewMetricsServer(p.factory.Client())
mmx, err := mx.FetchPodsMetrics(p.namespace) mmx, err := mx.FetchPodsMetrics(p.namespace)

View File

@ -13,10 +13,12 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
// Policy represent rbac policy.
type Policy struct { type Policy struct {
Resource Resource
} }
// List returns available policies.
func (p *Policy) List(ctx context.Context) ([]runtime.Object, error) { func (p *Policy) List(ctx context.Context) ([]runtime.Object, error) {
gvr, ok := ctx.Value(internal.KeyGVR).(string) gvr, ok := ctx.Value(internal.KeyGVR).(string)
if !ok { if !ok {

View File

@ -4,6 +4,7 @@ import (
"github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/render"
) )
// Registy tracks resources metadata.
// BOZO!! Break up deps and merge into single registrar // BOZO!! Break up deps and merge into single registrar
var Registry = map[string]ResourceMeta{ var Registry = map[string]ResourceMeta{
// Custom... // Custom...

View File

@ -15,6 +15,7 @@ type Resource struct {
factory Factory factory Factory
} }
// Init initializes the model.
func (r *Resource) Init(ns, gvr string, f Factory) { func (r *Resource) Init(ns, gvr string, f Factory) {
r.namespace, r.gvr, r.factory = ns, gvr, f r.namespace, r.gvr, r.factory = ns, gvr, f
} }
@ -29,7 +30,7 @@ func (r *Resource) List(ctx context.Context) ([]runtime.Object, error) {
return r.factory.List(r.gvr, r.namespace, lsel) return r.factory.List(r.gvr, r.namespace, lsel)
} }
// Render returns a node as a row. // Hydrate renders all rows.
func (r *Resource) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error { func (r *Resource) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error {
for i, o := range oo { for i, o := range oo {
if err := re.Render(o, r.namespace, &rr[i]); err != nil { if err := re.Render(o, r.namespace, &rr[i]); err != nil {

View File

@ -80,7 +80,7 @@ func (s *Stack) AddListener(l StackListener) {
} }
// Dump prints out the stack. // Dump prints out the stack.
func (s *Stack) DumpStack() { func (s *Stack) Dump() {
log.Debug().Msgf("--- Stack Dump %p---", s) log.Debug().Msgf("--- Stack Dump %p---", s)
for i, c := range s.components { for i, c := range s.components {
log.Debug().Msgf("%d -- %s -- %#v", i, c.Name(), c) log.Debug().Msgf("%d -- %s -- %#v", i, c.Name(), c)

View File

@ -14,6 +14,7 @@ type Generic struct {
table *metav1beta1.Table table *metav1beta1.Table
} }
// SetTable sets the tabular resource.
func (g *Generic) SetTable(t *metav1beta1.Table) { func (g *Generic) SetTable(t *metav1beta1.Table) {
g.table = t g.table = t
} }

View File

@ -41,16 +41,16 @@ func (p Pod) ColorerFunc() ColorerFunc {
switch status { switch status {
case ContainerCreating, PodInitializing: case ContainerCreating, PodInitializing:
return AddColor c = AddColor
case Initialized: case Initialized:
return HighlightColor c = HighlightColor
case Completed: case Completed:
return CompletedColor c = CompletedColor
case Running: case Running:
case Terminating: case Terminating:
return KillColor c = KillColor
default: default:
return ErrColor c = ErrColor
} }
return c return c

View File

@ -62,6 +62,7 @@ func (rr Rows) Delete(id string) Rows {
return append(rr[:idx], rr[idx+1:]...) return append(rr[:idx], rr[idx+1:]...)
} }
// Upserts adds a new item.
func (rr Rows) Upsert(r Row) Rows { func (rr Rows) Upsert(r Row) Rows {
idx, ok := rr.Find(r.ID) idx, ok := rr.Find(r.ID)
if !ok { if !ok {
@ -113,6 +114,7 @@ func (s RowSorter) Less(i, j int) bool {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Helpers... // Helpers...
// Less return true if c1 < c2.
func Less(asc bool, c1, c2 string) bool { func Less(asc bool, c1, c2 string) bool {
if o, ok := isDurationSort(asc, c1, c2); ok { if o, ok := isDurationSort(asc, c1, c2); ok {
return o return o

View File

@ -21,6 +21,7 @@ func (h Header) Clone() Header {
// HeaderRow represents a table header. // HeaderRow represents a table header.
type HeaderRow []Header type HeaderRow []Header
// Clone duplicates a header.
func (hh HeaderRow) Clone() HeaderRow { func (hh HeaderRow) Clone() HeaderRow {
h := make(HeaderRow, len(hh)) h := make(HeaderRow, len(hh))
for i, v := range hh { for i, v := range hh {
@ -44,9 +45,9 @@ func (hh HeaderRow) Changed(h HeaderRow) bool {
} }
// Columns return header as a collection of strings. // Columns return header as a collection of strings.
func (h HeaderRow) Columns() []string { func (hh HeaderRow) Columns() []string {
cc := make([]string, len(h)) cc := make([]string, len(hh))
for i, c := range h { for i, c := range hh {
cc[i] = c.Name cc[i] = c.Name
} }
@ -54,8 +55,8 @@ func (h HeaderRow) Columns() []string {
} }
// HasAge returns true if table has an age column. // HasAge returns true if table has an age column.
func (h HeaderRow) HasAge() bool { func (hh HeaderRow) HasAge() bool {
for _, r := range h { for _, r := range hh {
if r.Name == ageCol { if r.Name == ageCol {
return true return true
} }
@ -65,9 +66,9 @@ func (h HeaderRow) HasAge() bool {
} }
// AgeCol checks if given column index is the age column. // AgeCol checks if given column index is the age column.
func (h HeaderRow) AgeCol(col int) bool { func (hh HeaderRow) AgeCol(col int) bool {
if !h.HasAge() { if !hh.HasAge() {
return false return false
} }
return col == len(h)-1 return col == len(hh)-1
} }

View File

@ -48,6 +48,7 @@ func (s Subject) Render(o interface{}, ns string, r *Row) error {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Helpers... // Helpers...
// SubjectRef represents a subject rule.
type SubjectRef struct { type SubjectRef struct {
Name, Kind, FirstLocation string Name, Kind, FirstLocation string
} }

View File

@ -29,6 +29,7 @@ func NewKeyAction(d string, a ActionHandler, display bool) KeyAction {
return KeyAction{Description: d, Action: a, Visible: display} return KeyAction{Description: d, Action: a, Visible: display}
} }
// NewSharedKeyAction returns a new shared keyboard action.
func NewSharedKeyAction(d string, a ActionHandler, display bool) KeyAction { func NewSharedKeyAction(d string, a ActionHandler, display bool) KeyAction {
return KeyAction{Description: d, Action: a, Visible: display, Shared: true} return KeyAction{Description: d, Action: a, Visible: display, Shared: true}
} }
@ -40,14 +41,14 @@ func (a KeyActions) Add(aa KeyActions) {
} }
} }
// Clear // Clear remove all actions.
func (a KeyActions) Clear() { func (a KeyActions) Clear() {
for k := range a { for k := range a {
delete(a, k) delete(a, k)
} }
} }
// SetActions replace actions with new ones. // Set replace actions with new ones.
func (a KeyActions) Set(aa KeyActions) { func (a KeyActions) Set(aa KeyActions) {
for k, v := range aa { for k, v := range aa {
a[k] = v a[k] = v

View File

@ -121,6 +121,7 @@ func (c *CmdBuff) AddListener(w ...BuffWatcher) {
c.listeners = append(c.listeners, w...) c.listeners = append(c.listeners, w...)
} }
// RemoveListener unregisters a listener.
func (c *CmdBuff) RemoveListener(l BuffWatcher) { func (c *CmdBuff) RemoveListener(l BuffWatcher) {
victim := -1 victim := -1
for i, lis := range c.listeners { for i, lis := range c.listeners {

View File

@ -35,6 +35,7 @@ func NewCommand(styles *config.Styles) *Command {
return &c return &c
} }
// StylesChanged notifies skin changed.
func (c *Command) StylesChanged(s *config.Styles) { func (c *Command) StylesChanged(s *config.Styles) {
c.styles = s c.styles = s
c.SetBackgroundColor(s.BgColor()) c.SetBackgroundColor(s.BgColor())

View File

@ -96,6 +96,7 @@ func (c *Configurator) RefreshStyles(cluster string) {
if err := c.Styles.Load(config.K9sStylesFile); err != nil { if err := c.Styles.Load(config.K9sStylesFile); err != nil {
log.Info().Msgf("No skin file found -- %s. Loading stock skins.", config.K9sStylesFile) log.Info().Msgf("No skin file found -- %s. Loading stock skins.", config.K9sStylesFile)
c.updateStyles("")
return return
} }
c.updateStyles(config.K9sStylesFile) c.updateStyles(config.K9sStylesFile)

View File

@ -33,6 +33,7 @@ func NewCrumbs(styles *config.Styles) *Crumbs {
return &c return &c
} }
// StylesChanged notifies skin changed.
func (c *Crumbs) StylesChanged(s *config.Styles) { func (c *Crumbs) StylesChanged(s *config.Styles) {
c.styles = s c.styles = s
c.SetBackgroundColor(s.BgColor()) c.SetBackgroundColor(s.BgColor())

View File

@ -36,7 +36,7 @@ func NewStatusIndicator(app *App, styles *config.Styles) *StatusIndicator {
return &s return &s
} }
// StyleChanged notifies the skins changed. // StylesChanged notifies the skins changed.
func (s *StatusIndicator) StylesChanged(styles *config.Styles) { func (s *StatusIndicator) StylesChanged(styles *config.Styles) {
s.styles = styles s.styles = styles
s.SetBackgroundColor(styles.BgColor()) s.SetBackgroundColor(styles.BgColor())

View File

@ -32,14 +32,17 @@ func NewLogo(styles *config.Styles) *Logo {
return &l return &l
} }
// Logo returns the logo viewer.
func (l *Logo) Logo() *tview.TextView { func (l *Logo) Logo() *tview.TextView {
return l.logo return l.logo
} }
// Status returns the status viewer.
func (l *Logo) Status() *tview.TextView { func (l *Logo) Status() *tview.TextView {
return l.status return l.status
} }
// StylesChanged notifies the skin changed.
func (l *Logo) StylesChanged(s *config.Styles) { func (l *Logo) StylesChanged(s *config.Styles) {
l.styles = s l.styles = s
l.Reset() l.Reset()

View File

@ -41,15 +41,18 @@ func NewMenu(styles *config.Styles) *Menu {
return &m return &m
} }
// StylesChanged notifies skin changed.
func (m *Menu) StylesChanged(s *config.Styles) { func (m *Menu) StylesChanged(s *config.Styles) {
m.styles = s m.styles = s
m.SetBackgroundColor(s.BgColor()) m.SetBackgroundColor(s.BgColor())
} }
// StackPushed notifies a component was added.
func (m *Menu) StackPushed(c model.Component) { func (m *Menu) StackPushed(c model.Component) {
m.HydrateMenu(c.Hints()) m.HydrateMenu(c.Hints())
} }
// StackPopped notifies a component was removed.
func (m *Menu) StackPopped(o, top model.Component) { func (m *Menu) StackPopped(o, top model.Component) {
if top != nil { if top != nil {
m.HydrateMenu(top.Hints()) m.HydrateMenu(top.Hints())
@ -58,6 +61,7 @@ func (m *Menu) StackPopped(o, top model.Component) {
} }
} }
// StackTop notifies the top component.
func (m *Menu) StackTop(t model.Component) { func (m *Menu) StackTop(t model.Component) {
m.HydrateMenu(t.Hints()) m.HydrateMenu(t.Hints())
} }

View File

@ -8,11 +8,13 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// Pages represents a stack of view pages.
type Pages struct { type Pages struct {
*tview.Pages *tview.Pages
*model.Stack *model.Stack
} }
// NewPages return a new view.
func NewPages() *Pages { func NewPages() *Pages {
p := Pages{ p := Pages{
Pages: tview.NewPages(), Pages: tview.NewPages(),
@ -23,10 +25,12 @@ func NewPages() *Pages {
return &p return &p
} }
// Show displays a given page.
func (p *Pages) Show(c model.Component) { func (p *Pages) Show(c model.Component) {
p.SwitchToPage(componentID(c)) p.SwitchToPage(componentID(c))
} }
// Current returns the current component.
func (p *Pages) Current() model.Component { func (p *Pages) Current() model.Component {
c := p.CurrentPage() c := p.CurrentPage()
if c == nil { if c == nil {
@ -52,7 +56,8 @@ func (p *Pages) delete(c model.Component) {
p.RemovePage(componentID(c)) p.RemovePage(componentID(c))
} }
func (p *Pages) DumpPages() { // Dump for debug.
func (p *Pages) Dump() {
log.Debug().Msgf("Dumping Pages %p", p) log.Debug().Msgf("Dumping Pages %p", p)
for i, c := range p.Stack.Peek() { for i, c := range p.Stack.Peek() {
log.Debug().Msgf("%d -- %s -- %#v", i, componentID(c), p.GetPrimitive(componentID(c))) log.Debug().Msgf("%d -- %s -- %#v", i, componentID(c), p.GetPrimitive(componentID(c)))
@ -61,14 +66,17 @@ func (p *Pages) DumpPages() {
// Stack Protocol... // Stack Protocol...
// StackPushed notifies a new component was pushed.
func (p *Pages) StackPushed(c model.Component) { func (p *Pages) StackPushed(c model.Component) {
p.addAndShow(c) p.addAndShow(c)
} }
// StackPopped notifies a component was removed.
func (p *Pages) StackPopped(o, top model.Component) { func (p *Pages) StackPopped(o, top model.Component) {
p.delete(o) p.delete(o)
} }
// StackTop notifies a new component is at the top of the stack.
func (p *Pages) StackTop(top model.Component) { func (p *Pages) StackTop(top model.Component) {
if top == nil { if top == nil {
return return

View File

@ -52,8 +52,8 @@ func NewTable(gvr string) *Table {
} }
} }
// Init initializes the component.
func (t *Table) Init(ctx context.Context) { func (t *Table) Init(ctx context.Context) {
t.SetFixed(1, 0) t.SetFixed(1, 0)
t.SetBorder(true) t.SetBorder(true)
t.SetBorderAttributes(tcell.AttrBold) t.SetBorderAttributes(tcell.AttrBold)
@ -61,14 +61,16 @@ func (t *Table) Init(ctx context.Context) {
t.SetSelectable(true, false) t.SetSelectable(true, false)
t.SetSelectionChangedFunc(t.selectionChanged) t.SetSelectionChangedFunc(t.selectionChanged)
t.SetInputCapture(t.keyboard) t.SetInputCapture(t.keyboard)
t.StylesChanged(mustExtractSyles(ctx))
t.styles = mustExtractSyles(ctx)
t.StylesChanged(t.styles)
} }
// StylesChanged notifies the skin changed.
func (t *Table) StylesChanged(s *config.Styles) { func (t *Table) StylesChanged(s *config.Styles) {
t.styles = s t.SetBackgroundColor(config.AsColor(s.GetTable().BgColor))
t.SetBackgroundColor(config.AsColor(t.styles.GetTable().BgColor)) t.SetBorderColor(config.AsColor(s.GetTable().FgColor))
t.SetBorderColor(config.AsColor(t.styles.GetTable().FgColor)) t.SetBorderFocusColor(config.AsColor(s.Frame().Border.FocusColor))
t.SetBorderFocusColor(config.AsColor(t.styles.Frame().Border.FocusColor))
t.SetSelectedStyle( t.SetSelectedStyle(
tcell.ColorBlack, tcell.ColorBlack,
config.AsColor(t.styles.GetTable().CursorColor), config.AsColor(t.styles.GetTable().CursorColor),
@ -118,6 +120,7 @@ func (t *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
return evt return evt
} }
// 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()
} }
@ -261,7 +264,6 @@ func (t *Table) buildRow(ns string, r int, re render.RowEvent, header render.Hea
c.SetAlign(header[col].Align) c.SetAlign(header[col].Align)
c.SetTextColor(color(ns, re)) c.SetTextColor(color(ns, re))
if marked { if marked {
log.Debug().Msgf("Marked!")
c.SetTextColor(config.AsColor(t.styles.GetTable().MarkColor)) c.SetTextColor(config.AsColor(t.styles.GetTable().MarkColor))
} }
if col == 0 { if col == 0 {
@ -271,6 +273,7 @@ func (t *Table) buildRow(ns string, r int, re render.RowEvent, header render.Hea
} }
} }
// ClearMarks clear out marked items.
func (t *Table) ClearMarks() { func (t *Table) ClearMarks() {
t.marks = map[string]bool{} t.marks = map[string]bool{}
t.Refresh() t.Refresh()
@ -281,6 +284,7 @@ func (t *Table) Refresh() {
t.Update(t.model.Peek()) t.Update(t.model.Peek())
} }
// GetSelectedRow returns the entire selected row.
func (t *Table) GetSelectedRow() render.Row { func (t *Table) GetSelectedRow() render.Row {
return t.model.Peek().RowEvents[t.GetSelectedRowIndex()].Row return t.model.Peek().RowEvents[t.GetSelectedRowIndex()].Row
} }

View File

@ -75,6 +75,7 @@ func TrimLabelSelector(s string) string {
return strings.TrimSpace(s[2:]) return strings.TrimSpace(s[2:])
} }
// SkinTitle decorates a title.
func SkinTitle(fmat string, style config.Frame) string { func SkinTitle(fmat string, style config.Frame) string {
fmat = strings.Replace(fmat, "[fg:bg", "["+style.Title.FgColor+":"+style.Title.BgColor, -1) fmat = strings.Replace(fmat, "[fg:bg", "["+style.Title.FgColor+":"+style.Title.BgColor, -1)
fmat = strings.Replace(fmat, "[hilite", "["+style.Title.HighlightColor, 1) fmat = strings.Replace(fmat, "[hilite", "["+style.Title.HighlightColor, 1)

View File

@ -9,6 +9,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// Runner represents a runnable action handler.
type Runner interface { type Runner interface {
App() *App App() *App
GetSelectedItem() string GetSelectedItem() string
@ -50,7 +51,6 @@ func inScope(scopes, aliases []string) bool {
func hotKeyActions(r Runner, aa ui.KeyActions) { func hotKeyActions(r Runner, aa ui.KeyActions) {
hh := config.NewHotKeys() hh := config.NewHotKeys()
if err := hh.Load(); err != nil { if err := hh.Load(); err != nil {
log.Warn().Msgf("No HotKey configuration found")
return return
} }

View File

@ -114,7 +114,7 @@ func (a *App) Init(version string, rate int) error {
return nil return nil
} }
// StylesChanges notifies the skin changed. // StylesChanged notifies the skin changed.
func (a *App) StylesChanged(s *config.Styles) { func (a *App) StylesChanged(s *config.Styles) {
a.Main.SetBackgroundColor(s.BgColor()) a.Main.SetBackgroundColor(s.BgColor())
if f, ok := a.Main.GetPrimitive("main").(*tview.Flex); ok { if f, ok := a.Main.GetPrimitive("main").(*tview.Flex); ok {

View File

@ -20,7 +20,7 @@ type Benchmark struct {
ResourceViewer ResourceViewer
} }
// NewBench returns a new viewer. // NewBenchmark returns a new viewer.
func NewBenchmark(gvr client.GVR) ResourceViewer { func NewBenchmark(gvr client.GVR) ResourceViewer {
b := Benchmark{ b := Benchmark{
ResourceViewer: NewBrowser(gvr), ResourceViewer: NewBrowser(gvr),

View File

@ -59,6 +59,7 @@ func (d *Details) Init(_ context.Context) error {
return nil return nil
} }
// 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())
d.SetTextColor(d.app.Styles.FgColor()) d.SetTextColor(d.app.Styles.FgColor())
@ -67,6 +68,7 @@ func (d *Details) StylesChanged(s *config.Styles) {
d.Update(d.buff) d.Update(d.buff)
} }
// Update updates the view content.
func (d *Details) Update(buff string) *Details { func (d *Details) Update(buff string) *Details {
d.buff = buff d.buff = buff
d.SetText(colorizeYAML(d.app.Styles.Views().Yaml, buff)) d.SetText(colorizeYAML(d.app.Styles.Views().Yaml, buff))
@ -75,6 +77,12 @@ func (d *Details) Update(buff string) *Details {
return d return d
} }
// SetSubjects updates the subject.
func (d *Details) SetSubject(s string) {
d.subject = s
}
// Actions returns menu actions
func (d *Details) Actions() ui.KeyActions { func (d *Details) Actions() ui.KeyActions {
return d.actions return d.actions
} }
@ -132,10 +140,6 @@ func (d *Details) cpCmd(evt *tcell.EventKey) *tcell.EventKey {
return nil return nil
} }
func (d *Details) SetSubject(s string) {
d.subject = s
}
func (d *Details) updateTitle() { func (d *Details) updateTitle() {
if d.title == "" { if d.title == "" {
return return

View File

@ -21,7 +21,7 @@ func TestHelp(t *testing.T) {
assert.Nil(t, v.Init(ctx)) assert.Nil(t, v.Init(ctx))
assert.Equal(t, 17, v.GetRowCount()) assert.Equal(t, 17, v.GetRowCount())
assert.Equal(t, 10, v.GetColumnCount()) assert.Equal(t, 8, v.GetColumnCount())
assert.Equal(t, "<ctrl-k>", v.GetCell(1, 0).Text) assert.Equal(t, "<ctrl-k>", v.GetCell(1, 0).Text)
assert.Equal(t, "Kill", v.GetCell(1, 1).Text) assert.Equal(t, "Kill", v.GetCell(1, 1).Text)
} }

View File

@ -210,7 +210,7 @@ func (l *Log) updateLogs(ctx context.Context, c <-chan string, buffSize int) {
} }
} }
// ScrollIndicator returns the scroll mode viewer. // Indicator returns the scroll mode viewer.
func (l *Log) Indicator() *LogIndicator { func (l *Log) Indicator() *LogIndicator {
return l.indicator return l.indicator
} }

View File

@ -7,18 +7,21 @@ import (
"github.com/derailed/k9s/internal/ui" "github.com/derailed/k9s/internal/ui"
) )
// PageStack represents a stack of pages.
type PageStack struct { type PageStack struct {
*ui.Pages *ui.Pages
app *App app *App
} }
// NewPageStack returns a new page stack.
func NewPageStack() *PageStack { func NewPageStack() *PageStack {
return &PageStack{ return &PageStack{
Pages: ui.NewPages(), Pages: ui.NewPages(),
} }
} }
// Init initializes the view.
func (p *PageStack) Init(ctx context.Context) (err error) { func (p *PageStack) Init(ctx context.Context) (err error) {
if p.app, err = extractApp(ctx); err != nil { if p.app, err = extractApp(ctx); err != nil {
return err return err
@ -28,16 +31,19 @@ func (p *PageStack) Init(ctx context.Context) (err error) {
return nil return nil
} }
// StackPushed notifies a new page was added.
func (p *PageStack) StackPushed(c model.Component) { func (p *PageStack) StackPushed(c model.Component) {
c.Start() c.Start()
p.app.SetFocus(c) p.app.SetFocus(c)
} }
// StackPopped notifies a page was removed.
func (p *PageStack) StackPopped(o, top model.Component) { func (p *PageStack) StackPopped(o, top model.Component) {
o.Stop() o.Stop()
p.StackTop(top) p.StackTop(top)
} }
// StackTop notifies for the top component.
func (p *PageStack) StackTop(top model.Component) { func (p *PageStack) StackTop(top model.Component) {
if top == nil { if top == nil {
return return

View File

@ -13,10 +13,12 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// ScaleExtenders adds scaling extensions.
type ScaleExtender struct { type ScaleExtender struct {
ResourceViewer ResourceViewer
} }
// NewScaleExtender returns a new extender.
func NewScaleExtender(r ResourceViewer) ResourceViewer { func NewScaleExtender(r ResourceViewer) ResourceViewer {
s := ScaleExtender{ResourceViewer: r} s := ScaleExtender{ResourceViewer: r}
s.bindKeys(s.Actions()) s.bindKeys(s.Actions())

View File

@ -71,7 +71,7 @@ func (f *Factory) Get(gvr, path string, sel labels.Selector) (runtime.Object, er
return inf.Lister().ByNamespace(ns).Get(n) return inf.Lister().ByNamespace(ns).Get(n)
} }
// WaitForCachesync waits for all factories to update their cache. // WaitForCacheSync waits for all factories to update their cache.
func (f *Factory) WaitForCacheSync() { func (f *Factory) WaitForCacheSync() {
for _, fac := range f.factories { for _, fac := range f.factories {
m := fac.WaitForCacheSync(f.stopChan) m := fac.WaitForCacheSync(f.stopChan)
@ -98,7 +98,7 @@ func (f *Factory) Terminate() {
f.forwarders.DeleteAll() f.forwarders.DeleteAll()
} }
// RegisterForwarder registers a new portforward for a given container. // AddForwarder registers a new portforward for a given container.
func (f *Factory) AddForwarder(pf Forwarder) { func (f *Factory) AddForwarder(pf Forwarder) {
f.forwarders[pf.Path()] = pf f.forwarders[pf.Path()] = pf
} }
@ -114,7 +114,7 @@ func (f *Factory) DeleteForwarder(path string) {
delete(f.forwarders, path) delete(f.forwarders, path)
} }
// Forwards returns all portforwards. // Forwarders returns all portforwards.
func (f *Factory) Forwarders() Forwarders { func (f *Factory) Forwarders() Forwarders {
return f.forwarders return f.forwarders
} }
@ -133,6 +133,7 @@ func (f *Factory) Start(stopChan chan struct{}) {
} }
} }
// SetActive sets the active namespace.
// BOZO!! Check ns access for resource?? // BOZO!! Check ns access for resource??
func (f *Factory) SetActive(ns string) { func (f *Factory) SetActive(ns string) {
if !f.isClusterWide() { if !f.isClusterWide() {
@ -222,6 +223,7 @@ func (f *Factory) Client() client.Connection {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Helpers... // Helpers...
// Dump for debug.
func (f *Factory) Dump() { func (f *Factory) Dump() {
log.Debug().Msgf("----------- FACTORIES -------------") log.Debug().Msgf("----------- FACTORIES -------------")
for ns := range f.factories { for ns := range f.factories {
@ -230,6 +232,7 @@ func (f *Factory) Dump() {
log.Debug().Msgf("-----------------------------------") log.Debug().Msgf("-----------------------------------")
} }
// Debug for debug.
func (f *Factory) Debug(gvr string) { func (f *Factory) Debug(gvr string) {
log.Debug().Msgf("----------- DEBUG FACTORY (%s) -------------", gvr) log.Debug().Msgf("----------- DEBUG FACTORY (%s) -------------", gvr)
inf := f.factories[allNamespaces].ForResource(toGVR(gvr)) inf := f.factories[allNamespaces].ForResource(toGVR(gvr))
@ -238,6 +241,7 @@ func (f *Factory) Debug(gvr string) {
} }
} }
// Show for debug.
func (f *Factory) Show(ns, gvr string) { func (f *Factory) Show(ns, gvr string) {
log.Debug().Msgf("----------- SHOW FACTORIES %q -------------", ns) log.Debug().Msgf("----------- SHOW FACTORIES %q -------------", ns)
inf := f.ForResource(ns, gvr) inf := f.ForResource(ns, gvr)