dynamic background color for custom prompt element in Powerlevel9k - kubernetes

I am using the awesome Powerlevel9k theme for my Zsh.
I defined a custom kubecontext element to show my kubernetes cluster (context) and namespace (see code below).
While I conditionally set the foreground color through the color variable I would like to set the background color instead to be able to better see when I work on the production cluster.
Is that somehow possible with Powerlevel9k? All I could find is that I can set the background color of the prompt element statically with POWERLEVEL9K_CUSTOM_KUBECONTEXT_BACKGROUND='075'
# Kubernetes Current Context/Namespace
custom_prompt_kubecontext() {
local kubectl_version="$(kubectl version --client 2>/dev/null)"
if [[ -n "$kubectl_version" ]]; then
# Get the current Kuberenetes context
local cur_ctx=$(kubectl config view -o=jsonpath='{.current-context}')
cur_namespace="$(kubectl config view -o=jsonpath="{.contexts[?(#.name==\"${cur_ctx}\")].context.namespace}")"
# If the namespace comes back empty set it default.
if [[ -z "${cur_namespace}" ]]; then
cur_namespace="default"
fi
local k8s_final_text="$cur_ctx/$cur_namespace"
local color='%F{black}'
[[ $cur_ctx == "prod" ]] && color='%F{196}'
echo -n "%{$color%}\U2388 $k8s_final_text%{%f%}" # \U2388 is Kubernetes Icon
#"$1_prompt_segment" "$0" "$2" "magenta" "black" "$k8s_final_text" "KUBERNETES_ICON"
fi
}
POWERLEVEL9K_CUSTOM_KUBECONTEXT="custom_prompt_kubecontext"
# Powerlevel9k configuration
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context dir vcs custom_kubecontext)
Here is a screenshot of the current setup in action:

Disclaimer: I'm the author of powerlevel10k.
No, this is not possible in powerlevel9k. It is, however, possible in powerlevel10k. Powerlevel10k is backward compatible with powerlevel9k configuration, meaning that you won't have to change any POWERLEVEL9K parameters if you decide to switch.
Powerlevel10k has several advantages over its predecessor:
It's over 10 times faster.
It has a builtin configuration wizard. Type p10k configure to access it.
It has many new features. One of them is relevant to you. The builtin kubecontext supports context classes that allow you to style this prompt segment differently depending on which kubernetes context is currently active. Here's the excerpt from the configuration that p10k configure generates:
# Kubernetes context classes for the purpose of using different colors, icons and expansions with
# different contexts.
#
# POWERLEVEL9K_KUBECONTEXT_CLASSES is an array with even number of elements. The first element
# in each pair defines a pattern against which the current kubernetes context gets matched.
# More specifically, it's P9K_CONTENT prior to the application of context expansion (see below)
# that gets matched. If you unset all POWERLEVEL9K_KUBECONTEXT_*CONTENT_EXPANSION parameters,
# you'll see this value in your prompt. The second element of each pair in
# POWERLEVEL9K_KUBECONTEXT_CLASSES defines the context class. Patterns are tried in order. The
# first match wins.
#
# For example, given these settings:
#
# typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=(
# '*prod*' PROD
# '*test*' TEST
# '*' DEFAULT)
#
# If your current kubernetes context is "deathray-testing/default", its class is TEST
# because "deathray-testing/default" doesn't match the pattern '*prod*' but does match '*test*'.
#
# You can define different colors, icons and content expansions for different classes:
#
# typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_FOREGROUND=0
# typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_BACKGROUND=2
# typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐'
# typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <'
typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=(
# '*prod*' PROD # These values are examples that are unlikely
# '*test*' TEST # to match your needs. Customize them as needed.
'*' DEFAULT)
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=7
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_BACKGROUND=5
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⎈'
You can also customize the text content of kubecontext. You'll find more info in ~/.p10k.zsh once you run p10k configure. Oh, and kubecontext is about 1000 times faster in powerlevel10k.

Related

how to seperate compadd values with line break (zsh)

I have a compadd function that is meant to list AWS instances tags and return that list as completion options.
_aws_instance_by_name() {
# TODO: Figure out partial completion
local instances=$(aws ec2 describe-instances --query "Reservations[*].Instances[*].{Name:Tags[?Key=='Name']|[0].Value}" --output text)
[[ ${DEBUG} ]] && echo -e "\033[34;1m[DEBUG]\033[0m ${instances}"
compadd ${instances}
}
compdef _aws_instance_by_name aws_instance_id_by_name
But when I hit tab I get all options in option delimited by \n
foo\nbar\nSuper fancy
How do I split each value into the returned suggestions?
#compdef aws_instance_id_by_name
# Wrap output in double quotes to
# preserve all whitespace.
local output="$( <command> )"
# Split on line breaks.
local -a instances=( "${(f)output}" )
# Use convenience function to get
# fancy completion features for
# free. No need to figure out
# partial completion yourself.
_wanted aws-instances 'AWS instance' \
compadd -a instances
If you paste the above into a text file whose name starts with _ and save it into a dir that’s in your $fpath, it will get picked up automatically when you run compinit. No need to call compdef.
Documentation:
Command substitution
Parameter expansion flags
Completion system:
Utility functions
Autoloaded files

How can I enable tab-completion for `#` path options to HTTPie in fish?

HTTPie accepts paths as arguments with options that include the # sign. Unfortunately, they don't seem to work with shell completions in fish. Instead, the option is treated as an opaque string.
To stick with the file upload example from the HTTPie documentation with a file at ~/files/data.xml, I would expect to be able to tab complete the file name when typing:
http -f POST pie.dev/post name='John Smith' cv#~/files/da<TAB>
However, no completion is offered.
I have installed the completions for fish from the HTTPie project and they work for short and long arguments. This file does not specify how to complete the # arguments though.
In addition, I looked into specifying my own completions but I am not able to find a way of getting to work file completions with the arbitrary prefix.
How could I implement a completion for these path arguments for HTTPie?
Currently, the fish completions for HTTPie do not have completion for file path arguments with #. There is a more general GitHub Issue open about this.
If this is something you'd like to work on, either for yourself or for the project, you might be able draw some inspiration for the fish implementation from an HTTPie plugin for zsh+ohmyzsh that achieves your desired behaviour.
I managed to get the tab completion of the path arguments working with some caveats.
This adds the completion:
complete -c http --condition "__is_httpie_path_argument" -a "(__complete_httpie_path_argument (commandline -t))"
With the following functions:
function __is_httpie_path_argument
set -l arg (commandline -t)
__match_httpie_path_argument --quiet -- $arg
end
function __match_httpie_path_argument
string match --entire --regex '^([^#:=]*)(#|=#|:=#)(.*)$' $argv
end
function __complete_httpie_path_argument
__complete_httpie_path_argument_helper (__match_httpie_path_argument -- $argv[1])
end
function __complete_httpie_path_argument_helper
set -l arg $argv[1]
set -l field $argv[2]
set -l operator $argv[3]
set -l path $argv[4]
string collect $field$operator(__fish_complete_path $path)
end
The caveat is that this does not expand any variables nor the tilde ~. It essentially only works for plain paths — relative or absolute.

How to conditionally install documentation to pkghtmldir using Automake

I have a recipe in Automake that optionally builds documentation if the user issues make doc or make htmldoc:
if DOXYGEN_AVAILABLE
docs html htmldoc html-doc:
$(DOXYGEN) Doxyfile -d DOXYGEN_PROCESSING
fi
DOXYGEN_AVAILABLE is set in configure based on the result of AC_CHECK_PROGS. If the docs are built there will be a directory html-doc. The documentation is optional and html-doc may be missing.
If html-doc is present I won't have a file list. I don't believe this will work in Makefile.am:
if DOXYGEN_AVAILABLE
docs html htmldoc html-doc:
$(DOXYGEN) Doxyfile -d DOXYGEN_PROCESSING
pkghtmldir_FILES += html-doc/
fi
How do I optionally install documentation to pkghtmldir when using Automake?
I suggest in the first place that you change your logic a bit. If it's OK to not install the Doxygen docs when Doxygen isn't available to build them, then it should also be OK not to install them even if Doxygen is available. Thus, it makes sense to use an --enable-docs or --with-docs or similar option to configure to let the package builder express whether the docs should be built, with whichever default suits you. You could also consider including pre-built docs with your package, and then selecting whether to enable rebuilding them.
You can furthermore, then, altogether omit the check for Doxygen when docs are not requested anyway, and emit a warning or error when they are requested but Doxygen is not available (or is too old). That should be less surprising to package builders. At least, it would be less surprising to me.
Still, it ultimately comes down to Automake conditionals either way. Here's a slightly trimmed version of how I handle pretty much the same task in one of my projects:
$(top_srcdir)/Makefile.am:
# An Automake conditional:
if make_docs
# The name of the target(s) that encompasses actually building the docs
doxygen_html_targets = dox-html
# My Doxyfile is built by the build system, and the docs also depend on some example
# sources, stylesheets, and other files provided by the package. All these are
# listed here, so that the docs are rebuilt if any of them change:
dox_deps = Doxyfile ...
# How to actually install the docs (a one-line make recipe). Covers also installing
# pre-built docs that I include in the package for convenience, though this example
# has most of the other plumbing for that removed.
#
# The chmod in the below command must ensure the target files writable
# in order to work around weirdness in the behavior of the "distcheck" target
# when not configured to rebuild docs.
html_install = test -d dox-html && html_dir=dox-html || html_dir=$(srcdir)/dox-html; \
$(MKDIR_P) $(DESTDIR)$(pkgdocdir); \
cp -pR $${html_dir} $(DESTDIR)$(pkgdocdir)/html; \
chmod -R u+w,go+rX $(DESTDIR)$(pkgdocdir)/html
else
doxygen_html_targets =
dox_deps =
html_install = :
endif
# The variable prerequisites of this rule are how the selection is made between
# building the docs and not building them:
html-local: $(doxygen_html_targets)
:
## This rule should not be necessary, but Automake seems otherwise to ignore the
## install-html-local rule, perhaps because there are no targets with an HTML
## primary.
install-data-local: install-html-local
# The variable recipe for this rule is how the selection is made between installing
# the docs and not installing them:
install-html-local:
$(html_install)
maintainer-clean-local:
$(RM) -rf dox-html
# This rule, when exercised, is what actually builds the docs:
dox-html: $(dox_deps)
$(RM) -rf dox-html
$(DOXYGEN) Doxyfile
The key thing to take away here is that it's not only file lists that you can store in make variables and control via Automake conditionals. You can also store the names of arbitrary targets, to be used in prerequisite lists, and you can even store the text of rule recipes, so as to vary behavior of the rules that are selected.

Passing optional parameters to rundeck script

I have a python script that I would like to run using rundeck that is invoked as follows:
createInstance.py [-n <name>] <env> <version>
Where name is optional and env and version are required.
e.g. if I want to call the script with a name I would call:
createInstance.py -n test staging 1.2.3.4
If I want to default the name, I would call:
createInstance.py staging 1.2.3.4
The problem i have is that I dont know how to specify the script arguments string in rundeck. I have a job, with 3 options, one for env, version and name and if I define the arguments string as:
-n ${option.name} ${option.env} ${option.version}
Whenever the name is unset, rundeck calls:
createInstance.py -n staging 1.2.3.4
Instead I would like it to omit the -n. Is there any way of doing this? Right now my only option is to change the script to be more forgiving in how it handles the -n, and to always ensure its at the end, e.g.:
createInstance.py staging 1.2.3.4 -n
createInstance.py staging 1.2.3.4 -n test
I would like to avoid making this change though, as I want to be able to use the scripts standalone as well.
Rather than use a command step, try an inline script step. Your inline script can count the number of arguments and if they are set. Then with that logic you can choose how to set the creteInstance.py args.
As #Alex-SF suggests, I've also used an inline script for this, along with a Key Value Data log filter. The script is:
#!/bin/bash
# Parse optional parameters
# https://stackoverflow.com/questions/41233996/passing-optional-parameters-to-rundeck-script
# Arguments to this script should be in the format "flag" "value", eg "-p" ${option.name}
# If value is not missing then return will be "flag value", otherwise blank
echo -n "RUNDECK:DATA:"
while (( "$#" )); do
flag="$1"
value="$2"
if [[ -z "$value" ]] || [[ $value =~ ^\- ]]; then
# no value for this parameter (empty or picking up the next flag)
echo -n ""
shift
else
# value provided for this parameter
echo -n "$flag $value "
shift
shift
fi
done
And the key value data filter uses the pattern ^RUNDECK:DATA:(.*)$ and the name data args. Then I use ${data.args*} as the input for the real command.
It's all rather messy, and I can't find any open issue requesting this as a feature (yet).
Use an inline script and use conditional variable expansion feature from bash.
createInstance.py ${RD_OPTION_NAME:+-n $RD_OPTION_NAME} $RD_OPTION_ENV $RD_OPTION_VERSION
This will omit the first option altogether if it is empty ("").

Oh-my-zsh aliases do not autocomplete

I am a bit out of my wits researching this... and I just have to ask.
I have oh-my-zsh on my Mavericks machine and have everything updated. I also have Xcode and Brew. All updated. According to this page: https://github.com/robbyrussell/oh-my-zsh/wiki/Cheatsheet am I not supposed to just type, say: "g" [tab] and get "git"? or type "md" [tab] and get "mkdir -p"? Right now I just get a list of options I can tab through (or arrow through)... I thought it would autocomplete. What am I missing?
I have a feeling it might be related to my $PATH but that is where I also get confused... where should it point to?
I greatly appreciate and enlightenment.
# Path to your oh-my-zsh configuration.
#ZSH=$HOME/.oh-my-zsh
export ZSH=$HOME/.oh-my-zsh
# Set name of the theme to load.
# Look in ~/.oh-my-zsh/themes/
# Optionally, if you set this to "random", it'll load a random theme each
# time that oh-my-zsh is loaded.
#ZSH_THEME="af-magic"
ZSH_THEME="agnoster"
# Set to this to use case-sensitive completion
# CASE_SENSITIVE="true"
# Comment this out to disable weekly auto-update checks
# DISABLE_AUTO_UPDATE="true"
# Uncomment following line if you want to disable colors in ls
# DISABLE_LS_COLORS="true"
# Uncomment following line if you want to disable autosetting terminal title.
# DISABLE_AUTO_TITLE="true"
# Uncomment following line if you want red dots to be displayed while waiting for completion
COMPLETION_WAITING_DOTS="true"
# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
# Example format: plugins=(rails git textmate ruby lighthouse)
plugins=(git textmate sublime zsh-syntax-highlighting)
source $ZSH/oh-my-zsh.sh
#export PATH=/usr/local/bin:/usr/local/sbin:/usr/local/git/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/X11/$
#export PATH=$HOME/bin:/usr/local/bin:$PATH
export PATH=/usr/local/bin:$PATH
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
zstyle ':completion:*' list-prompt ''
zstyle ':completion:*' select-prompt ''
autoload -Uz compinit
compinit
Aliases are essentially just short names for commands. Before executing a command zsh internally replaces aliases by their values. But by default aliases are not expanded when using completion (Tab), they are handled just like any other command.
For example:
alias ll='ls -l'
alias la='ls -al'
If you now type lTab, zsh will present you every command starting with an l, including the aliases ll and la. If you type llTab it will probably just add an space after ll (assuming there are no other commands starting with ll).
When you run ll somedir it does the exact same thing as ls -l somedir. You can even add other options of ls: ll -t somedir runs ls -l -t somedir.
That being said, if you want to expand aliases when typing Tab, zsh can do so.
There are two ways:
You can call the _expand_alias widget. In emacs mode (bindkey -e) this is bound to ^Xa (press Control+X then A).
You can add _expand_alias to the completer style. It seems that oh-my-zsh does not change this style from its default value, so adding
zstyle ':completion:*' completer _expand_alias _complete _ignored
to your ~/.zshrc should work.
(To be save you can print the current setting with zstyle -L ':completion:*' completer, _expand_alias has to come before _complete)
If you now type llTab, zsh will replace it with ls -l immediatelly.
Note: in both cases the cursor has to be in or just after the alias for the replacement to happen. This also means you have to type the whole alias or backspace if automatically completed (_completer adds a space after successful completion)