Ein Datenbank-Client in neovim

Es gibt ja immer mal wieder den Fall, dass man mal schnell in der Datenbank eine Query abfeuern möchte. Nur um mal zu schauen, ob die Daten, die man gerade über Doctrine gezogen hat, auch stimmen. Oder sich mal kurz einen Überblick verschaffen möchte, wie denn die Datenbank überhaupt aufgebaut ist.
Natürlich kann man dann Tools wie Sequel Ace oder DBeaver verwenden. IDEs wie PhpStorm bringen ihre eigenen Database-Viewer mit, mit denen man solche Aufgaben sehr gut erledigen kann. Also muss ich sowas auch in neovim haben. Punkt.

Mit vim-dadbod-ui existiert sowas auch als optimiertes “grafisches” Interface für vim-dadbod und es erfüllt genau diese Anforderungen: man kann unterschiedliche Verbindungen definieren, Queries abschicken und sogar Queries für später speichern. Man schreib einfach die Query in einen Buffer, speichert diesen und sofort wird diese abgefeuert und die Ergebnisse dargestellt. Wunderbar.

Konfiguration für MySQL anpassen

Seine Verbindung definiert man in vim-dadbod in Form von “URLs”:

mysql://db@localhost/mydb

Da normalerweise MySQL aber meckert, wenn man sein Passwort in der Form übergibt ("Using a password on the command line interface can be insecure") und dadurch die Ausgabe der Ergebnisse leider in Mitleidenschaft gezogen wird, behelfe ich mir damit, dass ich über das kleine Helferlein mysql_config_editor bestimmte Angaben zu der Verbindung (Benutzername, Passwort und Port) in die Datei .mylogin.cnf abspeichere. 

mysql_config_editor set --login-path=myconnection --host=localhost --port=12345 --user=db --password

Damit kann man dann in vim-dadbod mit folgender URL die Verbindung aufrufen und bekommt keine Probleme mehr

mysql://localhost/mydb?login-path=myconnection

Noch ein kleiner Tipp für die, die DDEV verwenden: ihr solltet in der Konfiguration eures Projektes per host_db_port den Port für die Datenbank “festzurren”. Normalerweise ändert der sich nämlich bei jedem Start eures Projektes.

CubeQuest

Werbung macht man für Sachen, die einem gefallen und vor allem, wenn sie von Menschen erstellt wurden, die man kennt und schätzt. Stephan (Hah! Was für ein schöner Name!) ist so jemand. Kennengelernt haben wir uns bei einem ehemaligen Arbeitgeber von mir und wahrscheinlich spielt er immer noch mit einer mir unverständlichen Leidenschaft Dark Souls. Daher kommt vermutlich auch sein Hang für knackige Rätsel, die er in sein mittlerweile zweites Spiel gepackt hat: “CubeQuest - a QB Game”.

Ein Puzzle-Plattformer in seiner reinsten Form. Die Spielmechaniken erinnern sehr an den Vorgänger “QB – A Cube’s Tale”, heben das Ganze jetzt durch die wunderbare Grafik, Sound und die Ambient-Musik aber auf ein ganz anderes Level. In den ersten der sechzig Level wird man Schritt für Schritt in die Mechaniken und Möglichkeiten eingeführt, wie man seine Spielfigur (einen Würfel) in der Welt herumbewegt. Alle paar Level schaltet man Upgrades wie Laser, Sprünge oder Slides frei, mit denen man die immer schwerer werdenden Rätsel lösen muss, um sich ins nächste Level beamen zu können.

Wer Spiele wie Monument Valley oder Fez gerne spielt, wird in CubeQuest ein weiteres Spiel finden, das genauso liebevoll umgesetzt ist. Zum Einstieg kann man sich die App einfach mal installieren und loslegen, die ersten Level sind kostenlos, durch einen einmaligen InApp-Kauf schaltet man alle sechzig Level frei. Und dann ist der Kerl mit seinem Spiel auch noch beim Deutschen Computerspielpreis nominiert!

