<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>r &amp;mdash; musicmatzes blog</title>
    <link>https://beyermatthias.de/tag:r</link>
    <description></description>
    <pubDate>Thu, 07 May 2026 14:52:49 +0200</pubDate>
    <item>
      <title>Prompt me</title>
      <link>https://beyermatthias.de/prompt-me</link>
      <description>&lt;![CDATA[I love minimalism. I had my prompt long time just beeing a simple status&#xA;indicator and a pipe, everything which was not that important was ripped out.&#xA;&#xA;At some point, I decided that I need at least the time in my prompt, but I&#xA;wanted it to be on the right side. I managed to do it. And now, as I have more&#xA;machines, I need to put the hostname in the prompt. I also added a shell-level&#xA;indicator in the prompt, a &#34;How many jobs are in the background&#34; indicator was&#xA;also added some time ago.&#xA;&#xA;This post wants to elaborate how this all was achived while keeping the&#xA;prompt itself as minimal as possible. At least from my point of view.&#xA;&#xA;!-- more --&#xA;&#xA;Requirements&#xA;&#xA;So first, the requirements:&#xA;&#xA;Indicators&#xA;    Did the last command work?&#xA;    How many background jobs do you have?&#xA;    How many shell levels are there?&#xA;What&#39;s the current hostname?&#xA;What&#39;s the time?&#xA;Where am I?&#xA;&#xA;Also, the bash shouldn&#39;t flatter around. I want to have my commands in one&#xA;column, straight down the line.&#xA;&#xA;The prompt&#xA;&#xA;So, that&#39;s what my prompt looks like:&#xA;&#xA;&lt;img&#xA;    src=&#34;/2015-01-18-prompt-me.png&#34;&#xA;    alt=&#34;my prompt&#34;&#xA;    style=&#34;width:700px&#34;/  As you can see, my hostname is one the left but almost everything else is on&#xA;the right. Well, there&#39;s actually really much on the left!&#xA;&#xA;First, there is the hostname. I managed to get the hostname into a box which&#xA;is always 8 characters long. So longer host names will fit in there as well&#xA;and don&#39;t break the pipe bar at the end of the left side of the prompt.&#xA;&#xA;Also, the hostname will be green whenever the last command succeeded, turning&#xA;into red if the last command failed.&#xA;&#xA;After the hostname we have the pipe, which is simply the delimiter between my&#xA;hostname and my commands. Well, not quite. It also doubles itself in a&#xA;subshell, tribles itself in a sub-subshell and so on.&#xA;&#xA;On the right side there is another pipe, but this one flutters. After that, we&#xA;have another two delimiters which could be removed, but I keep them. Then&#xA;there is the current branch whenever I&#39;m inside a git directory, the current&#xA;working directory the number of jobs and the time.&#xA;&#xA;Howto&#xA;&#xA;To achive this, you need to write a bit of bash code into your .bashrc,&#xA;that&#39;s all:&#xA;&#xA;~/.bashrc&#xA;&#xA;printfnchr() {&#xA;    for i in seq 1 $1; do echo -ne &#34;$2&#34;; done&#xA;}&#xA;&#xA;shlvl() {&#xA;    # I&#39;m always on shell level 4 here, login, xserver, terminal, bash&#xA;    # so subtract 3 to get 1 in a normal (non-nested) shell&#xA;    echo $((SHLVL - 3))&#xA;}&#xA;&#xA;PS1=$&#39;$(if [[ &#34;$?&#34; == &#34;0&#34; ]];then echo &#34;\[\033[32m\]&#34;; else echo &#34;\[\033[31m\]&#34;; fi) $(printf &#34;%8s&#34; &#34;($HOSTNAME)&#34;)\e[0m $(printfnchr $(shlvl) &#34;\u2502&#34;) &#39;&#xA;PS2=$&#39;\[\033[32m\] $(printf &#34;%8s&#34; &#34;($HOSTNAME)&#34;) #  \e[0m \u2502 &#39;&#xA;&#xA;rightpromptstring() {&#xA;    local tmp=$?&#xA;    local dirty=$([[ $(git diff --shortstat 2  /dev/null | tail -n 1) != &#34;&#34; ]] &amp;&amp;&#xA;        echo &#34; &#34;)&#xA;    local g=$([[ $(git branch 2  /dev/null) ]] &amp;&amp;&#xA;        echo &#34; ($(git describe --all | sed &#39;s/^[a-zA-Z]\///&#39;)) &#34;)&#xA;    local p=$(pwd | sed &#34;s:^$HOME:~:&#34; | rev | cut -d/ -f 1 | rev)&#xA;    local j=$(jobs | wc -l)&#xA;    local d=$(date +%H:%M)&#xA;&#xA;    local r=$(echo -n &#34;\u2502 \033[1;30m&lt;&lt;$dirty$g$p [$j] [$d]\033[0m&#34;)&#xA;&#xA;    local rl=${#r}&#xA;    local t=$(tput cols)&#xA;    let &#34;p = $t - $rl + 22&#34;&#xA;    printf -v sp &#34;%*s&#34; $p &#39; &#39;&#xA;    echo -ne &#34;$sp$r\r&#34;&#xA;    return $tmp&#xA;}&#xA;&#xA;PROMPTCOMMAND=rightpromptstring&#xA;&#xA;It is not as complicated as it seems and I&#39;m sure there&#39;s room for&#xA;optimization here and there, but for me it works and it is fast.&#xA;&#xA;Of course, the printfnchr function and also the shlvl function could have&#xA;been placed right in the PS1 variable, but I want to keep them, maybe I can&#xA;reuse them later!&#xA;&#xA;The rightpromptstring function is a beast, I know. This would be my first&#xA;point if I had to optimize this whole thing, but I don&#39;t need to, so there is&#xA;no need to.&#xA;&#xA;---&#xA;&#xA;I won&#39;t go into detail how things work, I assume you know bash. Anyways, feel&#xA;free to ask me questions about this!&#xA;&#xA;---&#xA;&#xA;Edit:&#xA;&#xA;To have the pipe character also when logged in via SSH, you have to modify the&#xA;shlvl function like this:&#xA;&#xA;shlvl() {&#xA;    # I&#39;m always on shell level 4 here, login, xserver, terminal, bash&#xA;    # so subtract 3 to get 1 in a normal (non-nested) shell&#xA;    if [ -z &#34;$SSHCLIENT&#34; ]&#xA;    then&#xA;        echo $((SHLVL - 3))&#xA;    else&#xA;        echo $SHLVL&#xA;    fi&#xA;}&#xA;&#xA;tags:  #linux #bash&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I love minimalism. I had my prompt long time just beeing a simple status
indicator and a pipe, everything which was not that important was ripped out.</p>

<p>At some point, I decided that I need at least the time in my prompt, but I
wanted it to be on the right side. I managed to do it. And now, as I have more
machines, I need to put the hostname in the prompt. I also added a shell-level
indicator in the prompt, a “How many jobs are in the background” indicator was
also added some time ago.</p>

<p>This post wants to elaborate how this all was achived while keeping the
prompt itself as minimal as possible. At least from my point of view.</p>



<h1 id="requirements" id="requirements">Requirements</h1>

<p>So first, the requirements:</p>
<ul><li>Indicators
<ul><li>Did the last command work?</li>
<li>How many background jobs do you have?</li>
<li>How many shell levels are there?</li></ul></li>
<li>What&#39;s the current hostname?</li>
<li>What&#39;s the time?</li>
<li>Where am I?</li></ul>

<p>Also, the bash shouldn&#39;t flatter around. I want to have my commands in one
column, straight down the line.</p>

<h1 id="the-prompt" id="the-prompt">The prompt</h1>

<p>So, that&#39;s what my prompt looks like:</p>

<p><img src="/2015-01-18-prompt-me.png" alt="my prompt" style="width:700px"/></p>

<p>As you can see, my hostname is one the left but almost everything else is on
the right. Well, there&#39;s actually really much on the left!</p>

<p>First, there is the hostname. I managed to get the hostname into a box which
is always 8 characters long. So longer host names will fit in there as well
and don&#39;t break the pipe bar at the end of the left side of the prompt.</p>

<p>Also, the hostname will be green whenever the last command succeeded, turning
into red if the last command failed.</p>

<p>After the hostname we have the pipe, which is simply the delimiter between my
hostname and my commands. Well, not quite. It also doubles itself in a
subshell, tribles itself in a sub-subshell and so on.</p>

<p>On the right side there is another pipe, but this one flutters. After that, we
have another two delimiters which could be removed, but I keep them. Then
there is the current branch whenever I&#39;m inside a git directory, the current
working directory the number of jobs and the time.</p>

<h1 id="howto" id="howto">Howto</h1>

<p>To achive this, you need to write a bit of bash code into your <code>.bashrc</code>,
that&#39;s all:</p>

<pre><code class="language-bash">#
# ~/.bashrc
#

printfnchr() {
    for i in `seq 1 $1`; do echo -ne &#34;$2&#34;; done
}

shlvl() {
    # I&#39;m always on shell level 4 here, login, xserver, terminal, bash
    # so subtract 3 to get 1 in a normal (non-nested) shell
    echo $((SHLVL - 3))
}

PS1=$&#39;$(if [[ &#34;$?&#34; == &#34;0&#34; ]];then echo &#34;\[\033[32m\]&#34;; else echo &#34;\[\033[31m\]&#34;; fi) $(printf &#34;%8s&#34; &#34;($HOSTNAME)&#34;)\e[0m $(printfnchr $(shlvl) &#34;\u2502&#34;) &#39;
PS2=$&#39;\[\033[32m\] $(printf &#34;%8s&#34; &#34;($HOSTNAME)&#34;) #&gt;\e[0m \u2502 &#39;

rightpromptstring() {
    local tmp=$?
    local dirty=$([[ $(git diff --shortstat 2&gt;/dev/null | tail -n 1) != &#34;&#34; ]] &amp;&amp;
        echo &#34; *&#34;)
    local g=$([[ $(git branch 2&gt;/dev/null) ]] &amp;&amp;
        echo &#34; ($(git describe --all | sed &#39;s/^[a-zA-Z]*\///&#39;)) &#34;)
    local p=$(pwd | sed &#34;s:^$HOME:~:&#34; | rev | cut -d/ -f 1 | rev)
    local j=$(jobs | wc -l)
    local d=$(date +%H:%M)

    local r=$(echo -n &#34;\u2502 \033[1;30m&lt;&lt;$dirty$g$p [$j] [$d]\033[0m&#34;)

    local rl=${#r}
    local t=$(tput cols)
    let &#34;p = $t - $rl + 22&#34;
    printf -v sp &#34;%*s&#34; $p &#39; &#39;
    echo -ne &#34;$sp$r\r&#34;
    return $tmp
}

PROMPT_COMMAND=rightpromptstring
</code></pre>

<p>It is not as complicated as it seems and I&#39;m sure there&#39;s room for
optimization here and there, but for me it works and it is fast.</p>

<p>Of course, the <code>printfnchr</code> function and also the <code>shlvl</code> function could have
been placed right in the <code>PS1</code> variable, but I want to keep them, maybe I can
reuse them later!</p>

<p>The <code>rightpromptstring</code> function is a beast, I know. This would be my first
point if I had to optimize this whole thing, but I don&#39;t need to, so there is
no need to.</p>

<hr>

<p>I won&#39;t go into detail how things work, I assume you know bash. Anyways, feel
free to ask me questions about this!</p>

<hr>

<p>Edit:</p>

<p>To have the pipe character also when logged in via SSH, you have to modify the
<code>shlvl</code> function like this:</p>

<pre><code class="language-bash">shlvl() {
    # I&#39;m always on shell level 4 here, login, xserver, terminal, bash
    # so subtract 3 to get 1 in a normal (non-nested) shell
    if [ -z &#34;$SSH_CLIENT&#34; ]
    then
        echo $((SHLVL - 3))
    else
        echo $SHLVL
    fi
}

</code></pre>

<p>tags:  <a href="https://beyermatthias.de/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a> <a href="https://beyermatthias.de/tag:bash" class="hashtag"><span>#</span><span class="p-category">bash</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/prompt-me</guid>
      <pubDate>Sun, 18 Jan 2015 16:37:29 +0100</pubDate>
    </item>
    <item>
      <title>Bash right prompt</title>
      <link>https://beyermatthias.de/bash-right-prompt</link>
      <description>&lt;![CDATA[I switched to i3 recently and therefor reconfigured my whole system in manner of&#xA;apperance. I really like it now, as it uses grey as basic color. Everything is&#xA;grey: My terminal (xterm, bash), my editor (vim), my IRC client (irssi), my&#xA;music player (ncmpcpp). But what I like most by far, is my prompt.&#xA;&#xA;!-- more --&#xA;&#xA;Bash it to the right&#xA;&#xA;I always hated the flutter of my bash prompt when diving into directories:&#xA;&#xA;    ~ $ cd foo&#xA;    ~/foo &amp;amp; cd bar&#xA;    ~/foo/bar $ cd&#xA;    ~ $&#xA;&#xA;But now, I finally reconfigured it to be in a straigt line:&#xA;&#xA;    :  | cd foo&#xA;    :  | cd bar&#xA;    :  | cd&#xA;&#xA;And the path is now on the right side (I can&#39;t show it in the example,&#xA;unfortunately).&#xA;&#xA;There is not much magic in it... but let me show you:&#xA;&#xA;The magic&#xA;&#xA;The PS1 variable is the one shelter for the prompt. I configured it to be just&#xA;&#xA;    :  |&#xA;&#xA;but if the last command failed, it uses the sad smilie:&#xA;&#xA;    :&lt; |&#xA;&#xA;(you can do this with Unicode smilies as well!) There is not much magic in it.&#xA;The pipe symbol is a Unicode character (\u2502) for me, so I get a straight line&#xA;without gaps between the lines.&#xA;&#xA;The real magic comes now! There is also a bash variable for a command which gets&#xA;executed for a prompt. And I abuse this variable a little bit. But first, we&#xA;have to write the command (actually a bash function):&#xA;&#xA;    rightpromptstring() {&#xA;        local tmp=$?&#xA;        local dirty=$([[ $(git diff --shortstat 2  /dev/null | tail -n 1) != &#34;&#34; ]] &amp;&amp;&#xA;            echo &#34; &#34;)&#xA;        local g=$([[ $(git branch 2  /dev/null) ]] &amp;&amp;&#xA;            echo &#34; ($(git name-rev HEAD | cut -d &#34; &#34; -f 2)) &#34;)&#xA;        local p=$(pwd | sed &#34;s:^$HOME:~:&#34;)&#xA;        local j=$(jobs | wc -l)&#xA;        local d=$(date +%H:%M)&#xA;        local r=$(echo -n &#34;\u2502 \033[1;30m&amp;lt;&lt;$dirty$g$p [$j] [$d]\033[0m&#34;)&#xA;        local rl=${#r}&#xA;        local t=$(tput cols)&#xA;        let &#34;p = $t - $rl&#34;&#xA;        printf -v sp &#34;%s&#34; $p &#39; &#39;&#xA;        echo -ne &#34;$sp$r\r&#34;&#xA;        return $tmp&#xA;    }&#xA;&#xA;So, what happens in here? The first line is for saving the return value of the&#xA;previous command. We need it to be returned lateron, as the smilie from PS1&#xA;won&#39;t work if we don&#39;t return it.&#xA;&#xA;The next few lines do a bit of git magic, to include the current branch and a&#xA;asterisk if the repository is &#34;dirty&#34;. The variable p gets the path, but if&#xA;I&#39;m in my home directory, it gets replaced by the tilde. The j variable gets&#xA;the number of jobs in the bash, as I always want this to be printed somewhere.&#xA;The d gets the current time.&#xA;&#xA;The r variable now gets the string which represents the right prompt. It also&#xA;gets the pipe character (actually the Unicode character \u2502) and some  color&#xA;stuff. Then, the rl variable gets the length of the string in r. The t&#xA;variable gets the number of colums, which is required for printing spaces until&#xA;we are at the right side (the printf part prints spaces to the variable sp).&#xA;Then, the spaces and the right prompt get printed. And then simply a \r for&#xA;carriage-return.&#xA;&#xA;Afterwards we return the stored exit code of the application which just exited&#xA;and that&#39;s it.&#xA;&#xA;Now, just set the prompt command variable:&#xA;&#xA;    PROMTP_COMMAND=rightpromptstring&#xA;&#xA;And that&#39;s it.&#xA;&#xA;I know, the rightpromptstring function is a bit ugly and I bet it can be&#xA;improved, but it works very good for me! Feel free to send me patches!&#xA;&#xA;tags:  #bash #programming #linux&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I switched to i3 recently and therefor reconfigured my whole system in manner of
apperance. I really like it now, as it uses grey as basic color. Everything is
grey: My terminal (xterm, bash), my editor (vim), my IRC client (irssi), my
music player (ncmpcpp). But what I like most by far, is my prompt.</p>



<h1 id="bash-it-to-the-right" id="bash-it-to-the-right">Bash it to the right</h1>

<p>I always hated the flutter of my bash prompt when diving into directories:</p>

<p>    ~ $ cd foo
    ~/foo &amp; cd bar
    ~/foo/bar $ cd
    ~ $</p>

<p>But now, I finally reconfigured it to be in a straigt line:</p>

<p>    :&gt; | cd foo
    :&gt; | cd bar
    :&gt; | cd</p>

<p>And the path is now on the right side (I can&#39;t show it in the example,
unfortunately).</p>

<p>There is not much magic in it... but let me show you:</p>

<h1 id="the-magic" id="the-magic">The magic</h1>

<p>The <code>PS1</code> variable is the one shelter for the prompt. I configured it to be just</p>

<p>    :&gt; |</p>

<p>but if the last command failed, it uses the sad smilie:</p>

<p>    :&lt; |</p>

<p>(you can do this with Unicode smilies as well!) There is not much magic in it.
The pipe symbol is a Unicode character (\u2502) for me, so I get a straight line
without gaps between the lines.</p>

<p>The real magic comes now! There is also a bash variable for a command which gets
executed for a prompt. And I abuse this variable a little bit. But first, we
have to write the command (actually a bash function):</p>

<p>    rightpromptstring() {
        local tmp=$?
        local dirty=$([[ $(git diff —shortstat 2&gt;/dev/null | tail -n 1) != “” ]] &amp;&amp;
            echo “ “)
        local g=$([[ $(git branch 2&gt;/dev/null) ]] &amp;&amp;
            echo “ ($(git name-rev HEAD | cut -d ” “ -f 2)) “)
        local p=$(pwd | sed “s:^$HOME:~:“)
        local j=$(jobs | wc -l)
        local d=$(date +%H:%M)
        local r=$(echo -n “\u2502 \033[1;30m&lt;&lt;$dirty$g$p [$j] [$d]\033[0m”)
        local rl=${<a href="https://beyermatthias.de/tag:r" class="hashtag"><span>#</span><span class="p-category">r</span></a>}
        local t=$(tput cols)
        let “p = $t – $rl”
        printf -v sp “%s” $p &#39; &#39;
        echo -ne “$sp$r\r”
        return $tmp
    }</p>

<p>So, what happens in here? The first line is for saving the return value of the
previous command. We need it to be returned lateron, as the smilie from <code>PS1</code>
won&#39;t work if we don&#39;t return it.</p>

<p>The next few lines do a bit of git magic, to include the current branch and a
asterisk if the repository is “dirty”. The variable <code>p</code> gets the path, but if
I&#39;m in my home directory, it gets replaced by the tilde. The <code>j</code> variable gets
the number of jobs in the bash, as I always want this to be printed somewhere.
The <code>d</code> gets the current time.</p>

<p>The <code>r</code> variable now gets the string which represents the right prompt. It also
gets the pipe character (actually the Unicode character \u2502) and some  color
stuff. Then, the <code>rl</code> variable gets the length of the string in <code>r</code>. The <code>t</code>
variable gets the number of colums, which is required for printing spaces until
we are at the right side (the <code>printf</code> part prints spaces to the variable <code>sp</code>).
Then, the spaces and the right prompt get printed. And then simply a <code>\r</code> for
carriage-return.</p>

<p>Afterwards we return the stored exit code of the application which just exited
and that&#39;s it.</p>

<p>Now, just set the prompt command variable:</p>

<p>    PROMTP_COMMAND=rightpromptstring</p>

<h2 id="and-that-s-it" id="and-that-s-it">And that&#39;s it.</h2>

<p>I know, the <code>rightpromptstring</code> function is a bit ugly and I bet it can be
improved, but it works very good for me! Feel free to send me patches!</p>

<p>tags:  <a href="https://beyermatthias.de/tag:bash" class="hashtag"><span>#</span><span class="p-category">bash</span></a> <a href="https://beyermatthias.de/tag:programming" class="hashtag"><span>#</span><span class="p-category">programming</span></a> <a href="https://beyermatthias.de/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/bash-right-prompt</guid>
      <pubDate>Mon, 22 Sep 2014 18:36:16 +0200</pubDate>
    </item>
  </channel>
</rss>