From 6ec4ed89cebca93c7c5c470cb1a8b99ad3865e7d Mon Sep 17 00:00:00 2001 From: "Michael J. Giarlo" Date: Tue, 22 Feb 2022 19:30:14 -0800 Subject: [PATCH] Add RVM segment for Rubyists who use RVM Includes a configurable indicator and theme colors. Based heavily on the rbenv segment, with some novel work to extract the RVM gemset from an environment variable. --- README.md | 8 ++-- args.go | 6 +-- defaults.go | 15 ++++++++ main.go | 1 + segment-rvm.go | 91 +++++++++++++++++++++++++++++++++++++++++++++ themes.go | 4 ++ themes/default.json | 2 + 7 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 segment-rvm.go diff --git a/README.md b/README.md index 0e98e8f9..0177aa4e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Ported to golang by @justjanne. - Changes color if the last command exited with a failure code - If you're too deep into a directory tree, shortens the displayed path with an ellipsis - Shows the current Python [virtualenv](http://www.virtualenv.org/) environment -- Shows the current Ruby version using [rbenv](https://github.com/rbenv/rbenv) +- Shows the current Ruby version using [rbenv](https://github.com/rbenv/rbenv) or [rvm](https://rvm.io/) - Shows if you are in a [nix](https://nixos.org/) shell - It's easy to customize and extend. See below for details. @@ -248,12 +248,12 @@ Usage of powerline-go: (default "patched") -modules string The list of modules to load, separated by ',' - (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl) + (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl) Unrecognized modules will be invoked as 'powerline-go-MODULE' executable plugins and should output a (possibly empty) list of JSON objects that unmarshal to powerline-go's Segment structs. (default "venv,user,host,ssh,cwd,perms,git,hg,jobs,exit,root") -modules-right string The list of modules to load anchored to the right, for shells that support it, separated by ',' - (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, wsl) + (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, wsl) Unrecognized modules will be invoked as 'powerline-go-MODULE' executable plugins and should output a (possibly empty) list of JSON objects that unmarshal to powerline-go's Segment structs. -newline Show the prompt on a new line @@ -266,7 +266,7 @@ Usage of powerline-go: Use '~' for your home dir. You may need to escape this character to avoid shell substitution. -priority string Segments sorted by priority, if not enough space exists, the least priorized segments are removed first. Separate with ',' - (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl) + (valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl) (default "root,cwd,user,host,ssh,perms,git-branch,git-status,hg,jobs,exit,cwd-path") -shell string Set this to your shell type diff --git a/args.go b/args.go index 6ba3ce89..d0f3b6c1 100644 --- a/args.go +++ b/args.go @@ -127,19 +127,19 @@ var args = arguments{ "modules", strings.Join(defaults.Modules, ","), commentsWithDefaults("The list of modules to load, separated by ','", - "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl)", + "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl)", "Unrecognized modules will be invoked as 'powerline-go-MODULE' executable plugins and should output a (possibly empty) list of JSON objects that unmarshal to powerline-go's Segment structs.")), ModulesRight: flag.String( "modules-right", strings.Join(defaults.ModulesRight, ","), comments("The list of modules to load anchored to the right, for shells that support it, separated by ','", - "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, wsl)", + "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, wsl)", "Unrecognized modules will be invoked as 'powerline-go-MODULE' executable plugins and should output a (possibly empty) list of JSON objects that unmarshal to powerline-go's Segment structs.")), Priority: flag.String( "priority", strings.Join(defaults.Priority, ","), commentsWithDefaults("Segments sorted by priority, if not enough space exists, the least priorized segments are removed first. Separate with ','", - "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl)")), + "(valid choices: aws, bzr, cwd, docker, docker-context, dotenv, duration, exit, fossil, gcp, git, gitlite, goenv, hg, host, jobs, kube, load, newline, nix-shell, node, perlbrew, perms, plenv, rbenv, root, rvm, shell-var, shenv, ssh, svn, termtitle, terraform-workspace, time, user, venv, vgo, vi-mode, wsl)")), MaxWidthPercentage: flag.Int( "max-width", defaults.MaxWidthPercentage, diff --git a/defaults.go b/defaults.go index be595936..84df1ec8 100644 --- a/defaults.go +++ b/defaults.go @@ -84,6 +84,7 @@ var defaults = Config{ VenvIndicator: "\uE235", NodeIndicator: "\u2B22", + RvmIndicator: "\uE92B", }, "patched": { Lock: "\uE0A2", @@ -106,6 +107,7 @@ var defaults = Config{ VenvIndicator: "\uE235", NodeIndicator: "\u2B22", + RvmIndicator: "\uE92B", }, "flat": { RepoDetached: "\u2693", @@ -119,6 +121,7 @@ var defaults = Config{ VenvIndicator: "\uE235", NodeIndicator: "\u2B22", + RvmIndicator: "\uE92B", }, }, Shells: ShellMap{ @@ -263,6 +266,9 @@ var defaults = Config{ NodeVersionFg: 40, NodeVersionBg: 15, + RvmFg: 255, + RvmBg: 160, + LoadFg: 15, LoadBg: 22, LoadHighBg: 161, @@ -637,6 +643,9 @@ var defaults = Config{ LoadAvgValue: 5, LoadThresholdBad: 1.0, + RvmFg: 255, + RvmBg: 160, + NixShellFg: 69, // a light blue NixShellBg: 254, @@ -977,6 +986,8 @@ var defaults = Config{ LoadHighBg: 5, LoadAvgValue: 5, LoadThresholdBad: 1.0, + RvmFg: 8, + RvmBg: 6, NixShellFg: 0, NixShellBg: 4, HostnameColorizedFgMap: map[uint8]uint8{ @@ -1316,6 +1327,8 @@ var defaults = Config{ LoadHighBg: 5, LoadAvgValue: 5, LoadThresholdBad: 1.0, + RvmFg: 8, + RvmBg: 6, NixShellFg: 0, NixShellBg: 7, HostnameColorizedFgMap: map[uint8]uint8{ @@ -1649,6 +1662,8 @@ var defaults = Config{ NodeBg: gruvbox_faded_green, // match virtualenv NodeVersionFg: gruvbox_faded_green, // match virtualenv NodeVersionBg: gruvbox_light0, // match virtualenv + RvmFg: gruvbox_light0, + RvmBg: gruvbox_neutral_red, LoadFg: gruvbox_light0, LoadBg: gruvbox_faded_purple, LoadHighBg: gruvbox_neutral_red, diff --git a/main.go b/main.go index 84ffa492..b2a55001 100644 --- a/main.go +++ b/main.go @@ -95,6 +95,7 @@ var modules = map[string]func(*powerline) []pwl.Segment{ "perms": segmentPerms, "rbenv": segmentRbenv, "root": segmentRoot, + "rvm": segmentRvm, "shell-var": segmentShellVar, "shenv": segmentShEnv, "ssh": segmentSSH, diff --git a/segment-rvm.go b/segment-rvm.go new file mode 100644 index 00000000..740933ac --- /dev/null +++ b/segment-rvm.go @@ -0,0 +1,91 @@ +package main + +import ( + "errors" + "os" + "os/exec" + "strings" + + pwl "github.com/justjanne/powerline-go/powerline" +) + +func runRvmCommand(cmd string, args ...string) (string, error) { + command := exec.Command(cmd, args...) + out, err := command.Output() + return string(out), err +} + +// check RUBY_VERSION variable +func checkEnvForRubyVersion() (string, error) { + rubyVersion := os.Getenv("RUBY_VERSION") + if len(rubyVersion) <= 0 { + return "", errors.New("Not found in RUBY_VERSION") + } + return rubyVersion, nil +} + +// check GEM_HOME variable for gemset information +func checkEnvForRubyGemset() (string, error) { + gemHomeSegments := strings.Split(os.Getenv("GEM_HOME"), "@") + + if len(gemHomeSegments) <= 1 { + return "", errors.New("Gemset not found in GEM_HOME") + } + + return gemHomeSegments[1], nil +} + +// retrieve ruby version from RVM +func checkForRvmOutput() (string, error) { + // ask RVM what the current ruby version is + out, err := runRvmCommand("rvm", "current") + if err != nil { + return "", errors.New("Not found in RVM output") + } + items := strings.Split(out, " ") + if len(items) <= 0 { + return "", errors.New("Not found in RVM output") + } + + return items[0], nil +} + +func segmentRvm(p *powerline) []pwl.Segment { + var ( + segment string + err error + ) + + segment, err = checkEnvForRubyVersion() + if err != nil { + segment, err = checkForRubyVersionFileInTree() + } + if err != nil { + segment, err = checkForRvmOutput() + } + if err != nil { + return []pwl.Segment{} + } + + // Remove explicit "ruby-" prefix from segment because it's superfluous + segment_components := strings.Split(segment, "-") + if len(segment_components) > 1 { + segment = segment_components[1] + } + + // If gemset is missing from segment, get that info from the environment + segment_components = strings.Split(segment, "@") + if len(segment_components) < 2 { + gemset, err := checkEnvForRubyGemset() + if err == nil && gemset != "" { + segment = segment + "@" + gemset + } + } + + return []pwl.Segment{{ + Name: "rvm", + Content: p.symbols.RvmIndicator + " " + segment, + Foreground: p.theme.RvmFg, + Background: p.theme.RvmBg, + }} +} diff --git a/themes.go b/themes.go index 8d9e4859..c2732ce9 100644 --- a/themes.go +++ b/themes.go @@ -22,6 +22,7 @@ type SymbolTemplate struct { VenvIndicator string NodeIndicator string + RvmIndicator string } // Theme definitions @@ -141,6 +142,9 @@ type Theme struct { NodeVersionFg uint8 NodeVersionBg uint8 + RvmFg uint8 + RvmBg uint8 + LoadFg uint8 LoadBg uint8 LoadHighBg uint8 diff --git a/themes/default.json b/themes/default.json index e1146dd1..0615b6fd 100644 --- a/themes/default.json +++ b/themes/default.json @@ -66,6 +66,8 @@ "NodeBg": 40, "NodeVersionFg": 40, "NodeVersionBg": 15, + "RvmFg": 255, + "RvmBg": 160, "LoadFg": 15, "LoadBg": 22, "LoadHighBg": 161,