Strike Commander

Origin gehört für mich immer zu den besten Computerspielfirmen, die mich von Anfang an begleitet haben. Ich bin mir auch recht sicher, dass ich damals auf einem 8088er eins der ersten Ultima angespielt habe. Aufgrund meiner nicht vorhandenen Englisch-Kentnisse als Grundschüler habe ich aber nicht verstanden, was ich eigentlich machen sollte.

Was man sagen kann, ist, dass die Spiele alle immer sehr hardwarehungrig waren. Egal, ob es sich um Wing Commander, Ultima oder auch Strike Commander handelt, um diese spielen zu können, benötigte man einen sehr gut ausgebauten Rechner. Und Strike Commander habe ich geliebt!
Klar, eine gute Flugsimulation war Strike Commander nicht. Dafür gab es ja die Falcon-Reihe. Aber, was Origin mit seinen Spielen so unvergesslich macht, ist, dass sie Geschichten erzählen konnten.

Aber auch heute noch kann man Strike Commander recht gut spielen, wenn man sich an die hakelige Steuerung und vor allem das sehr gewöhnungsbedürftige “Flugmodell” gewöhnt hat, beziehungsweise beide Dinge auf ihre Weise einfach akzeptiert. Strike Commander ist auch eher ein Action-Shooter, der mit vielen kleinen spielmechanischen Kniffen wie einer angedeuteten Kampagne oder dem Einkaufen von Waffensystemen mich als Spieler in seinen Bann zieht.

Ich habe heute Abend die ersten neun Missionen durchgespielt und werde in der nächsten Zeit hoffentlich das Ende sehen.

Vim Motions - Teil 2, die Reise geht weiter

Im ersten Teil habe ich schon einige Basis-Motions heruntergeschrieben und nun habe ich da noch ein paar Motions, mit denen man sich ein wenig in der Datei herumbewegen kann. Und zwar kann mit gedrückter CTRL-/STRG-Taste und den Buchstaben f (einen Bildschirm vorwärts/runter), b (einen Bildschirm rückwärts/hoch), sowie d (einen halben Bildschirm vorwärts/runter) und u (einen halben Bildschirm rückwärts/hoch) bewegen. Wenn man den Cursor in einer Zeile hat, kann man diese Zeile mit zz in die Mitte des Bildschirms bewegen.

BefehlBeschreibung
<C-f>Einen Bildschirm runterscrollen
<C-b>Einen Bildschirm hochscrollen
<C-d>Einen halben Bildschirm runterscrollen
<C-u>Einen halben Bildschirm hochscrollen
zzAktuelle Position des Cursors in der Bildschirmmitte platzieren
ztAktuelle Position des Cursors oben am Bildschirm platzieren
zbAktuelle Position des Cursors unten am Bildschirm platzieren

Dann möchte man sich natürlich noch zu bestimmten Positionen im Dokument bewegen. Mit G geht es zum Ende der Datei und mit gg wieder zurück an den Anfang. Zu einer bestimmten Zeile kommt man entweder im Command-Mode mit :123 oder mit 123G. Beides setzt den Cursor in die Zeile 123. Mit Motions wie { und } bewegt man sich zwischen Absätzen (Leerzeilen) hin und her und dann gibt es noch eine Menge Motions, mit denen man sich zum Start oder Ende einer Funktion, Klasse usw. bewegen kann, die habe ich aber entweder noch nicht so recht verstanden oder ich habe sie bei mir irgendwie kaputt konfiguriert. Da muss ich also nochmal ran.

BefehlBeschreibung
ggAn den Anfang der Datei springen
GAn das Ende der Datei springen
123G oder :123Zur Zeile 123 springen
HCursor zum Anfang des Bildschirms setzen
MCursor in die Mitte des Bildschirms setzen
LCursor an den unteren Rand des Bildschirms setzen
{Zur nächsten Leerzeile oberhalb des Cursors springen
}Zur nächsten Leerzeile unterhalb des Cursors springen

