From dfa530ab5f025ec5adff0090d585aaf596412720 Mon Sep 17 00:00:00 2001 From: Janne Koschinski Date: Wed, 18 Oct 2017 22:44:36 +0200 Subject: [PATCH] Fix a broken default, and add kube segment --- defaults.go | 10 +++++ main.go | 67 +++++++++++++++++++++--------- segment-cwd.go | 11 +++-- segment-kube.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ themes.go | 5 +++ 5 files changed, 176 insertions(+), 22 deletions(-) create mode 100644 segment-kube.go diff --git a/defaults.go b/defaults.go index f3a071e4..0ee6a779 100644 --- a/defaults.go +++ b/defaults.go @@ -92,6 +92,11 @@ var themes = map[string]Theme{ DockerMachineFg: 177, // light purple DockerMachineBg: 55, // purple + KubeClusterFg: 117, + KubeClusterBg: 26, + KubeNamespaceFg: 170, + KubeNamespaceBg: 17, + DotEnvFg: 15, // white DotEnvBg: 55, // purple @@ -422,6 +427,11 @@ var themes = map[string]Theme{ DockerMachineFg: 55, // purple DockerMachineBg: 177, // light purple + KubeClusterFg: 117, + KubeClusterBg: 26, + KubeNamespaceFg: 170, + KubeNamespaceBg: 17, + DotEnvFg: 15, // white DotEnvBg: 55, // purple diff --git a/main.go b/main.go index 7bd25d79..014ea75c 100644 --- a/main.go +++ b/main.go @@ -41,8 +41,9 @@ type args struct { Priority *string MaxWidthPercentage *int TruncateSegmentWidth *int - IgnoreRepos *string PrevError *int + IgnoreRepos *string + ShortenGKENames *bool } func (s segment) computeWidth() int { @@ -93,6 +94,7 @@ var modules = map[string](func(*powerline)){ "hg": segmentHg, "host": segmentHost, "jobs": segmentJobs, + "kube": segmentKube, "perlbrew": segmentPerlbrew, "perms": segmentPerms, "root": segmentRoot, @@ -104,58 +106,87 @@ var modules = map[string](func(*powerline)){ func main() { args := args{ - CwdMode: flag.String("cwd-mode", "fancy", + CwdMode: flag.String( + "cwd-mode", + "fancy", "How to display the current directory\n"+ " (valid choices: fancy, plain, dironly)\n"+ " "), - CwdMaxDepth: flag.Int("cwd-max-depth", 5, + CwdMaxDepth: flag.Int( + "cwd-max-depth", + 5, "Maximum number of directories to show in path\n"+ " "), - CwdMaxDirSize: flag.Int("cwd-max-dir-size", -1, + CwdMaxDirSize: flag.Int( + "cwd-max-dir-size", + -1, "Maximum number of letters displayed for each directory in the path\n"+ " "), - ColorizeHostname: flag.Bool("colorize-hostname", false, + ColorizeHostname: flag.Bool( + "colorize-hostname", + false, "Colorize the hostname based on a hash of itself"), - EastAsianWidth: flag.Bool("east-asian-width", false, + EastAsianWidth: flag.Bool( + "east-asian-width", + false, "Use East Asian Ambiguous Widths"), - PromptOnNewLine: flag.Bool("newline", false, + PromptOnNewLine: flag.Bool( + "newline", + false, "Show the prompt on a new line"), - Mode: flag.String("mode", "patched", + Mode: flag.String( + "mode", + "patched", "The characters used to make separators between segments.\n"+ " (valid choices: patched, compatible, flat)\n"+ " "), - Theme: flag.String("theme", "default", + Theme: flag.String( + "theme", + "default", "Set this to the theme you want to use\n"+ " (valid choices: default, low-contrast)\n"+ " "), - Shell: flag.String("shell", "bash", + Shell: flag.String( + "shell", + "bash", "Set this to your shell type\n"+ " (valid choices: bare, bash, zsh)\n"+ " "), - Modules: flag.String("modules", + Modules: flag.String( + "modules", "venv,user,host,ssh,cwd,perms,git,hg,jobs,exit,root", "The list of modules to load, separated by ','\n"+ " (valid choices: aws, cwd, docker, dotenv, exit, git, gitlite, hg, host, jobs, perlbrew, perms, root, ssh, time, user, venv)\n"+ " "), - Priority: flag.String("priority", - "root,cwd,user,host,ssh,perms,git-branch,git-status,hg,jobs,exit", + Priority: flag.String( + "priority", + "root,cwd,user,host,ssh,perms,git-branch,git-status,hg,jobs,exit,cwd-path", "Segments sorted by priority, if not enough space exists, the least priorized segments are removed first. Separate with ','\n"+ - " (valid choices: aws, cwd, docker, exit, git-branch, git-status, hg, host, jobs, perlbrew, perms, root, ssh, time, user, venv)\n"+ + " (valid choices: aws, cwd, cwd-path, docker, exit, git-branch, git-status, hg, host, jobs, perlbrew, perms, root, ssh, time, user, venv)\n"+ " "), - MaxWidthPercentage: flag.Int("max-width", + MaxWidthPercentage: flag.Int( + "max-width", 50, "Maximum width of the shell that the prompt may use, in percent. Setting this to 0 disables the shrinking subsystem.\n"+ " "), - TruncateSegmentWidth: flag.Int("truncate-segment-width", + TruncateSegmentWidth: flag.Int( + "truncate-segment-width", 16, "Minimum width of a segment, segments longer than this will be shortened if space is limited. Setting this to 0 disables it.\n"+ " "), - PrevError: flag.Int("error", 0, + PrevError: flag.Int( + "error", + 0, "Exit code of previously executed command"), - IgnoreRepos: flag.String("ignore-repos", + IgnoreRepos: flag.String( + "ignore-repos", "", "A list of git repos to ignore. Separate with ','\n"+ "Repos are identified by their root directory."), + ShortenGKENames: flag.Bool( + "shorten-gke-names", + false, + "Shortens names for GKE Kube clusters."), } flag.Parse() if strings.HasSuffix(*args.Theme, ".json") { diff --git a/segment-cwd.go b/segment-cwd.go index d0e033c4..a27d1ad7 100644 --- a/segment-cwd.go +++ b/segment-cwd.go @@ -12,7 +12,6 @@ type pathSegment struct { home bool root bool ellipsis bool - priority int } func cwdToPathSegments(cwd string) []pathSegment { @@ -107,13 +106,12 @@ func segmentCwd(p *powerline) { } firstPart := pathSegments[:nBefore] secondPart := pathSegments[len(pathSegments)+nBefore-maxDepth:] + pathSegments = make([]pathSegment, 0) for _, segment := range firstPart { - segment.priority = -2 pathSegments = append(pathSegments, segment) } pathSegments = append(pathSegments, pathSegment{ - priority: -1, path: ellipsis, ellipsis: true, }) @@ -135,7 +133,12 @@ func segmentCwd(p *powerline) { segment.separatorForeground = p.theme.SeparatorFg } - p.appendSegment("cwd", segment) + origin := "cwd-path" + if isLastDir { + origin = "cwd" + } + + p.appendSegment(origin, segment) } } } diff --git a/segment-kube.go b/segment-kube.go new file mode 100644 index 00000000..0fb1fa4a --- /dev/null +++ b/segment-kube.go @@ -0,0 +1,105 @@ +package main + +import ( + "io/ioutil" + "os" + "path" + "path/filepath" + "runtime" + "strings" + + "fmt" + "gopkg.in/yaml.v2" +) + +type KubeContext struct { + Context struct { + Cluster string + Namespace string + User string + } + Name string +} + +type KubeConfig struct { + Contexts []KubeContext `yaml:"contexts"` + CurrentContext string `yaml:"current-context"` +} + +func homePath() string { + env := "HOME" + if runtime.GOOS == "windows" { + env = "USERPROFILE" + } + return os.Getenv(env) +} + +func readKubeConfig(config *KubeConfig, path string) (err error) { + absolutePath, err := filepath.Abs(path) + if err != nil { + return + } + fileContent, err := ioutil.ReadFile(absolutePath) + if err != nil { + return + } + err = yaml.Unmarshal(fileContent, config) + if err != nil { + return + } + + return +} + +func segmentKube(p *powerline) { + paths := append(strings.Split(os.Getenv("KUBECONFIG"), ":"), path.Join(homePath(), ".kube", "config")) + config := &KubeConfig{} + for _, configPath := range paths { + if readKubeConfig(config, configPath) == nil { + break + } + } + + cluster := "" + namespace := "" + for _, context := range config.Contexts { + if context.Name == config.CurrentContext { + cluster = context.Context.Cluster + namespace = context.Context.Namespace + break + } + } + + // When you use gke your clusters may look something like gke_projectname_availability-zone_cluster-01 + // instead I want it to read as `cluster-01` + // So we remove the first 3 segments of this string, if the flag is set, and there are enough segments + if strings.HasPrefix(cluster, "gke") && *p.args.ShortenGKENames { + segments := strings.Split(cluster, "_") + if len(segments) > 3 { + cluster = strings.Join(segments[3:], "_") + } + } + + // Only draw the icon once + kubeIconHasBeenDrawnYet := false + if cluster != "" { + kubeIconHasBeenDrawnYet = true + p.appendSegment("kube-cluster", segment{ + content: fmt.Sprintf("⎈ %s", cluster), + foreground: p.theme.KubeClusterFg, + background: p.theme.KubeClusterBg, + }) + } + + if namespace != "" { + content := namespace + if !kubeIconHasBeenDrawnYet { + content = fmt.Sprintf("⎈ %s", content) + } + p.appendSegment("kube-namespace", segment{ + content: content, + foreground: p.theme.KubeNamespaceFg, + background: p.theme.KubeNamespaceBg, + }) + } +} diff --git a/themes.go b/themes.go index 546009cb..2dddc34b 100644 --- a/themes.go +++ b/themes.go @@ -45,6 +45,11 @@ type Theme struct { DockerMachineFg uint8 DockerMachineBg uint8 + KubeClusterFg uint8 + KubeClusterBg uint8 + KubeNamespaceFg uint8 + KubeNamespaceBg uint8 + DotEnvFg uint8 DotEnvBg uint8