Wilkommen!

Ich bin Martin HĂ€cker, ein Softwareentwickler mit mehr als 20 Jahren Erfahrung. Ich kann bei allen Aspekten der professionellen Softwareentwicklung unterstĂŒtzen.

In meinem Blog geht es um Software, Liquid Democracy, Go / Baduk / Weiqi, Kochen, Chor-Singen, Bouldern, Billiard, Gleitschirmfliegen, Kiten, Jonglieren und eben alles was mich interessiert. Schau dich um, benutze meinen Code und abonniere meinen Feed, um mein Blog bequem in einem Reader zu lesen.

WĂ€hrend meine Webseite zweisprachig ist, sind meine Blog-Posts in der Regel einsprachig deutsch oder englisch.

Neueste EintrÀge:

Die Freuden einer gut eingerichteten Shell: Autocomplete

written by Martin HĂ€cker on

Was ist schlechte VervollstÀndigung?

Um zu verstehen was ich mit guter Auto-Completion fĂŒr Shells meine, brauchen wir erst einmal eine Baseline wie eine schlechte Completion aussieht. Das lĂ€sst sich sehr gut mit Docker demonstrieren: 

docker run --rm -it --hostname shell-completion-demo debian

Erstes Experiment: ls⇄⇄ (kein Leerzeichen vor den Tabs!)

Automatische VervollstÀndigung von Kommandos - unkonfiguriert

Zeigt alle Kommandos die mit ls anfangen Zweites Experiment: ls ⇄⇄ Das zeigt bei mir:

Automatische VervollstÀndigung von Dateien - unkonfiguriert

Schon mal gut, denn hier werden die Dateien im aktuellen Ordner vervollstÀndigt.

NĂ€chste Schwierigkeitsstufe - kurze und lange Optionen: ls -⇄⇄ (Minus vor dem Tab) Das zeigt hier nichts, genauso fĂŒr lange Optionen ls --⇄⇄ (zwei mal Minus vor dem Tab)

Keine Ausgabe. ls ist eigentlich so ungefÀhr das einfachste Programm das jeder Shell beiliegt. Wenn automatische VervollstÀndigung also irgend etwas kann, dann sollte ls gut funktionieren.

Was ist gute VervollstÀndigung?

Dagegen mal ein Beispiel von meinem System:

ls⇄ zeigt die Kommandos die mit ls anfangen, mit einer Kurzbeschreibung was diese Kommandos tun.

VervollstÀndigung von Kommandos mit der Fish-Shell

Schon mit einem Tab sehe ich die Dateien, und zusĂ€tzlich sehe ich als Vorschlag den letzten Befehl den ich mit ls abgesetzt habe und kann diesen mit ⌃→ im ganzen, oder mit → wortweise akzeptieren kann.

Automatische VervollstÀndigung von Dateien mit der Fish Shell