Und die ultimative Weise, sich in einer Datei zu bewegen, ist über eine Suchfunktion. Und die hat es in vim glaube ich in sich. Denn nicht nur kann man mit /suchwort nach suchwort suchen, sondern kann das Ganze auch mit Regex-Patterns füttern (auch etwas, was ich aktuell noch gar nicht verwendet habe, mir reicht die “einfache” Suche). Mit n bewegt man sich dann zum nächsten Treffer bzw. mit N dann in der Treffer-Historie rückwärts in der Datei. Um die hervorgehobenen Treffer dann wieder auszublenden, kann man :nohl (oder bei mir in der Konfiguration reicht auch :noh) ausführen. Und wenn man gar keine Lust hat, ein Suchwort anzugeben, kann mit * einfach nach dem Wort suchen, das sich gerade unter bzw. in der nächsten Nähe des Cursors befindet. Was möchte man mehr?

BefehlBeschreibung
/{pattern}Nach {pattern} vorwärts in der Datei suchen
?{pattern}Nach {pattern} rückwärts in der Datei suchen
*Nach dem Wort unter bzw. in der Nähe des Cursors vorwärts in der Datei suchen
#Nach dem Wort unter bzw. in der Nähe des Cursors rückwärts in der Datei suchen
nZum nächsten Treffer springen
NZum vorhergehenden Treffer springen
:nohl bzw. :nohTreffer-Highlighting ausschalten

Man bekommt übrigens auch die Anzahl der gefundenen Treffer sowie die Nummer des Treffers angezeigt, bei dem man gerade angekommen ist. Und wer sich jetzt wundert, warum es mit * und # eigentlich die gleiche Funktion gibt: ja, die gefundenen Treffer usw. sind hierbei gleich. Der Unterschied ist dann, mit welchen Tasten man sich dann zwischen den Treffern bewegt. n und N haben mit beiden Suchmethoden dann die umgekehrte Richtung. Das gilt auch für die Suche mit / oder ?.

Vim Motions

Ich glaube, dass Benutzer von vim (oder neovim) gar keine Probleme haben alte Flugsimulatoren zu spielen. Die Anzahl an Tastatur-Shortcuts ist überwältigend und erinnert mich an die doppelte oder dreifache Belegung in solchen Simulatoren. Das ganze ist aber natürlich Teil des Konzepts. Man arbeitet schließlich in einem Terminal und die haben in ihrer reinen Form keine Mausunterstützung.
Außerdem ist es mein Ziel, die Maus so wenig wie möglich in die Hand nehmen zu müssen, da dies auch zum Teil eine Art Ablenkung beim Programmieren bedeuten kann. Nicht, dass man viel größere Probleme hat, Ablenkung zu vermeiden, aber man kann ja bei den kleinen Sachen anfangen.

Ich komme zwar schon halbwegs zurecht, was die Bewegung in vim angeht und auch wie man gewisse “Events” auslöst und das wird hier auch keine vollständige Auflistung, was so alles möglich ist, aber ich schreibe ein wenig die Befehle und Shortcuts auf, die ich mittlerweile benutze oder mir vorgenommen habe, zu verinnerlichen. Zur Erklärung der Befehle in den Tabellen: wenn dort sowas wie <C-v> steht, ist damit gemeint, dass man CTRL(STRG)-v drückt.

Grundsätzlich werden alle folgenden Befehle im Normal-Mode von vim ausgeführt. Es gibt die verschieden Modi Normal-Mode, Visual-Mode, Visual-Line-Mode, Visual-Block-Mode, Insert-Mode (hier schreibt man Code), den Replace-Mode und den Command-Mode, in die man, wie soll es auch anders sein, mit Tastatureingaben wechselt. Zum Beispiel wechselt man mit i in den Insert-Mode, um Code zu schreiben. Und zwar fängt man dann vor dem Cursor an zu schreiben. Möchte man hinter dem Cursor anfangen zu schreiben, drückt man a. Möchte man am Ende der aktuellen Zeile weiterschreiben, kann man sich mit A dorthin beamen und sofort loslegen.

