<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>bash &amp;mdash; musicmatzes blog</title>
    <link>https://beyermatthias.de/tag:bash</link>
    <description></description>
    <pubDate>Tue, 28 Jul 2026 14:07:53 +0200</pubDate>
    <item>
      <title>The annoyance of programming language tutorials - or: Why learning rust feels amazing</title>
      <link>https://beyermatthias.de/the-annoyance-of-programming-language-tutorials-or-why-learning-rust-feels</link>
      <description>&lt;![CDATA[This article is about the annoyance of programming language tutorials. First, I&#xA;will argue why learning new programming languages always feels a bit like a pain&#xA;to me. And then I will tell you why learning Rust was different.&#xA;&#xA;!-- more --&#xA;&#xA;I know a few programming languages. I&#39;ve done things in C, Ruby, Java, Python,&#xA;PHP, C++, Bash, Lisp (Racket, actually), Haskell, LaTeX, Nix, Make, Lua and&#xA;JavaScript.&#xA;&#xA;small&#xA;    *: Only a bit, but still enough to say &#34;I&#39;ve done things in this language&#34;&#xA;/small&#xA;&#xA;When I started learning programming, I learned Java and shortly after that Ruby.&#xA;Both languages have their oddities, but besides their overall concept&#xA;(imperative programming and object orientated programming) they are both rather&#xA;easy to learn.&#xA;After that I learned C. Learning C was a new world for me back then, as I&#xA;only knew object orientation. I cannot remember which resources I&#39;ve been using&#xA;learning C, though I remember it was a pain. I had a good friend helping me,&#xA;which was awesome, though I struggled a lot with the new concept.&#xA;&#xA;After learning C, I did a fair amount of PHP. Learning PHP was simple (I&#xA;actually did it in one weekend and a few thousand lines), though it again was a&#xA;pain. It was a pain because of the tutorials and resources. And that&#39;s the point&#xA;I want to discuss here.&#xA;&#xA;All other programming languages I&#39;ve been learning so far were painful to learn.&#xA;Not because of their concepts (see Haskell, functional programming at all), but&#xA;because of the resources. Haskell is a really good example here. There is&#xA;exactly one resource I enjoyed while learning Haskell, and that&#39;s&#xA;&#34;Learn you a Haskell for great good&#34;.&#xA;And why? Because it takes your hand and shows you the new world. It is good&#xA;because the concept of functional programming is new for most people reading&#xA;this resource. Learning JavaScript, Bash, Lua or Python sucks because you&#xA;already know what an object is. You know what a function or method is and you&#xA;know that the basic syntax for arithmetic is the very same as in the languages&#xA;you&#39;ve been using by now. But all tutorials expect you start from zero - which&#xA;is fine if you&#39;re actually starting from zero, but most of the time you&#39;re not.&#xA;After learning Java and Ruby I understood what OOP is (actually not after&#xA;learning Java, but after learning Ruby, because Java isn&#39;t a fully object&#xA;oriented language in my opinion).&#xA;&#xA;So, learning Haskell was kinda amazing. Learn you a Haskell is a really great&#xA;book and if you want to learn Haskell, you really should read it. But what was&#xA;even a better experience was learning Rust.&#xA;&#xA;So why is that? It is because Rust is a new concept and the old concept&#xA;(imperative programming). Learning Rust is not like learning Python after&#xA;learning Ruby. It is like Learning Haskell after learning Racket. The concept&#xA;behind the language is kinda the same, though it is different in most details.&#xA;&#xA;Plus, the Rust tutorials and resources are freakin&#39; awesome. Let me repeat that.&#xA;The tutorials and documentation of the tools, libraries and everything, the&#xA;resources on how to do things, are awesome!&#xA;&#xA;Every documentation for each library looks exactly the same, which is a huge&#xA;advantage over other languages library documentations. cargo, the Rust&#xA;build-tool builds the documentation locally for you, if you want that. So&#xA;working offline after you fetched the dependencies or your project (also via&#xA;cargo) is no hassle. Building a new project with cargo is absolutely painless,&#xA;its literally just executing a command, editing a textfile and executing another&#xA;command (setting up the project, writing down dependencies and meta information&#xA;about the project and building the project, which fetches the dependencies).&#xA;&#xA;So really, if you want to learn a new programming language, check out Rust. I&#xA;haven&#39;t even talked about its language features, and I will not, as this is not&#xA;the goal of this article. This article is about resources and tutorials. And my&#xA;conclusion is:&#xA;&#xA;All programming language tutorials suck. Except the Rust language tutorial.&#xA;tags:  #programming #open source #bash #c #c++ #haskell #nix #racket #rust #shell&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>This article is about the annoyance of programming language tutorials. First, I
will argue why learning new programming languages always feels a bit like a pain
to me. And then I will tell you why learning Rust was different.</p>



<p>I know a few programming languages. I&#39;ve done things in C, Ruby, Java, Python<em>,
PHP, C++, Bash, Lisp</em> (Racket<em>, actually), Haskell</em>, LaTeX, Nix, Make, Lua* and
JavaScript*.</p>

<p><small>
    *: Only a bit, but still enough to say “I&#39;ve done things in this language”
</small></p>

<p>When I started learning programming, I learned Java and shortly after that Ruby.
Both languages have their oddities, but besides their overall concept
(imperative programming and object orientated programming) they are both rather
easy to learn.
After that I learned C. Learning C was a new world for me back then, as I
only knew object orientation. I cannot remember which resources I&#39;ve been using
learning C, though I remember it was a pain. I had a good friend helping me,
which was awesome, though I struggled a lot with the new concept.</p>

<p>After learning C, I did a fair amount of PHP. Learning PHP was simple (I
actually did it in one weekend and a few thousand lines), though it again was a
pain. It was a pain because of the tutorials and resources. And that&#39;s the point
I want to discuss here.</p>

<p>All other programming languages I&#39;ve been learning so far were painful to learn.
Not because of their concepts (see Haskell, functional programming at all), but
because of the resources. Haskell is a really good example here. There is
exactly <em>one</em> resource I enjoyed while learning Haskell, and that&#39;s
<a href="http://learnyouahaskell.com/">“Learn you a Haskell for great good”</a>.
And why? Because it <em>takes your hand and shows you the <strong>new</strong> world</em>. It is good
because the concept of functional programming is <em>new</em> for most people reading
this resource. Learning JavaScript, Bash, Lua or Python <em>sucks</em> because you
already know what an object is. You know what a function or method is and you
know that the basic syntax for arithmetic is the very same as in the languages
you&#39;ve been using by now. But all tutorials expect you start from zero – which
is fine if you&#39;re actually starting from zero, but most of the time you&#39;re not.
After learning Java and Ruby I understood what OOP is (actually not after
learning Java, but after learning Ruby, because Java isn&#39;t a fully object
oriented language in my opinion).</p>

<p>So, learning Haskell was kinda amazing. Learn you a Haskell is a really great
book and if you want to learn Haskell, you really should read it. But what was
even a better experience was learning Rust.</p>

<p>So why is that? It is because Rust is a new concept <em>and</em> the old concept
(imperative programming). Learning Rust is not like learning Python after
learning Ruby. It is like Learning Haskell after learning Racket. The concept
behind the language is <em>kinda</em> the same, though it is different in most details.</p>

<p>Plus, the Rust tutorials and resources are freakin&#39; awesome. Let me repeat that.
The tutorials and documentation of the tools, libraries and everything, the
resources on how to do things, are <em>awesome</em>!</p>

<p>Every documentation for each library looks exactly the same, which is a <em>huge</em>
advantage over other languages library documentations. <code>cargo</code>, the Rust
build-tool builds the documentation locally for you, if you want that. So
working offline after you fetched the dependencies or your project (also via
cargo) is no hassle. Building a new project with cargo is absolutely painless,
its literally just executing a command, editing a textfile and executing another
command (setting up the project, writing down dependencies and meta information
about the project and building the project, which fetches the dependencies).</p>

<p>So really, if you want to learn a new programming language, check out Rust. I
haven&#39;t even talked about its language features, and I will not, as this is not
the goal of this article. This article is about resources and tutorials. And my
conclusion is:</p>

<p>All programming language tutorials suck. Except the Rust language tutorial.
tags:  <a href="https://beyermatthias.de/tag:programming" class="hashtag"><span>#</span><span class="p-category">programming</span></a> <a href="https://beyermatthias.de/tag:open" class="hashtag"><span>#</span><span class="p-category">open</span></a> source <a href="https://beyermatthias.de/tag:bash" class="hashtag"><span>#</span><span class="p-category">bash</span></a> <a href="https://beyermatthias.de/tag:c" class="hashtag"><span>#</span><span class="p-category">c</span></a> <a href="https://beyermatthias.de/tag:c" class="hashtag"><span>#</span><span class="p-category">c</span></a>++ <a href="https://beyermatthias.de/tag:haskell" class="hashtag"><span>#</span><span class="p-category">haskell</span></a> <a href="https://beyermatthias.de/tag:nix" class="hashtag"><span>#</span><span class="p-category">nix</span></a> <a href="https://beyermatthias.de/tag:racket" class="hashtag"><span>#</span><span class="p-category">racket</span></a> <a href="https://beyermatthias.de/tag:rust" class="hashtag"><span>#</span><span class="p-category">rust</span></a> <a href="https://beyermatthias.de/tag:shell" class="hashtag"><span>#</span><span class="p-category">shell</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/the-annoyance-of-programming-language-tutorials-or-why-learning-rust-feels</guid>
      <pubDate>Sun, 31 Jan 2016 16:37:43 +0100</pubDate>
    </item>
    <item>
      <title>The world in a Shell</title>
      <link>https://beyermatthias.de/the-world-in-a-shell</link>
      <description>&lt;![CDATA[Everyone starts using shell environments, where custom variables are available,&#xA;custom bash functions are enabled, special commands are available, maybe even&#xA;some additional programs are installed.&#xA;&#xA;Projects on github pop up for handling these things, installing bash&#xA;&#34;environments&#34; and so on. And I have to ask: Why?&#xA;&#xA;center&#xA;    &lt;img&#xA;        src=&#34;/2015-11-10-whywouldyoudothat.jpg&#34;&#xA;        alt=&#34;Why would you do that?&#34;&#xA;        style=&#34;width:200px;height=200px&#34;/  /center&#xA;&#xA;!-- more --&#xA;&#xA;I tell you, there&#39;s a solution to all of your problems. It is called &#34;nix&#34;. It&#xA;is a package manager which provides you opportunities, you&#39;ve never dreamed of!&#xA;&#xA;Yes, you could hack the functionality of these project-environment-manager&#xA;things yourself (that&#39;s what people did, then they put it on github and now you&#xA;see it and decide to write your own becaues you can do it better). You could use&#xA;this piece of clusterbash and suffer from impurities you&#39;d never expect. Or,&#xA;you could just use the purity of the nix package manager to deploy the world in&#xA;a shell.&#xA;&#xA;With the nix package manager, you can use custom project-based environments to&#xA;install packages neither globally nor in your user package environment:&#xA;&#xA;nix-shell -p haskellPackages.pandoc&#xA;&#xA;for example installs &#34;Pandoc&#34; and starts a shell where it is available. The&#xA;executable is not available anymore after you type exit. It is not installed&#xA;in your system, it is not even installed in you user package set. It was&#xA;available in this shell and only will be available again after you entered this&#xA;shell via nix-shell.&#xA;&#xA;I have a lot of packages...&#xA;&#xA;... so have I. Normally, I install one or two packages via commandline in my&#xA;nix-shell environment. If there are more packages or I need the packages on&#xA;multiple systems (when developing something, for example), I add a default.nix&#xA;file to the repository:&#xA;&#xA;{ stdenv, pkgs ? (import nixpkgs {}) }:&#xA;&#xA;let&#xA;  env = with pkgs; [ racket ];&#xA;in&#xA;&#xA;stdenv.mkDerivation rec {&#xA;    name        = &#34;blog&#34;;&#xA;    src         = ./.;&#xA;    version     = &#34;0.0.0&#34;;&#xA;    buildInputs = [ env ];&#xA;}&#xA;&#xA;The I only have to type nix-shell to enter the environment.&#xA;&#xA;Another idea would be to install the packages &#34;persistent&#34;, so after a call to&#xA;nix-collect-garbage won&#39;t remove the packages from the ominous store where the&#xA;packages live:&#xA;&#xA;nix-instantiate . --indirect --add-root $PWD/shell.drv&#xA;nix-shell $PWD/shell.drv&#xA;(copy-pasted from&#xA;the nixos-wiki)&#xA;&#xA;tags:  #bash #nix #nixos #programming #software&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Everyone starts using shell environments, where custom variables are available,
custom bash functions are enabled, special commands are available, maybe even
some additional programs are installed.</p>

<p>Projects on github pop up for handling these things, installing bash
“environments” and so on. And I have to ask: Why?</p>

<p>
    <img src="/2015-11-10-whywouldyoudothat.jpg" alt="Why would you do that?" style="width:200px;height=200px"/>
</p>



<p>I tell you, there&#39;s a solution to all of your problems. It is called “nix”. It
is a package manager which provides you opportunities, you&#39;ve never dreamed of!</p>

<p>Yes, you could hack the functionality of these project-environment-manager
things yourself (that&#39;s what people did, then they put it on github and now you
see it and decide to write your own becaues you can do it better). You could use
this piece of cluster<em>bash</em> and suffer from impurities you&#39;d never expect. Or,
you could just use the purity of the nix package manager to deploy the world in
a shell.</p>

<p>With the nix package manager, you can use custom project-based environments to
install packages neither globally nor in your user package environment:</p>

<pre><code class="language-bash">nix-shell -p haskellPackages.pandoc
</code></pre>

<p>for example installs “Pandoc” and starts a shell where it is available. The
executable is not available anymore after you type <code>exit</code>. It is not installed
in your system, it is not even installed in you user package set. It was
available in this shell and only will be available again after you entered this
shell via <code>nix-shell</code>.</p>

<h1 id="i-have-a-lot-of-packages" id="i-have-a-lot-of-packages">I have a lot of packages...</h1>

<p>... so have I. Normally, I install one or two packages via commandline in my
nix-shell environment. If there are more packages or I need the packages on
multiple systems (when developing something, for example), I add a <code>default.nix</code>
file to the repository:</p>

<pre><code class="language-nix">{ stdenv, pkgs ? (import &lt;nixpkgs&gt; {}) }:

let
  env = with pkgs; [ racket ];
in

stdenv.mkDerivation rec {
    name        = &#34;blog&#34;;
    src         = ./.;
    version     = &#34;0.0.0&#34;;
    buildInputs = [ env ];
}
</code></pre>

<p>The I only have to type <code>nix-shell</code> to enter the environment.</p>

<p>Another idea would be to install the packages “persistent”, so after a call to
<code>nix-collect-garbage</code> won&#39;t remove the packages from the ominous store where the
packages live:</p>

<pre><code class="language-bash">nix-instantiate . --indirect --add-root $PWD/shell.drv
nix-shell $PWD/shell.drv
</code></pre>

<p>(copy-pasted from
<a href="https://nixos.org/wiki/Development_Environments#Making_a_Persistent_nix-shell_Environment">the nixos-wiki</a>)</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:nix" class="hashtag"><span>#</span><span class="p-category">nix</span></a> <a href="https://beyermatthias.de/tag:nixos" class="hashtag"><span>#</span><span class="p-category">nixos</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:software" class="hashtag"><span>#</span><span class="p-category">software</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/the-world-in-a-shell</guid>
      <pubDate>Tue, 10 Nov 2015 16:37:42 +0100</pubDate>
    </item>
    <item>
      <title>rate.sh -- Port to C++</title>
      <link>https://beyermatthias.de/rate-sh-port-to-c</link>
      <description>&lt;![CDATA[Some of you might know my little project&#xA;rate. It is a bash script to collect&#xA;a database of things you want to rate.&#xA;&#xA;What this means and why I started to reimplement in C++ - read it here!&#xA;&#xA;!-- more --&#xA;&#xA;So I started to write this application because I wanted to keep track of&#xA;animes I already watched, Bands I like but do not listen to that often and so&#xA;on and so forth. What the application does is really simple: You can enter&#xA;notes about a certain thing (in your favourite text editor, which is vim for&#xA;me) and attach tags to it and put it into a category. Then you can give it a&#xA;rating. The rating can be everything, from simply numbers to text to whatever&#xA;you like. But it is supposed to be a number between 1 and 10, of course.&#xA;That&#39;s also the way I use it.&#xA;&#xA;So how does it work? Well, that&#39;s really simple: The &#34;rate&#34; script creates a&#xA;directory structure in ~/.rate/collections/, whereas a folder is a&#xA;&#34;collection&#34; of things and a file is a rating. So, I have something like&#xA;&#34;movies/animes/&#34; as collections (they are nested, of course) and then a file&#xA;for each anime I watched. The filename is generated from the title I passed&#xA;&#34;rate&#34; when creating the entry. The file also contains a &#34;header&#34;, which&#xA;includes a unique ID (which you really should not change), a list of tags, the&#xA;title (the filename is the title, too, but as on linux you shouldn&#39;t include&#xA;whitespace in file names, it is not the title as you typed it) and a rating of&#xA;course. Custom fields could be added to the header, but this feature is not&#xA;implemented yet. After the header, you can put your description.&#xA;&#xA;That&#39;s basically it. &#34;rate&#34; provides some features to search this database,&#xA;for example you can grep for text in your entries, you can view your&#xA;entries, you can list your entries and you can attach more text to your&#xA;entries or edit them. As everything is git controlled in the ~/.rate&#xA;directory, you can reset if you (or the script,...) messed up somehow.&#xA;&#xA;There&#39;s no release by now, as it lacks of some features by now. For example I&#xA;want to be able to search for entries with a certain rating or within a&#xA;certain range of ratings. I also want to be able to search for entries with aspecial set of tags or within a certain collection (I can do this, though)&#xA;special set of tags or within a certain collection (I can do this, already)!&#xA;After these things are implemented, I will release my first version, which&#xA;would be 1.0 then. And, of course, I will package it for NixOS!&#xA;&#xA;So why C++&#xA;&#xA;Well, I have to learn C++ for my praxis semester. That&#39;s basically it. I&#xA;wanted to learn a new programming language for a relatively long time, and&#xA;that&#39;s my approach on learning C++. I was able to implement some things, but&#xA;not yet to run an application. My first step would be to parse my already&#xA;existing entries. Hope that works. As I stated in the github repos README.md&#xA;file, I do not want to use any frameworks for this. No Boost, no Qt, no other&#xA;libraries. I just want to use plain C++11 (or maybe 14 in future, not sure&#xA;about this, though).&#xA;&#xA;Also, C++ gives me way more posibilities when it comes to features. I can&#xA;refactor things really easy and maybe the C++ implementation will continue to&#xA;live whereas the bash implementation will die at some point. Who knows? The&#xA;point is, the bash implementation implements a file format which is&#xA;&#xA;really simple&#xA;forward compatible&#xA;&#xA;The file actually looks like this:&#xA;&#xA;key = value&#xA;other = value&#xA;another = another&#xA;---&#xA;&#xA;text&#xA;&#xA;and that&#39;s basically it. The three dashes mark the end of the header and&#xA;everything before the header is a key = value list, whereas each line is&#xA;only allowed to contain one key-value-pair. The value can be a list of values,&#xA;for example a list of Tags whereas tags are seperated by a whitespace&#xA;character (space) or a string, such as the title is. The bash implementation&#xA;&#34;knows&#34; which key has to be which value and the C++ implementation has to know&#xA;this, too, of course. But that&#39;s it.&#xA;&#xA;The commandline interface of the application needs some work, though. Maybe it&#xA;will get some REPL-like interface later on, or maybe something more&#xA;interactive. By now, it is simply an interface where you can do one thing per&#xA;call. I have no problem with that and I&#39;m planning to keep backward&#xA;compatibility with the bash implementation even if this one is not even&#xA;released! It is fun to write such a tool and I really like doing it.&#xA;&#xA;---&#xA;&#xA;Also, it is not a that complex thing to implement and that&#39;s a huge point to&#xA;me. I don&#39;t want to spend months and months in implementing a thing which only&#xA;one or two people on this planet actually use. For bigger projects, I&#xA;contribute to open source projects. That&#39;s a better way to produce large-scale&#xA;software, IMHO.&#xA;&#xA;tags:  #bash #programming #c++ #linux #shell #vim&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Some of you might know my little project
<a href="https://github.com/matthiasbeyer/rate">rate</a>. It is a bash script to collect
a database of things you want to rate.</p>

<p>What this means and why I started to reimplement in C++ – read it here!</p>



<p>So I started to write this application because I wanted to keep track of
animes I already watched, Bands I like but do not listen to that often and so
on and so forth. What the application does is really simple: You can enter
notes about a certain thing (in your favourite text editor, which is vim for
me) and attach tags to it and put it into a category. Then you can give it a
rating. The rating can be everything, from simply numbers to text to whatever
you like. But it is supposed to be a number between 1 and 10, of course.
That&#39;s also the way I use it.</p>

<p>So how does it work? Well, that&#39;s really simple: The “rate” script creates a
directory structure in <code>~/.rate/collections/</code>, whereas a folder is a
“collection” of things and a file is a rating. So, I have something like
“movies/animes/” as collections (they are nested, of course) and then a file
for each anime I watched. The filename is generated from the title I passed
“rate” when creating the entry. The file also contains a “header”, which
includes a unique ID (which you really should not change), a list of tags, the
title (the filename is the title, too, but as on linux you shouldn&#39;t include
whitespace in file names, it is not the title as you typed it) and a rating of
course. Custom fields <em>could</em> be added to the header, but this feature is not
implemented yet. After the header, you can put your description.</p>

<p>That&#39;s basically it. “rate” provides some features to search this database,
for example you can <code>grep</code> for text in your entries, you can view your
entries, you can list your entries and you can attach more text to your
entries or edit them. As everything is git controlled in the <code>~/.rate</code>
directory, you can reset if you (or the script,...) messed up somehow.</p>

<p>There&#39;s no release by now, as it lacks of some features by now. For example I
want to be able to search for entries with a certain rating or within a
certain range of ratings. I also want to be able to search for entries with aspecial set of tags or within a certain collection (I can do this, though)
special set of tags or within a certain collection (I can do this, already)!
After these things are implemented, I will release my first version, which
would be <code>1.0</code> then. And, of course, I will package it for NixOS!</p>

<h1 id="so-why-c" id="so-why-c">So why C++</h1>

<p>Well, I have to learn C++ for my praxis semester. That&#39;s basically it. I
wanted to learn a new programming language for a relatively long time, and
that&#39;s my approach on learning C++. I was able to implement some things, but
not yet to run an application. My first step would be to parse my already
existing entries. Hope that works. As I stated in the github repos <code>README.md</code>
file, I do not want to use any frameworks for this. No Boost, no Qt, no other
libraries. I just want to use plain C++11 (or maybe 14 in future, not sure
about this, though).</p>

<p>Also, C++ gives me <em>way</em> more posibilities when it comes to features. I can
refactor things really easy and maybe the C++ implementation will continue to
live whereas the bash implementation will die at some point. Who knows? The
point is, the bash implementation implements a file format which is</p>
<ol><li>really simple</li>
<li>forward compatible</li></ol>

<p>The file actually looks like this:</p>

<pre><code class="language-text">key = value
other = value
another = another
---

&lt;text&gt;
</code></pre>

<p>and that&#39;s basically it. The three dashes mark the end of the header and
everything before the header is a <code>&lt;key&gt; = &lt;value&gt;</code> list, whereas each line is
only allowed to contain one key-value-pair. The value can be a list of values,
for example a list of Tags whereas tags are seperated by a whitespace
character (space) or a string, such as the title is. The bash implementation
“knows” which key has to be which value and the C++ implementation has to know
this, too, of course. But that&#39;s it.</p>

<p>The commandline interface of the application needs some work, though. Maybe it
will get some REPL-like interface later on, or maybe something more
interactive. By now, it is simply an interface where you can do one thing per
call. I have no problem with that and I&#39;m planning to keep backward
compatibility with the bash implementation even if this one is not even
released! It is fun to write such a tool and I really like doing it.</p>

<hr>

<p>Also, it is not a that complex thing to implement and that&#39;s a huge point to
me. I don&#39;t want to spend months and months in implementing a thing which only
one or two people on this planet actually use. For bigger projects, I
contribute to open source projects. That&#39;s a better way to produce large-scale
software, IMHO.</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:c" class="hashtag"><span>#</span><span class="p-category">c</span></a>++ <a href="https://beyermatthias.de/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a> <a href="https://beyermatthias.de/tag:shell" class="hashtag"><span>#</span><span class="p-category">shell</span></a> <a href="https://beyermatthias.de/tag:vim" class="hashtag"><span>#</span><span class="p-category">vim</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/rate-sh-port-to-c</guid>
      <pubDate>Wed, 25 Feb 2015 16:37:30 +0100</pubDate>
    </item>
    <item>
      <title>My work on diary.sh</title>
      <link>https://beyermatthias.de/my-work-on-diary-sh</link>
      <description>&lt;![CDATA[I started a&#xA;fork of a diary application&#xA;which is written in bash, because I thought there are some things missing&#xA;and some features could be added - and the repository of the original&#xA;author was really old.&#xA;&#xA;I started to pretty it up and implement some 21st-century things so it becomes&#xA;a really nice note-taking application.&#xA;&#xA;!-- more --&#xA;&#xA;So, initially the application was called &#34;diary&#34; and developed on&#xA;sourceforge, by Jamie Briggs.&#xA;Someone created a fork, named&#xA;&#34;diary-f&#34;, which added some features.&#xA;&#xA;The lastest change in the original repository is from February 2013, which is&#xA;almost two years ago by now. The last change in the repository of the fork is&#xA;from three years ago - even longer, yes!&#xA;&#xA;So, the application per se is really good one. It is just a small shell&#xA;script, but it works really good for me. Anyways, I missed some features,&#xA;namingly:&#xA;&#xA;Multiple separate entries per day&#xA;Everything should be kept in git, so I know when I edited the articles&#xA;GPG encryption everywhere&#xA;&#xA;I started implementing multi-file support directly in the &#34;diary-f&#34;&#xA;repository, but then decided to create a fork, as it won&#39;t be compatible with&#xA;the original software anymore. By now, three things are done in the&#xA;repository: I refactored the codebase to fit my coding style (well, it is&#xA;still bash, isn&#39;t it?), mutli-file support as said and git support. I want to&#xA;implement gpg support next and maybe the ability to add attachements to&#xA;entries. And after these things are implemented, I want to be able to search&#xA;the entry repository for certain entries in a simple way, which could be&#xA;difficult, given the fact that everything is encrypted in there.&#xA;&#xA;---&#xA;&#xA;If you&#39;re interested in the application, I&#39;d welcome pull requests for almost&#xA;everything. Contributing guidelines are:&#xA;&#xA;Document your work, how do things work?&#xA;KISS&#xA;DRY&#xA;&#xA;That&#39;s basically it. I&#39;m looking forward to your patches!&#xA;tags:  #bash #git #open source #programming #shell #tools&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I started a
<a href="https://github.com/matthiasbeyer/diary.sh">fork of a diary application</a>
which is written in bash, because I thought there are some things missing
and some features could be added – and the repository of the original
author was <em>really</em> old.</p>

<p>I started to pretty it up and implement some 21st-century things so it becomes
a really nice note-taking application.</p>



<p>So, initially the application was called “diary” and developed on
<a href="https://sourceforge.net/projects/diary/">sourceforge, by Jamie Briggs</a>.
<a href="https://github.com/earshinov/diary-f">Someone created a fork</a>, named
“diary-f”, which added some features.</p>

<p>The lastest change in the original repository is from February 2013, which is
almost two years ago by now. The last change in the repository of the fork is
from three years ago – even longer, yes!</p>

<p>So, the application per se is really good one. It is just a small shell
script, but it works really good for me. Anyways, I missed some features,
namingly:</p>
<ul><li>Multiple separate entries per day</li>
<li>Everything should be kept in git, so I know when I edited the articles</li>
<li>GPG encryption everywhere</li></ul>

<p>I started implementing multi-file support directly in the “diary-f”
repository, but then decided to create a fork, as it won&#39;t be compatible with
the original software anymore. By now, three things are done in the
repository: I refactored the codebase to fit my coding style (well, it is
still bash, isn&#39;t it?), mutli-file support as said and git support. I want to
implement gpg support next and maybe the ability to add attachements to
entries. And after these things are implemented, I want to be able to search
the entry repository for certain entries in a simple way, which could be
difficult, given the fact that everything is encrypted in there.</p>

<hr>

<p>If you&#39;re interested in the application, I&#39;d welcome pull requests for almost
everything. Contributing guidelines are:</p>
<ul><li>Document your work, how do things work?</li>
<li>KISS</li>
<li>DRY</li></ul>

<p>That&#39;s basically it. I&#39;m looking forward to your patches!
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:git" class="hashtag"><span>#</span><span class="p-category">git</span></a> <a href="https://beyermatthias.de/tag:open" class="hashtag"><span>#</span><span class="p-category">open</span></a> source <a href="https://beyermatthias.de/tag:programming" class="hashtag"><span>#</span><span class="p-category">programming</span></a> <a href="https://beyermatthias.de/tag:shell" class="hashtag"><span>#</span><span class="p-category">shell</span></a> <a href="https://beyermatthias.de/tag:tools" class="hashtag"><span>#</span><span class="p-category">tools</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/my-work-on-diary-sh</guid>
      <pubDate>Sat, 31 Jan 2015 16:37:29 +0100</pubDate>
    </item>
    <item>
      <title>Too much languages to choose from</title>
      <link>https://beyermatthias.de/too-much-languages-to-choose-from</link>
      <description>&lt;![CDATA[I have a problem. I want to write a small application. It should be a&#xA;commandline application, but maybe I want to extend it later with a GUI or&#xA;even a web interface. But I don&#39;t know what language to write it in.&#xA;&#xA;!-- more --&#xA;&#xA;This article could also be named &#34;Which is the right tool for the job?&#34;&#xA;&#xA;The idea is simple: I want to write a journal-application, where one can take&#xA;notes, tag them, query the journal for entries, optionally provide filters&#xA;before printing them to print only some of them and so on.&#xA;&#xA;I want to be able to encrypt them with gpg and I want to write posts to the&#xA;journal with vim. I want to be able to configure these steps, of course, so I&#xA;can use a certain key for encrypting the journal or maybe another editor (for&#xA;these emacs lovers out there).&#xA;&#xA;It should be designed to be extensible, so I can add a GUI or web interface&#xA;later on. Or maybe a tex output, so I can compile a PDF out of it or&#xA;something. Posts should be written in standard markdown, so this wouldn&#39;t be a&#xA;big deal.&#xA;&#xA;But I don&#39;t know what language to write it in. The languages which I can or&#xA;would choose from are:&#xA;&#xA;C&#xA;C++&#xA;Haskell&#xA;Rust&#xA;Java (not really...)&#xA;Scala (not really either, it&#39;s still JVM)&#xA;Ruby&#xA;Python (by extending jrnl)&#xA;Racket&#xA;Lua&#xA;Bash (I really don&#39;t want to write it in bash, but it&#39;s still a possibility)&#xA;&#xA;As you can see, the first four languages are compiled languages, then Java and&#xA;Scala are (lets call it) Semi-Compiled languages and the others are scripting&#xA;languages. All of these languages have certain advantages over others.&#xA;&#xA;The compiled languages&#xA;&#xA;... have the advantages that they are fast. Haskell and Rust also have the&#xA;advantages that if the compiler does not fail compiling the sources, the&#xA;program just works (tm).&#xA;&#xA;Also, learning C++, Haskell or Rust would be a really great experience and may&#xA;be beneficial later in a job or something.&#xA;&#xA;The semi-compiled languages are also (kind of) fast, but they are&#xA;JVM-languages, so I won&#39;t look into them here...&#xA;&#xA;The scripting languages&#xA;&#xA;Writing the application in a scripting language would have some other&#xA;advantages: They would be much more flexible and I&#39;d be faster writing the&#xA;application (compared to Rust or Haskell, which I would need to learn with the&#xA;application). I don&#39;t need to learn Ruby, I know a fair bit of Racket and I&#xA;guess I can get productive with Python or Lua really fast.&#xA;&#xA;Bash is another option and I&#39;m actually an bash script for an almost similar&#xA;job right now. I could simply extend this script, that would be an option, of&#xA;course.&#xA;&#xA;So which is the right tool for the job?&#xA;&#xA;Can you tell me? I don&#39;t know which tool is the right tool for the job. After&#xA;all, I don&#39;t think I should write such an application from scratch. So, for&#xA;me, there are two options left: Extending&#xA;jrnl, which is an Python script, or&#xA;extending diary (I do not even find a link for this anymore), which is a bash&#xA;script. Extending the bash script would be an easy job, I guess. But it&#xA;wouldn&#39;t be as flexible as the Python tool is already.&#xA;tags:  #bash #c #c++ #haskell #programming #racket #rust #shell #tools&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I have a problem. I want to write a small application. It should be a
commandline application, but maybe I want to extend it later with a GUI or
even a web interface. But I don&#39;t know what language to write it in.</p>



<p>This article could also be named “Which is the right tool for the job?”</p>

<p>The idea is simple: I want to write a journal-application, where one can take
notes, tag them, query the journal for entries, optionally provide filters
before printing them to print only some of them and so on.</p>

<p>I want to be able to encrypt them with gpg and I want to write posts to the
journal with vim. I want to be able to configure these steps, of course, so I
can use a certain key for encrypting the journal or maybe another editor (for
these emacs lovers out there).</p>

<p>It should be designed to be extensible, so I can add a GUI or web interface
later on. Or maybe a tex output, so I can compile a PDF out of it or
something. Posts should be written in standard markdown, so this wouldn&#39;t be a
big deal.</p>

<p>But I don&#39;t know what language to write it in. The languages which I can or
would choose from are:</p>
<ul><li>C</li>
<li>C++</li>
<li>Haskell</li>
<li>Rust</li>
<li>Java (not really...)</li>
<li>Scala (not really either, it&#39;s still JVM)</li>
<li>Ruby</li>
<li>Python (by extending <a href="https://maebert.github.io/jrnl/">jrnl</a>)</li>
<li>Racket</li>
<li>Lua</li>
<li>Bash (I really don&#39;t want to write it in bash, but it&#39;s still a possibility)</li></ul>

<p>As you can see, the first four languages are compiled languages, then Java and
Scala are (lets call it) Semi-Compiled languages and the others are scripting
languages. All of these languages have certain advantages over others.</p>

<h1 id="the-compiled-languages" id="the-compiled-languages">The compiled languages</h1>

<p>... have the advantages that they are <em>fast</em>. Haskell and Rust also have the
advantages that if the compiler does not fail compiling the sources, the
program just works ™.</p>

<p>Also, learning C++, Haskell or Rust would be a really great experience and may
be beneficial later in a job or something.</p>

<p>The semi-compiled languages are also (kind of) fast, but they are
JVM-languages, so I won&#39;t look into them here...</p>

<h1 id="the-scripting-languages" id="the-scripting-languages">The scripting languages</h1>

<p>Writing the application in a scripting language would have some other
advantages: They would be much more flexible and I&#39;d be faster writing the
application (compared to Rust or Haskell, which I would need to learn with the
application). I don&#39;t need to learn Ruby, I know a fair bit of Racket and I
guess I can get productive with Python or Lua really fast.</p>

<p>Bash is another option and I&#39;m actually an bash script for an almost similar
job right now. I could simply extend this script, that would be an option, of
course.</p>

<h1 id="so-which-is-the-right-tool-for-the-job" id="so-which-is-the-right-tool-for-the-job">So which is the right tool for the job?</h1>

<p>Can you tell me? I don&#39;t know which tool is the right tool for the job. After
all, I don&#39;t think I should write such an application from scratch. So, for
me, there are two options left: Extending
<a href="https://maebert.github.io/jrnl">jrnl</a>, which is an Python script, or
extending diary (I do not even find a link for this anymore), which is a bash
script. Extending the bash script would be an easy job, I guess. But it
wouldn&#39;t be as flexible as the Python tool is already.
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:c" class="hashtag"><span>#</span><span class="p-category">c</span></a> <a href="https://beyermatthias.de/tag:c" class="hashtag"><span>#</span><span class="p-category">c</span></a>++ <a href="https://beyermatthias.de/tag:haskell" class="hashtag"><span>#</span><span class="p-category">haskell</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:racket" class="hashtag"><span>#</span><span class="p-category">racket</span></a> <a href="https://beyermatthias.de/tag:rust" class="hashtag"><span>#</span><span class="p-category">rust</span></a> <a href="https://beyermatthias.de/tag:shell" class="hashtag"><span>#</span><span class="p-category">shell</span></a> <a href="https://beyermatthias.de/tag:tools" class="hashtag"><span>#</span><span class="p-category">tools</span></a></p>
]]></content:encoded>
      <guid>https://beyermatthias.de/too-much-languages-to-choose-from</guid>
      <pubDate>Mon, 26 Jan 2015 16:37:29 +0100</pubDate>
    </item>
    <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>