Docu review done: Thu 29 Jun 2023 12:36:32 CEST

Table of content

Builtin Commands

URL: https://linux.die.net/man/1/zshbuiltins

Merge output of command into oneline

To merge the output of a command in one line, you can let zsh do that for you by running it like that: ${(f)$(<command>)}

# without (f)
$ echo "${$(ls)}"
./
../
myindexfile.html
testmanifest.pp

# with (f)
$ echo "${(f)$(ls)}"
./ ../ myindexfile.html testmanifest.pp

Special Builtins

In zsh you can stack variable calls with pointing to the content of the beneath data.

Sample html file:

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
        <meta name="Content-Style" content="text/css">
        <style type="text/css">
               p       { margin-top: 0; margin-bottom: 0; vertical-align: top }
               pre     { margin-top: 0; margin-bottom: 0; vertical-align: top }
               table   { margin-top: 0; margin-bottom: 0; vertical-align: top }
               h1      { text-align: center }
               body    { color: #0CCC68 ;  background-color: #000000; }
        </style>
    </head>
    <body>
        <h1>42</h1>
    </body>
</html>
$ echo ${=${${(f)"$(cat ./myindexfile.html(n))"}##<html>}%>}
#                                                 ^       ^ this will remove < at the end of each
#                                                 | this will remove <html> at the start of each
<head <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII" <meta name="Content-Style" content="text/css" <style type="text/css" p { margin-top: 0; margin-bottom: 0; vertical-align: top } pre { margin-top: 0; margin-bottom: 0; vertical-align: top } table { margin-top: 0; margin-bottom: 0; vertical-align: top } h1 { text-align: center } body { color: #0CCC68 ; background-color: #000000; } </style </head <body <h1>42</h1 </body </html

Expansion

Sometimes you want to write scripts which are working for bash and zsh. There you will very qickly figure out, that in some things work a bit differnt. Like in zsh, the variable expansion is not splited by default, but command expansions are.

This would work for example in bash, but not in zsh:

$ asdf="qwer asdf zxcv"
$ for i in $asdf ; do echo $asdf ; done
qwer
asdf
zxcv

If you run the same commands in zsh, you will get something like that:

$ asdf="qwer asdf zxcv"
$ for i in $asdf ; do echo $asdf ; done
qwer asdf zxcv

To avoide it, you could transform the variable into a command and it will work for both shells

$ asdf="qwer asdf zxcv"
$ for i in $(echo $asdf) ; do echo $asdf ; done
qwer
asdf
zxcv

Custom Tab Completion

To create your own tab completion for a script you can do the following thing. Create the function which fetches the data like the sample below

This will fetch the host entries from your local .ssh/config

function _ssht_compl_zsh() {
    compadd ${=${${${${${(f)"$(cat ~/.ssh/config(n) /dev/null)"}##[A-Z][a-z]* }##  *[A-Z][a-z]* *}%%[# ]*}%%--*}//,/ }
}

Now that we have our function, you just need to attach it to the command which is done with compdef <functionname> <executeable/alias> For our sample above, it would look like this:

compdef _ssht_compl_zsh _ssht

Next setp is to just source the file what you have written in your zsh.rc or where ever your zsh sources files and start a shell

source ~/.config/zsh/ssht_completion.zsh

Now you can tab it, have fun

$ ssht<tab><tab>
zsh: do you wish to see all 1337 possibilities (177 lines)?
server1  server2  server3  server4  server5  server6
server7  server8  server9  server10 server11 server12
...
$ ssht server101<tab>
server101   server1010  server1010  server1012
server1013  server1014  server1015  server1016
server1017  server1018  server1019
...
$ ssht server100<tab>
$ ssht server1001

List content of functions

As you may probably know, the command type in bash, lets you see the content of functions which got sourced. zsh has a equivalent, called whence

$ whence -f <function_name>
<function_name> () {
    <content of function>
}