zshell use variable variables to get value in hask tables - zsh

Make the following function output the same as echo ${clash[http]}
#!/usr/bin/zsh
typeset -A clash=( ["http"]=7890 ["socks"]=7891 )
function getValue() {
echo ${(P)1}
}
getValue clash http

function getValue() {
typeset -A hashTab=(${(kvP)1})
echo $hashTab[$2]
}

Related

ZSH Custom function like repeat

I have a command which I want to repeat when a certain error occurs. To make this generic I would like to come up with a function that can take any other function to basically wrap that behaviour, very similar to repeat in ZSH.
So what I would like to have is something like this:
repeatWhenError { someFunction() }
This would repeat the function within the braces until it succeeds successfully. Is there an easy way to implement this in ZSH?
From my dotfiles:
retry () {
retry-limited 0 "$#"
}
retry-limited () {
retry-limited-eval "$1" "$(gquote "${#:2}")"
}
retry-limited-eval () {
local retry_sleep="${retry_sleep:-0.1}"
local limit=0
local ecode=0
until {
test "$1" -gt 0 && test $limit -ge "$1"
} || {
eval "${#:2}" && ecode=0
}
do
ecode="$?"
ecerr Tried eval "${#:2}" "..."
sleep $retry_sleep
limit=$((limit+1))
done
return "$ecode"
}
gquote () {
\noglob : Use this to control quoting centrally.
print -r -- "${(q+#)#}"
}
ecerr () {
print -r -- "$#" >&2
}
Usage:
retry someFunction

How to do a set -u locally in zsh?

I would like to turn on
set -u
only inside the body of one zsh function. At the end of the function, it should be restored to its previous state.
I reckon that I have to do a
setopt localoptions ????
inside the function, but what comes at the place of the ???? ? From the zsh manpage, I found an explanation for the option UNSET, but this corresponds to set +u, not set -u.
UPDATE:
Based on the answer given by chepner, I also tried:
set -u
foo() {
setopt NO_UNSET LOCAL_OPTIONS
echo $xx
}
bar() {
setopt localoptions nounset
echo $xx
}
But both functions, when invoked, abort with xx: parameter not set
set -u is equivalent to setopt no_unset and set +u is equivalent to setopt unset. You've inverted the meaning.
set -u
foo() {
setopt local_options unset
echo $xx
}
foo # prints an empty line
echo $xx # errors out
Documentation references:
Long option documentation: UNSET is equivalent to +u (not to -u)
Single letter option documentation: -u is equivalent to NO_UNSET (not to UNSET)
The inverse of the UNSET option is NO_UNSET
foo () {
setopt NO_UNSET LOCAL_OPTIONS
...
}

How to print return code conditionally in oh my zsh theme?

I'm trying to conditionally print return code in custom oh-my-zsh theme but somehow I'm failling. I'm stuck with:
function get_rc {
rc=$(echo -e "${return_code}" | tr -d '[:space:]' )
[[ "${rc}" == "130" ]] && echo "${rc}" && return
echo "'${rc}'"
}
Where it's printing the quouted version all the time.
What's wrong with my approach?

How to pass a map to a Jenkins Pipeline global function?

I have a global function like this:
def myStep(Closure body) {
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
body()
echo config.name // works
echo config.configure // is null
}
Which is called like this:
myStep {
name = 'linux-build'
configure = [os: 'linux', dir: 'build']
echo "myStep"
}
Normal variables (name) are working but the passed map (configure) does not. Maybe that is because of def config = [:]? How can I access the map inside the function?
The Map is really passed the problem is that echo don't know how to deal with Map in order to print in the console (seems that echo only prints string).
So you can try with the follow code instead:
echo config.configure.toString() // prints [os:linux, dir:build]
Or using GString:
echo "${config.configure}" // prints [os:linux, dir:build]
Or using println:
println config.configure // prints {os=linux, dir=build}
So the thing is that Map is there so you can access config.configure.os or config.configure.dir without problems, try with the follow code in the jenkins-pipeline:
def myStep(Closure body) {
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
body()
echo config.name // works
echo config.configure.os // prints linux
echo config.configure.dir // prints buid
println config.configure // prints {os=linux, dir=build}
}
myStep {
name = 'linux-build'
configure = [os: 'linux', dir: 'build']
echo "myStep"
}
It shows the follow result in the Output console:
[Pipeline] echo
myStep
[Pipeline] echo
linux-build
[Pipeline] echo
linux
[Pipeline] echo
build
[Pipeline] echo
{os=linux, dir=build}
[Pipeline] End of Pipeline
Finished: SUCCESS

last n elements of an array

I'm trying to write a function that will print out the last 3 elements of $PWD, with a '...' beforehand if there are more than 3 elements.
e.g.
/home/nornagon/src --> ~/src
/home/nornagon/src/foo/bar/baz --> ...foo/bar/baz
This is my code so far, but $foo[-3,-1] doesn't work if the array has too few elements in it.
function custom_pwd() {
d=${PWD/#$HOME/\~}
d=(${(s:/:)d})
echo $d[-4,-1]
}
The zsh already has some nifty prompt processing available with print's -P option. This should do the trick:
custom_pwd() {
d=$(print -P '%3~')
case $d in
('~'*|/*) echo "$d";;
(*) echo "...$d"
esac
}
See man zshmisc, section "EXPANSION OF PROMPT SEQUENCES" for the gory details.
Here's what I came up with, though it's not terribly elegant:
function custom_pwd() {
local d slash
d=${PWD/#$HOME/\~}
case $d in
/*) slash=/ ;;
*) slash= ;;
esac
d=(${(s:/:)d})
d[1]=$slash$d[1]
num=$#d
ellipsis=
if (( num > 3 )); then num=3; ellipsis='…'; fi
echo $ellipsis${(j./.)d[-$num,-1]}
}

Resources