BefehlBeschreibung
iWechsel in den Insert-Mode
aWechsel in den Insert-Mode (nach dem Cursor)
AWechsel in den Insert-Mode (am Ende der Zeile)
vWechsel in den Visual-Mode
<C-v>Wechsel in den Visual-Block-Mode
:Wechsel in den Command-Mode
RWechsel in den Replace-Mode
ESCWechsel in den Normal-Mode

Bewegung in vim

wasd ist natürlich neben den Pfeiltasten auch eine Art, sich in einer 3D-Landschaft virtuell zu bewegen, ist aber auch dem Umstand geschuldet, dass man dann der in der anderen Hand eine Maus hält und aufgrund der Position der Hand über der Tastatur an die üblichen Tasten zum Waffenwechsel kommt oder andere Kommandos ausführen kann beziehungsweise hierüber schnell an SHIFT, CTRL oder TAB kommt.
In vim werden die Tasten h,j,k und l für diese Bewegungen innerhalb des Textes benutzt, was einfach nur dem Umstand entsprungen ist, dass der Entwickler von vi, damals eine Tastatur verwendet hat, auf der auf diesen Tasten die Pfeiltasten lagen.

BefehlBeschreibung
hCursor nach links
jCursor nach unten
kCursor nach oben
lCursor nach rechts

Jetzt wäre es natürlich umständlich, wenn man 10 mal auf j hämmern müsste, um 10 Zeilen nach unten zu scrollen. Hier kommen dann neben den Motions von vim zusätzlich ein Count (Faktor) ins Spiel, um zu sagen, wie oft die folgende Bewegung ausgeführt werden soll. Mit 10j bewegt man sich also zehn Zeilen nach unten, was im Zusammenspiel mit relativen Zeilennummern eine Möglichkeit offenbart, sich super schnell im Code nach oben und unten zu bewegen. Grundsätzlich kann man auch mit 17l sagen, dass man den Cursor 17 Zeichen nach rechts bewegen möchte, aber mein Gehirn ist alt und kann die Zeichen horizontal nicht so schnell abzählen. Für die Bewegung innerhalb einer Zeile gibt es aber dafür auch bessere Motions.
Zum Beispiel kann man sich mit $ ans Ende der Zeile katapultieren, sich mit fx zum ersten Vorkommen des Buchstabens x bewegen. Oder man gelangt mit W zum nächsten Wort nach einem Leerzeichen. Diese Bewegungen kann man übrigens auch mit Faktoren kombinieren: mit 3W gelangt man also zum dritten Wort, dem ein Leerzeichen vorangeht.

BefehlBeschreibung
$Bewegt Cursor zum Ende der Zeile
0Bewegt Cursor zum Anfang der Zeile
^Bewegt Cursor zum ersten Zeichen einer Zeile
fxBewegt Cursor zum nächsten Buchstaben ‘x’
FxBewegt Cursor rückwärts zum nächsten Buchstaben ‘x’
txBewegt Cursor vor den nächsten Buchstaben ‘x’
TxBewegt Cursor rückwärts vor den nächsten Buchstaben ‘x’
;Wiederholt vorangegangene Motions f, F, t oder T
,Wiederholt vorangegangene Motions f, F, t oder T rückwärts
wBewegt den Cursor zum Anfang des nächsten Wortes (Interpunktion gilt auch als Wort)
WBewegt den Cursor zum Anfang des nächsten Wortes (Leerzeichen vor dem Wort)
bBewegt den Cursor zum Anfang des vorhergehenden Wortes (Interpunktion gilt auch als Wort)
BBewegt den Cursor zum Anfang des vorhergebenden Wortes (Leerzeichen vor dem Wort)
eBewegt den Cursor zum Ende des Wortes (Interpunktion gilt auch als Wort)
EBewegt den Cursor zum Ende des Wortes (Leerzeichen vor dem Wort)
geBewegt den Cursor zum Ende des vorhergehenden Wortes (Interpunktion gilt auch als Wort)
gEBewegt den Cursor zum Ende des vorhergehenden Wortes (Leerzeichen vor dem Wort)