Ein ls -⇄ergibt sofort eine Optionsliste - kurz und lang - mit einer Kurzbeschreibung was dieses Schalter tun. Ein zweites Minus und Tabls --⇄` zeigt nur noch die langen Optionen an:

VervollstÀndigung von Optionen mit der Fish-Shell VervollstÀndigung von langen Optionen mit der Fish-Shell

NatĂŒrlich kann ich mit den Pfeiltasten oder mit Tab eine der Optionen auswĂ€hlen - natĂŒrlich mit ordentlichem Highlighting. So macht arbeiten auf der Shell Spaß!

Falls Ihr verwirrt seid das mein ls andere Optionen anbietet als eures, dann liegt das daran das ich ls durch exa ersetzt habe.

Wie könnt Ihr das bei euch nutzen?

Ich nutze die Fish-Shell, da diese von Haus aus eine sehr gute Autocompletion anbietet. Das ist aber nicht fĂŒr jede, denn die Syntax der Fish Shell ist etwas anders als bei Bash/ZSH - eben nicht posix kompatibel. Ich mag das Weil es logischer und KĂŒrzer ist, aber ich komme auch nicht durcheinander mit den verschiedenen Shell-Syntaxen da ich sie schon so lange verwende.

Fast alle Shell Konfigrurations-Frameworks wie oh-my-zsh oder Prezto bieten zumindest etwas an das diesem Nahe kommen. Alle automatische Konfiguration stĂ¶ĂŸt aber irgendwann an Ihre Grenzen wenn es um die Kommandos geht, die wir tĂ€glich benutzen. docker vervollstĂ€ndigt dann nicht compose und oder kennt die Unterkommandos davon nicht oder nur unvollstĂ€ndig, kubectl und helm sind notorische Kandidaten fĂŒr die man sich selber kĂŒmmern muss.

Jetzt könnte man natĂŒrlich versuchen automatisch aus der Hilfsausgabe dieser Kommandos etwas zu generieren (das macht z.B. die Fish shell von sich aus) oder man schreibt selber etwas (argh).

Oder man wendet sich vertrauensvoll an das tool carapace, mit dem man die Completion fĂŒr Programme komfortabel fĂŒr alle Shells nachrĂŒsten kann. Als Beispiel um die die Autocompletions fĂŒr kubectl nachzurĂŒsten, einfach source <(carapace kubectl zsh) oder carapace kubectl fish | source (je nach shell) eingeben und ausprobieren ob es gefĂ€llt, und wenn ja, diese Zeile in die User-Konfiguration deiner shell eintragen und viel glĂŒcklicher sein.

Obacht: Man kann mit so einem Snippet

# ~/.zshrc 
export CARAPACE_BRIDGES='zsh,fish,bash,inshellisense' # optional
zstyle ':completion:*' format $'\e[2;37mCompleting %d\e[m'
source <(carapace _carapace)

in seiner Shell-Konfiguration alle completer des Carapace Projekts aktivieren. Das hat mir allerdings nicht gefallen,, da ich manche der eingebauten Completer der Fish-Shell noch etwas besser finde als das was Carapace bereit stellt. Aber um LĂŒcken zu ergĂ€nzen? Perfekt!

Meine Shell-Completion Konfiguration (fish!) sieht daher so aus:

# enable shell completions
set --global --export CARAPACE_BRIDGES 'zsh,fish,bash,inshellisense'
# I didn't have much luck enabling all carapace completions, but I do like some of them - especially if there is no built in fish completion for them
# carapace _carapace | source
carapace fd | source
carapace bat | source
carapace brew | source
carapace rg | source
carapace docker | source
uv generate-shell-completion fish | source
yq completion fish | source

Die Freuden einer gut eingerichteten Shell: Der Prompt

written by Martin HĂ€cker on

Terminal

Es fĂ€ngt natĂŒrlich mit der Frage an: welche Shell?

Das ist sehr einfach zu beantworten. Auf MacOS ist die zsh die Standard-Shell - und daher sollte man die auch benutzen. Artikel Fertig, vielen Dank fĂŒrs Lesen! 😅

Windows hat die PowerShell - wer damit Arbeiten (muss) sollte sie lernen!

Die nackte Shell ist ziemlich schlecht konfiguriert, da die Möglichkeiten der Shell gar nicht ausgenutzt werden. Auf Linux-Distributionen ist es Standard, dass die Shell von der Distribution eingerichtet wird, daher kann man damit meistens schon gut arbeiten.

Aber fĂŒr MacOS (und Windows) gibt es viel zu tun.

So sieht die zsh unkonfiguriert aus:

dwt@NB1321 ~ % cd Library/Favorites
dwt@NB1321 Favorites %

Das ist schon gar nicht schlecht, denn man sieht einiges:

  • dwt: Welcher Nutzer man gerade ist. Wichtig, wenn man viel mit sudo arbeitet, damit man nicht versehentlich Kommandos als root mit zu vielen Rechten ausfĂŒhrt.
  • NB1321: Auf welchem Rechner man gerade eingeloggt ist. Wichtig wenn man auf vielen Rechnern arbeitet und nicht
  • Den aktuellen Ordner in dem man ist (Favorites). Wichtig damit man z.B. nicht versehentlich die falschen Dateien löscht.
  • Der Prompt % trennt die Meta-Informationen von dem was man selbst eingibt.

Da geht aber noch wesentlich mehr. Bei mir z.B. sieht der Prompt so aus:

~/C/P/m/api ❄ đŸ§Ș nix-shell-env   🐍 venv ⛔ mkk-itsc-dev (api) đŸŒ± main $!  4s
❯

Da ist enthalten:

  • ~/C/P/m/api - nicht nur der aktuelle Ordner, sondern auch jeweils der Anfangsbuchstabe der darĂŒber liegenden Ordner. Das liefert platzsparend viel mehr Kontext, wo man gerade ist. Super wenn man in vielen Projekten gleichnamige Ordner wie z.B. etc, src oder dist hat.
  • ❄ đŸ§Ș nix-shell-env Zeigt an, dass gerade eine 'dreckige' Nix-Shell aktiv ist. Das verwende ich um Projek-spezifische AbhĂ€ngigkeiten (Shell-Tools, bestimmte Vesionen von Python etc.) zu installieren die ich deklarativ im Projekt tracke. Gut vergleichbar mit Python-Virtual-Envs - aber eben fĂŒr alles, nicht nur Python-Pakete. Dreckig ('impure') ist Sie, da nicht nur die Shell-Tools aus der Nix-Shell sichtbar sind, sondern auch alles andere was ich im Betriebsystem installiert habe.
  • 🐍 venv - zeigt an, dass gerade ein Python-Virtual-Env aktiv ist. Da ich hauptsĂ€chlich mit Pyton entwickle ist das natĂŒrlich entscheidend weil es bedeutet das ich die Projekt-Werkzeuge direkt verwenden kann, da sie im $PATH und $PYTHONPATH sind.
  • ⛔ mkk-itsc-dev (api) zeigt an, dass ich mit dem mkk-itsc-dev Kubernetes Cluster verbunden bin, und den Namespace api aktiviert habe. Das ist mir sehr wichtig, damit ich nicht versehentlich mit kubectl Befehlen versehentlich den Produktiv-Cluster zerstöre. (Rate wieso mir das so wichtig ist
)
  • đŸŒ± main $! zeigt an, dass ich in einem Git-Repository bin, auf dem main branch, das ich dinge ge-'stash't habe (die vergisst man sonst sehr leicht) und das ich Änderungen habe die ich noch nicht commited habe. Hier gibt es auch noch mehr informationen wenn das Repo den entsprechenden Zustand hat.
  • Zuletzt sehe ich da das letzte Kommando 4 Sekunden gedauert hat. Das wird nur angezeigt wenn das letzte Programm mehr als 3 Sekunden gedauert hat und ist immer wiede ein hilfreiche Information um bei langlaufenden Prozesen zu verstehen ob es sich lohnt da etwas zu optimieren.

NatĂŒrlich könnte man hier noch viel mehr anzeigen, je nachdem an was man gerade arbeitet. Ich habe hier eben die Informationen aufgenommen die ich am meisten benötige.

Jetzt kommt der Clou: FrĂŒher habe ich das alles von hand Konfiguriert. Das war ein ewiges und mĂŒhsammes gefummel um $PS1 und konsorten so hinzufummeln das das alles funktioniert hat, und hat nie Spaß gemacht. Der Standard ist derzeit, das man einen Shell-Konfigurations-Framework wie Oh-My-Zsh oder Prezto verwendet. Und die sind auch gut. Aber auch langsam, und komplex und kompliziert. Wenn man da mal etwas anders haben will dann gott bewahre wenn das nicht schon vorbereitet ist oder man darf sich nicht nur mit den KomplexitĂ€ten von $PS1 auseinandersetzen, sondern auch noch damit wie genau dieser Framework das handhabt.

Inzwischen bin ich weiser geworden, und verwende Starship. Damit kann ich meinen Prompt deklarativ in einer .toml-Datei konfigurieren und diesen auch mitnehmen wenn ich mal die Shell wechsle. (Was hÀufiger vorkommt als mir lieb ist). Und: Starship funktioniert auch mit der PowerShell.

So sieht meine Konfiguration aus

Wie richtet man das ein?

  1. brew install starship (oder mit nix)
  2. nano ~/.zshrc und am Ende eval "$(starship init zsh)" einfĂŒgen.
  3. Konfigurationsdatei erstellen: nano ~/.config/starship.toml und z.b. den Inhalt aus der Datei oben einfĂŒgen.
  4. Shell neu starten oder neues Terminal öffnen.

Danke sagen fĂŒr die grandiose Verbesserung eures Shell-Lebens bei mir nicht vergessen. 😅

A Nix'le in a BĂŒchse und a goldigs Warteweile

written by Martin HĂ€cker on

Das Nix Hasenloch 
 ist ein schwĂ€bisches Sprichwort und passt gar nicht so schlecht fĂŒr die vielen schlechten Wortwitze die sich automatisch ergeben, wenn man anfĂ€ngt, sich in das Nix Projekt einzuarbeiten.

ZunĂ€chst mal die Karotte mit der ich mich ködern ließ:

  • Deklarative Konfiguration von Software-Builds, System-Konfigurationen, und wenn man möchte auch Deployments z.B. in Kubernetes und was man sonst gerne möchte
  • Ein funktionaler Paket-Manager, das heißt: Jede Software kann ihre eigenen AbhĂ€ngigkeiten in der passenden Version haben. Wenn ich mal ein Tool in der Version von vor 10 Jahren brauche - einfach zusĂ€tzlich installieren, ohne dass dadurch etwas gestört wird. Wenn ich mal eine neuere Version von etwas brauche als die aktuelle Distribution anbietet: Einfach installieren, ohne dass dadurch etwas gestört wird.
  • Rollback: Systemkonfiguration hat etwas kaputt gemacht? Einfach RĂŒckgĂ€ngig machen.
  • Update auf eine neue Version des Betriebssystems: Man kriegt fehlermeldungen fĂŒr alle Konfigurationen die man vorgenommen hat die jetzt umbenannt wurden oder anders funktionieren. đŸ€Ż
  • Reproduzierbarkeit: VollstĂ€ndige Erfassung der Inputs und Ablegen derselben in einem Lock-File.
  • Eine riesige Community, die beste Praktiken zum Betrieb von Linux (und mehr) Systemen in die grĂ¶ĂŸte Software-Bibliothek kodiert, die wir bisher gesehen haben.

Was sollte man da nicht mögen?

Auf MacOs gibt es mit nix-darwin ein Projekt mit dem man die System-Konfiguration deklarativ vornehmen kann - und auch homebrew (was sonst so gut wie gar nicht reproduzierbar ist) unter Kontrolle kriegt. Und wenn man möchte, verwaltet es einem auch die dotfiles.

Es gibt allerdings einen gewaltigen Nachteil: Das Ganze ist echt komplex und kompliziert. Und die Dokumentation ist nicht schlecht, aber könnte deutlich besser sein.

Wenn man diese HĂŒrde ĂŒberwindet, wird man mit einer erstaunlich kompakten und sehr schnell anzuwendenden System-Konfiguration belohnt. Damit kann man zum Beispiel auf einem Mac ein vollstĂ€ndig konfiguriertes System-Image fĂŒr einen Raspberry Pi erstellen. Dann noch flaschen, starten und lĂ€uft! Oder auf meinem Mac Bauen, und via ssh auf dem RasPi deployen, ohne dort irgendwas zu machen was dessen CPU stresst.

Ich habe inzwischen angefangen, meine Rechner damit zu verwalten und konfigurieren.

Nix ist vielleicht nichts fĂŒr dich



 aber wenn Du ein bisschen nerdig bist, und gerne auf der Kommandozeile lebst, infrastruktur as Code magst oder lernen magst und DevOps fĂŒr dich eh normal ist. Dann könnte Nix auch fĂŒr dich genau das richtige sein.

Wie lernt man Nix am besten?

Was mir beim Lernen von Nix gefehlt hat, wÀre eine Leitlinie gewesen, in welcher Reihenfolge ich mich an die vielen Features von Nix heran tasten sollte. Eine Reihenfolge, die sicherstellt, das die Lernkurve zu jedem Zeitpunkt ertrÀglich bleibt. Und besonders wichtig: Die Sicherstellt, das zu jedem Zeitpunkt sichtbar ist wie cool und wertvoll diese Technologie ist. Sonst lÀuft man Gefahr, ob der steilen Lernkurve abzuspringen.

Das hÀtte ich gerne gehabt: Wenn du anfÀngst Nix zu lernen, dann am besten in dieser Reihenfolge:

1. Schritt: Installieren, ohne was bestehendes kaputt zu machen

Zuerst sollte man Nix neben dem aktuellen OS installieren. Der Standard ist der Determinate Installer, aber ich mag das Lix Projekt lieber, da es schneller ist. Alternativ ist auch der Nix-Docker-Container super um es mal auszuprobieren. Wenn man möchte, kann man Nix (auf Linux) auch einfach in einen Ordner installieren und so verwenden (siehe "Single-User Mode"). Das wĂŒrde ich aber nur fĂŒr ein paar Experimente empfehlen. Sowohl der Determinate als auch der Lix-Installer haben sehr gute Uninstaller die das Projekt auch wieder komplett entfernen können.

2. Schritt: Imperativ verwenden

Nix erlaubt es jederzeit ein Paket zu benutzen, ohne es zu installieren. Das ist eine Konsequenz davon wie der Paket-Manager aufgebaut ist. Ein Paket kann 'im /nix/store/ sein' - ohne das es aktiv ist. Und der Befehl nix run nixpkgs#fzf startet es dann einfach - ohne es zu installieren. Alternativ gibt es auch nix shell nixpkgs#fzf. Damit erhĂ€llt man eine Shell, in der fzf installiert ist. Schließt man die Shell, ist es auch wieder weg. 😳

Dass ist der Hammer, weil man so Pakete ohne Reue ausprobieren kann. Ohne Sorgen, dass doch noch irgendwelche AbhÀngigkeiten evtl. auf dem System herum gurken und man vergessen könnte ein Experiment wieder zu entfernen. Und das beste: Auch spÀter wird man dieses Feature die ganze Zeit verwenden.

Vorsicht vor nix-env und nix profile - das ist das Äquivalent zu dem wie man mit homebrew und anderen Paketmanagern Pakete installieren wĂŒrde. Diese sollte man so selten wie möglich verwenden. Besser ist


3. Schritt: Entwicklungsumgebungen shell.nix

Das, was nix shell nixpkgs#fzf macht, kann man auch in eine Datei schreiben, und damit einfach in ein Repo mit einchecken. Schon hat man Deklarativ die ganzen Tools im Repo dokumentiert, die man braucht um mit einem Projekt zu arbeiten. Bonus: Ich kann fĂŒr jedes Projekt eigene Versionen der AbhĂ€ngigkeiten haben (wenn ich das brauche). Python-Virtual-Envs auf Steroiden!

Hier ein Beispiel:

{
  pkgs ? import <nixpkgs> { },
}:
pkgs.mkShell {
  buildInputs = with pkgs; [
    # Add your build inputs here
    pkgs.python313
    pkgs.uv
  ];
  env = {
    UV_PYTHON = pkgs.python313;
    UV_DOWNLOAD_PYTHON = "never";
  };
}

Wenn man das mit nix-shell aufruft, dann hat man diese Python-Version zur Hand. uv verwendet diese und lĂ€dt selber keine Python-Versionen herunter. Nice! Extra nice: mit nix-shell --pure hat man eine Shell in der nur das sichtbar ist was in dem shell.nix steht, und man kriegt Fehler fĂŒr alles was man verwendet und in der shell.nix vergessen hat. đŸ€Ż

Bonus: Direnv verwenden um automatisch die shell.nix und das .env zu laden. Dazu zoxide um schnell in der Shell zwischen vielen Projekten hin und zu springen. Eine richtig geniale Entwicklungsumgebung.

Ich empfehle erst mal eine weile auf diesem Niveau zu bleiben, denn das ist schon ziemlich cool!

4. Schritt: Mehr Tooling um besser mit Nix klar zu kommen

  • Pakete findet man am besten ĂŒber die Webseite search.nixos.org - aber ich mag eigentlich in der shell suchen. nix run nixpkgs#nh search ut1999 funktioniert besser als alles was ich sonst bisher getestet habe.
  • Anzeigen was gerade installiert ist und wieso ist aufgrund der Architektur von nix gar nicht so einfach. nix run nixpkgs#nix-tree aproximiert das und gibt einen guten ĂŒberblick darĂŒber was man auf dem System hat.
  • nom - der Nix-Output-Monitor nix run nixpkgs#nix-output-monitor macht den output von lĂ€ngeren nix builds viel informativer und spannender. Verwenden kann man das so: nix run $something |& nix run nixpkgs#nix-output-monitor
  • nix store gc um alles zu löschen, was man mal testweise runtergeladen hat und nicht mehr auf der Platte braucht. (Einer Der Nachteile von Nix: Es verbraucht schnell viel Plattenplatz).

5. Schritt: Tief in das Hasenloch fallen

Jetzt gibt es verschiedene Sachen die man sich anschauen könnte

Weitere BeitrÀge