So langsam dämmert es einem, dass da noch eine Menge Befehle kommen werden. Bereiche, wie das Springen zu bestimmten Zeilen, das Springen zwischen Funktionsblöcken oder das Suchen sind hier noch gar nicht erwähnt. Und dann kommen auch noch Motions zum Bearbeiten von Text (Löschen und so weiter). Aber für heute können wir uns schon mal recht gut innerhalb eines Dokuments bewegen.

Die Tastenbelegung der Keychron K8

Ende letzten Jahres habe ich mich von meiner heißgeliebten Vortex Pok3r getrennt und mir endlich eine mechanische Tastatur mit RGB-Tastenbeleuchtung gegönnt: eine Keychron K8. Die Pok3r hat ein 62-Tasten-Layout, was ich zwar im Blindflug beherrscht habe, aber manchmal haben dann doch der direkte Zugriff auf die Funktions- oder Pfeiltasten gefehlt.

Da ich mir aber die Tastenkombinationen für die Funktionen der Keychron-Tastatur nicht merken kann und ich jemand bin, der am besten lernt, wenn ich es jemanden erkläre oder niederschreibe, tue ich das hiermit. Vor allem, weil sie auf der offiziellen Seite falsch bzw. nicht vollständig stehen. Komplett ist die Liste hiermit nicht, ich schreibe nur die auf, die ich mir absolut nicht merken kann.

TastenkombinationFunktion
fn + bLadestand des Akkus (Lichter unter den Zahlentasten und zusätzlich farbliche Untermalung in 33%-Abstufungen (rot, blau, grün))
fn + e (+ d)Farbe der Hintergrundbeleuchtung festlegen
fn + w (+ s)Helligkeit der Hintergrundbeleuchtung festlegen
fn + q (+a)Modus der Hintergrundbeleuchtung festlegen

Markdown und neovim

Als gute Entwickler kommentieren wir natürlich unsere Arbeiten, sofern der Code nicht selbsterklärend ist. Und da Dokumentation über den Code auch hinausgeht, wenn es sich um das Aufsetzen von Projekten, Beschreibung von APIs und so weiter handelt, hat sich das Markdown-Format durchgesetzt. reStructuredText gibt es zwar auch noch, aber das nutzt man ja für komplette und zusammenhängende Dokumentationen.

Wenn man nun aber Markdown schreibt und dabei solche Dinge wie Tabellen oder ähnliches nutzt, dann habe ich persönlich dabei gerne eine Vorschaufunktion. IDEs wie PhpStorm bringen sowas als Plugin direkt mit und für neovim bin ich gestern auf markdown-preview.nvim gestoßen. Das Plugin rendert über node.js die Preview der Markdown-Datei inklusive Scrolling im Browser während man arbeitet und liefert gleich noch die Unterstützung von Flowcharts, UML und anderen Dingen mit. Was will man mehr?

Das habe ich dann gleich mal in meine neovim-Konfiguration mit aufgenommen.

Tetris

Ich halte mich jetzt nicht für einen sonderlich guten Tetris-Spieler, kann aber sagen, dass ich auf dem GameBoy wenigstens schon alle möglichen Raketen (nämlich vier) gesehen habe. Aber was dieser Junge hier auf seinem NES macht, ist einfach unglaublich. Nach knapp 38 Minuten krassester Konzentration und Fingerfertigkeit bringt er Tetris zum Absturz. Ich bin schon froh, wenn ich mal ab und zu über 200.000 Punkte in der GameBoy-Version erreiche.

Und ich mag mir nicht vorstellen, in welches Loch er gefallen sein mag. Auch wenn er erst 13 Jahre alt ist, hat er doch bestimmt jahrelang Tetris gespielt, um allein diese “Rolling” genannte Technik zu erlernen, damit er die Steine schnell genug verteilen kann. Was mag er als nächstes spielen?

Wegwerf-Vervollständigung

Ja, der Titel ist ein wenig sperrig, aber bevor wir zum erschlagenden Thema LSPs kommen, muss ich noch zwei Plugins für neovim zeigen, die ich auch nicht missen möchte.
Das erste Plugin ist ein Feature, das ich auch in “normalen” IDEs sehr gerne nutze: Wegwerf-Dateien. Gekritzel-Dateien wären die sinnvollere Übersetzung für diese Dateien. Ich paste zum Beispiel gerne einen Teil der Debug-Informationen in eine Datei ab, wenn ich programmiere, damit ich immer mal nachschauen kann, wie denn der Zustand zum Punkt X gewesen ist. Und dafür nutze ich sogenannte Scratch-Files. Die kann man mittels scratch.nvim in einem definierten Verzeichnis erstellen und später auch wieder aufrufen. Zum einen benötigt man dafür die Konfiguration des Plugins selber:

return {
  "LintaoAmons/scratch.nvim",
  event = "VeryLazy",
}

Sowie eine Konfigurations-Datei (berichtigt mich, wenn man die auch in die Plugin-Konfiguration übernehmen kann, ich habe es leider nicht geschafft), die ich unter lua/kaffdaddy/config/scratch_config.json gespeichert habe:

{
  "filetype_details": {
  }, 
  "use_telescope": true, 
  "filetypes": ["xml", "go", "lua", "js", "py", "sh", "html", "php", "css", "scss", "xml"], 
  "localKeys": [{
    "filenameContains": ["gp"], 
    "LocalKeys": [{
      "modes": ["n", "i", "v"],
      "cmd": "GpResponse",
      "key": "k"
    }]
  }], 
  "scratch_file_dir": "~/.cache/nvim/scratch.nvim",
  "window_cmd": "edit"
}

Das zweite Plugin ist insofern recht hilfreich, wenn man sich die zigtausend Befehle, die man dann so mittlerweile in vim zur Verfügung hat, nicht merken kann. which-key listet zum Beispiel nach Drücken des Leader-Keys alle Befehlsketten auf, denen man dann folgen kann und zeigt sogar den Beschreibungstext an. Auch wieder ganz einfach eine neue Datei mit folgendem Inhalt im Plugin-Verzeichnis erstellen und schon ist man nicht mehr aufgeschmissen:

return {
  "folke/which-key.nvim",
  event = "VeryLazy",
  init = function()
    vim.o.timeout = true
    vim.o.timeoutlen = 500
  end,
  opts = {
  },
}

Der aktuelle Stand der Konfiguration bis hierin ist hier zu finden.

Noch mehr Kleinkram

Kleinkram hört sich so despektierlich an, soll es aber in dem Fall gar nicht sein. Denn all diese kleinen Plugins bringen eine wunderbare Funktion mit, die mir das Leben als Entwickler einfacher machen und von daher möchte ich sie auch gar nicht missen.

Visualiserung von Farbwerten

Wer weiß denn auch schon aus dem Stegreif, was #336bff für eine Farbe ist? Ich jedenfalls nicht. Und dafür gibt es auch für neovim ein Plugin namens colorizer.lua, das Farbwerte in hexadezimaler Schreibweise mit der entsprechenden Hintergrundfarbe versieht. Und das funktioniert auch mit rgb- und hsl-Funktionen von CSS. Normalerweise versucht das Plugin Farbwerte in allen Dateitypen zu erkennen und darzustellen, ich benötige die Funktion aber lediglich in CSS/SCSS-Dateien und vielleicht ab und zu mal in JavaScript-Dateien. Daher sieht meine angepasste Konfiguration folgendermaßen aus:

return {
  "NvChad/nvim-colorizer.lua",
  event = { "BufReadPre", "BufNewFile" },
  config = function()
   local colorizer = require('colorizer')
    colorizer.setup({
      filetypes = {
        'css',
        'scss',
        'javascript',
        html = { mode = 'foreground' }
      },
      user_default_options = {
        names = false,
        rgb_fn = true,
        hsl_fn = true,
      }
    })
  end,
}

Eingaben schöner gestalten

Wenn man zum Beispiel eine Datei erstellen oder umbennen möchte, wird man normalerweise im “Prompt” von neovim zur Eingabe des Dateinamens gebeten. Damit sich das ein wenig besser in die UI von neovim einbettet, kann man dafür dressing.nvim verwenden. Das sieht dann so aus, wie oben im Screenshot festgehalten.

return {
  "stevearc/dressing.nvim",
  event = "VeryLazy",
}

Eine Statusbar für alles

Sehr oft benötige ich für mich zur Orientierung nicht nur den Pfad und Dateinamen der Datei, in der ich mich gerade befinde, sondern auch den Modus von neovim und die Kodierung und Art der Datei, sowie Zeile und Spalte, in der man sich befindet. lualine.nvim gibt einem das. Und nicht nur das, sondern man kann sich die Statusbar auch anständig konfigurieren, wenn man mit den Informationen noch nicht zufrieden ist oder die Reihenfolge geändert haben möchte.

return {
  "nvim-lualine/lualine.nvim",
  dependencies = { "nvim-tree/nvim-web-devicons" },
  config = function()
    local lualine = require("lualine")
    local lazy_status = require("lazy.status")

    local colors = {
      blue = "#65D1FF",
      green = "#3EFFDC",
      violet = "#FF61EF",
      yellow = "#FFDA7B",
      red = "#FF4A4A",
      fg = "#c3ccdc",
      bg = "#112638",
      inactive_bg = "#2c3043",
    }

    local my_lualine_theme = {
      normal = {
        a = { bg = colors.blue, fg = colors.bg, gui = "bold" },
        b = { bg = colors.bg, fg = colors.fg },
        c = { bg = colors.bg, fg = colors.fg },
      },
      insert = {
        a = { bg = colors.green, fg = colors.bg, gui = "bold" },
        b = { bg = colors.bg, fg = colors.fg },
        c = { bg = colors.bg, fg = colors.fg },
      },
      visual = {
        a = { bg = colors.violet, fg = colors.bg, gui = "bold" },
        b = { bg = colors.bg, fg = colors.fg },
        c = { bg = colors.bg, fg = colors.fg },
      },
      command = {
        a = { bg = colors.yellow, fg = colors.bg, gui = "bold" },
        b = { bg = colors.bg, fg = colors.fg },
        c = { bg = colors.bg, fg = colors.fg },
      },
      replace = {
        a = { bg = colors.red, fg = colors.bg, gui = "bold" },
        b = { bg = colors.bg, fg = colors.fg },
        c = { bg = colors.bg, fg = colors.fg },
      },
      inactive = {
        a = { bg = colors.inactive_bg, fg = colors.semilightgray, gui = "bold" },
        b = { bg = colors.inactive_bg, fg = colors.semilightgray },
        c = { bg = colors.inactive_bg, fg = colors.semilightgray },
      },
    }

    lualine.setup({
      options = {
        theme = my_lualine_theme,
      },
      sections = {
        lualine_b = {
          'branch',
          'diff',
          'diagnostics'
        },
        lualine_c = {
          {
            'filename',
            file_status = true,
            newfile_status = true,
            path = 1,
          }
        },
        lualine_x = {
          {
            lazy_status.updates,
            cond = lazy_status.has_updates,
            color = { fg = "#ff9e64" },
          },
          { "encoding" },
          { "fileformat" },
          { "filetype" },
        },
      },
    })
  end,
}

Den aktuellen Stand der Konfiguration bis hierhin kann man sich hier anschauen.