This commit is contained in:
2026-09-28 17:48:58 +02:00
parent 89c2cda81c
commit 455245664f
18 changed files with 5520 additions and 2 deletions
+161
View File
@@ -0,0 +1,161 @@
## 1. Die Basis: Modi & Navigation
Vim basiert auf dem Konzept von Modi. Um Befehle auszuführen, musst du fast immer im **Normal Mode** sein.
### Modi-Wechsel
* `i` / `a`: Insert-Modus (vor/nach Cursor).
* `I` / `A`: Insert am Zeilenanfang / Zeilenende.
* `o` / `O`: Neue Zeile unterhalb / oberhalb einfügen.
* `Esc`: Zurück in den Normal-Modus.
* `v` / `V` / `Ctrl+v`: Visueller Modus (Zeichen / Zeile / Block).
### Navigation (Normal Mode)
* **Grundbewegung:** `h` (links), `j` (runter), `k` (hoch), `l` (rechts).
* **Wortweise:** `w` (nächstes Wort), `b` (vorheriges), `e` (Wortende).
* **Zeilenweise:** `0` (Anfang), `^` (erstes Zeichen), `$` (Ende).
* **Datei-Sprünge:** `gg` (Anfang), `G` (Ende), `:n` (Zeile n).
* **Scrollen:** `Ctrl+u` / `Ctrl+d` (Halbe Seite hoch/runter).
* **Klammern:** `%` springt zur korrespondierenden Klammer `()`, `[]`, `{}`.
---
## 2. Bearbeitung & Text-Objekte
Die wahre Stärke von Vim liegt in der Kombination von **Operatoren** und **Bewegungen/Objekten**.
### Basis-Operationen
* `x`: Zeichen löschen.
* `dd`: Ganze Zeile löschen (Ausschneiden).
* `yy`: Zeile kopieren (Yank).
* `p` / `P`: Einfügen nach / vor dem Cursor.
* `u` / `Ctrl+r`: Undo / Redo.
* `.`: Die letzte Aktion wiederholen.
### Das "Verb + Adjektiv + Nomen" Prinzip
Viele Befehle folgen dem Muster: `[Zahl] + [Operator] + [Textobjekt/Bewegung]`.
* `3dw`: Lösche 3 Wörter.
* `ci"`: **C**hange **I**nside **"**: Löscht den Inhalt zwischen Anführungszeichen und geht in den Insert-Modus.
* `da(`: **D**elete **A**round **(**: Löscht die Klammern inklusive Inhalt.
* `yiw`: Kopiere das aktuelle Wort (**Y**ank **I**nside **W**ord).
---
## 3. Suche & Ersetzen (Regex & "Magic")
### Suchen in der aktuellen Datei
* `/muster`: Vorwärts suchen.
* `?muster`: Rückwärts suchen.
* `n` / `N`: Nächster / Vorheriger Treffer.
* `*` / `#`: Sucht das Wort unter dem Cursor vorwärts / rückwärts.
### Ersetzen (Substituieren)
* `:%s/alt/neu/g`: Ersetzt alle Vorkommen in der Datei.
* `:%s/alt/neu/gc`: Ersetzt mit Bestätigung für jeden Treffer.
### RegEx & Very Magic
Vim nutzt standardmäßig eine eigene RegEx-Syntax. Mit `\v` (very magic) nutzt du eine Syntax, die moderneren Sprachen (wie Python/JS) ähnelt.
```vim
" Findet abc oder ac (das ? ist in very magic ein Metazeichen)
/\vab?c
```
---
## 4. Projektweites Find & Replace (Neovim & Telescope)
Dies ist ein Workflow für umfassendes Refactoring über viele Dateien hinweg.
### Schritt 1: Suchen & Filtern
1. Starte Telescope: `:Telescope live_grep`.
2. Suche nach dem Begriff.
3. Sende Ergebnisse an die Quickfix-Liste: `Ctrl + q`.
### Schritt 2: Massen-Ersetzung mit `:cdo`
Der Befehl `:cdo` führt ein Kommando für jeden Eintrag in der Quickfix-Liste aus.
```vim
:cdo s/alter_begriff/neuer_begriff/gc | update
```
* `gc`: Global in der Zeile ersetzen, mit Bestätigung.
* `| update`: Speichert die Datei sofort, wenn eine Änderung vorgenommen wurde.
### Schritt 3: Zeilen löschen (Spezialfall)
Wenn du Zeilen, die ein Muster enthalten, komplett löschen willst, ist `:cfdo` (pro Datei) robuster als `:cdo` (pro Treffer).
```vim
:cfdo g/muster/d | update
```
---
## 5. Multi-File Suche mit `:vimgrep`
Wenn du kein Telescope nutzt, ist `:vimgrep` der integrierte Weg.
* `:vimgrep /muster/ **/*.py`: Sucht rekursiv in allen Python-Dateien.
* `:copen`: Öffnet das Quickfix-Fenster, um die Ergebnisse zu sehen.
* `:cn` / `:cp`: Springe zum nächsten/vorherigen Treffer.
---
## 6. Register & Clipboard
Vim hat mehrere "Ablagen" (Register).
* `"ayw`: Kopiere Wort in Register `a`.
* `"ap`: Füge Inhalt aus Register `a` ein.
* `"+y`: Kopiere in das **System-Clipboard** (Wichtig für Austausch mit anderen Apps!).
* `:reg`: Zeige alle aktuellen Registerinhalte an.
* `"%`: Enthält den Pfad der aktuellen Datei.
---
## 7. Effizienz-Booster: Makros & Markierungen
### Makros (Automatisierung)
* `qa`: Aufnahme in Register `a` starten.
* `q`: Aufnahme stoppen.
* `@a`: Makro `a` abspielen.
* `@@`: Das letzte Makro wiederholen.
### Markierungen (Ergänzung)
Mit Markierungen kannst du schnell zu bestimmten Stellen springen.
* `ma`: Setzt eine Markierung `a` an der aktuellen Position.
* `'a`: Springt direkt zur Markierung `a`.
---
## 8. Fenster, Tabs & Buffer
Vim verwaltet Dateien in **Buffern**. **Windows** (Splits) und **Tabs** sind nur Ansichten darauf.
* `:ls`: Alle offenen Buffer anzeigen.
* `:b 3`: Zum 3. Buffer wechseln.
* `:split` / `:vsplit`: Horizontaler / Vertikaler Split.
* `Ctrl+w w`: Zwischen Fenstern wechseln.
* `:tabnew`: Neuer Tab.
* `gt` / `gT`: Nächster / Vorheriger Tab.
---
## 9. Visual Block Mode & Kommentieren
Der Block-Modus (`Ctrl+v`) ist ideal, um Textspalten zu bearbeiten.
### Block-Kommentieren (Manuell)
1. `Ctrl+v` drücken und Zeilen nach unten markieren.
2. `Shift+i` (Insert am Anfang des Blocks).
3. Kommentarzeichen eingeben (z. B. `# `).
4. `Esc` drücken – die Änderung wird auf alle Zeilen angewendet.
### Plugin-Empfehlung: `vim-commentary`
Mit diesem Plugin reicht ein Befehl:
* `gcc`: Kommentiert die aktuelle Zeile um/aus.
* `gc` (im Visual Mode): Kommentiert den markierten Block.
---
## 10. Konfiguration (.vimrc / init.lua)
Einige Standard-Einstellungen, die jeder Power-User haben sollte:
```vim
set number " Absolute Zeilennummer der aktuellen Zeile
set relativenumber " Relative Nummern für alle anderen Zeilen (ideal für 5j, 3k)
set expandtab " Leerzeichen statt Tabs
set tabstop=4 " Tab-Breite
set ignorecase " Suche ignoriert Groß/Kleinschreibung...
set smartcase " ...außer du tippst einen Großbuchstaben
```
---
### Profi-Tipp: Befehlsbuffer
Wenn du einen komplexen Ex-Befehl (mit `:`) getippt hast und ihn bearbeiten willst, drücke im Normal-Modus `q:`. Es öffnet sich ein Fenster mit der Historie deiner Befehle, die du wie normalen Text bearbeiten und mit `Enter` neu ausführen kannst.
@@ -0,0 +1,146 @@
## Introduction[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#introduction)
Maintaining an organized and efficient codebase is essential for every developer. Neovim, a powerful text editor, offers a range of tools that can help you make global changes throughout your project with ease.
In this blog post, we’ll explore how to perform a project-wide find and replace using Neovim, Telescope, the Quickfix List, and the `:cdo` command. No complicated jargon, just straightforward guidance to enhance your coding experience.
## Prerequisites[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#prerequisites)
Before you start, ensure you have the following prerequisites in place:
1. Neovim installed.
2. The Telescope plugin installed.
3. A project directory opened in Neovim.
## Using Telescope for Live Grep[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#using-telescope-for-live-grep)
### 1. Initiate Telescope[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#1-initiate-telescope)
In Neovim’s Normal mode, execute the following command:
```shell
:Telescope live_grep
```
This opens the Telescope live grep prompt, ready for your query.
### 2. Enter Your Search Query[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#2-enter-your-search-query)
Type your search query. Telescope will display a list of search results throughout your project.
### 3. Open Results in Quickfix List[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#3-open-results-in-quickfix-list)
After searching for your query, press `Ctrl + q` to open the search results in the Quickfix List.
## Utilizing `:cdo` for Find and Replace[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#utilizing-cdo-for-find-and-replace)
### 4. Run the `:cdo` Command[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#4-run-the-cdo-command)
With the Quickfix List open, you can now perform the find and replace operation. Execute the following command:
```shell
:cdo s/query_string/replacement_string/gc
```
- `:cdo` applies a command to each entry in the Quickfix List.
- `s/query_string/replacement_string/gc` is the find and replace command, with `g` for global replacement.
- The `/c` flag provides confirmation before each replacement.
Press Enter to initiate the find and replace with confirmation.
### 5. Save Changes[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#5-save-changes)
If you’re satisfied with the changes and want to save them across all files in your project, you can use the `:wa` command:
```shell
:wa
```
## Conclusion[](https://blog.chaitanyashahare.com/posts/project-wide-find-and-replace-in-neovim/#conclusion)
Performing a project-wide find and replace in Neovim using Telescope, the Quickfix List, and the `:cdo` command is a potent approach that simplifies codebase maintenance. It allows you to make comprehensive changes while retaining full control over the replacement process, with the added `/c` flag providing a confirmation step for each replacement. By incorporating these techniques into your Neovim workflow, you’ll significantly improve your coding experience and efficiency. Use `:wa` to save your changes across all files and ensure your project is up to date.
# Bsp Zeilen mit Treffern löschen
Es gibt zwei leicht verschiedene Dinge:
1. Zeilen **in den Dateien** löschen
2. Einträge **aus der Quickfix‑Liste** löschen
Ich nehme an, du meinst 1., also die Zeilen in den Dateien entfernen, wo `live_grep` dein Wort gefunden hat. Ich zeige aber beide Varianten.
---
## 1. Zeilen in den Dateien löschen (empfohlen)
Du hast `live_grep` mit z.B. `wits` gemacht und die Treffer in die Quickfix-Liste geschickt (`<C-q>`).
Jetzt willst du **alle Zeilen in den Dateien löschen, die `wits` enthalten**.
Das geht am saubersten mit `:cfdo` + `:global`:
```vim
:cfdo g/wits/d | update
```
Erklärung:
- `cfdo` – führe den folgenden Befehl für jede **Datei** aus, die in der Quickfix-Liste vorkommt
- `g/wits/d` – in dieser Datei: lösche **alle Zeilen**, die `wits` enthalten
- `| update` – speichere die Datei, wenn sie geändert wurde
Damit sind nachher in allen Dateien, die in der Quickfix-Liste sind, sämtliche Zeilen mit `wits` weg.
### Variante ohne hartkodiertes Muster
Wenn du das Suchmuster noch einmal mit `/` gesetzt hast, kannst du es statt `wits` auch aus der letzten Suche nehmen:
```vim
/"dein muster"
:cfdo g//d | update
```
`g//` benutzt dann das aktuelle Suchmuster aus `/`.
---
## 2. Zeilen *aus der Quickfix-Liste* löschen
Falls du **nur die Einträge in der Quickfix-Liste selbst** filtern oder löschen willst (nicht die Dateien):
Quickfix-Fenster öffnen:
```vim
:copen
```
### Einträge mit bestimmtem Muster entfernen
```vim
:cfilter! wits
```
- `:cfilter {pat}` – behält nur Einträge, die `{pat}` matchen
- `:cfilter! {pat}` – entfernt Einträge, die `{pat}` matchen
Mit `:cfilter! wits` würdest du also alle Quickfix-Einträge wegwerfen, die `wits` enthalten (die Dateien bleiben unverändert).
---
## 3. Warum nicht `:cdo normal! dd`?
Rein technisch könntest du auch:
```vim
:cdo normal! dd
```
Das löscht in jeder Datei die jeweilige Trefferzeile.
Aber: `:cdo` läuft pro **Quickfix-Eintrag**; wenn du Zeilen löschst, können die nachfolgenden Einträge (mit alten Zeilennummern) verrutschen. Deshalb ist `:cfdo g/pattern/d` robuster – da wird pro Datei einmal gearbeitet, nicht pro Eintrag.
---
Kurzfassung für dein konkretes Beispiel (`wits` aus den Dateien löschen):
```vim
:cfdo g/wits/d | update
```
+476
View File
@@ -0,0 +1,476 @@
Hier ist ein kompaktes, aber vollständiges **VIM Cheat Sheet** 📝
---
## 🔹 Modi in VIM
|Modus|Bedeutung|Wechsel|
|---|---|---|
|**Normal Mode**|Navigation & Befehle|`Esc`|
|**Insert Mode**|Texteingabe|`i`, `a`, `o`, etc.|
|**Visual Mode**|Text markieren|`v`, `V`, `Ctrl+v`|
|**Command Mode**|Speichern, Beenden, etc.|`:`|
---
## 🔹 Insert Mode Befehle
|Befehl|Wirkung|
|---|---|
|`i`|Vor Cursor einfügen|
|`a`|Nach Cursor einfügen|
|`I`|Am Zeilenanfang einfügen|
|`A`|Am Zeilenende einfügen|
|`o`|Neue Zeile unterhalb|
|`O`|Neue Zeile oberhalb|
---
## 🔹 Navigation (Normal Mode)
### Zeichenweise
```
h ← j ↓ k ↑ l →
```
### Wortweise
```
w nächstes Wort
b vorheriges Wort
e Wortende
```
### Zeilenweise
```
0 Zeilenanfang
^ Erstes Nicht-Leerzeichen
$ Zeilenende
```
### Datei
```
gg Anfang der Datei
G Ende der Datei
:n Gehe zu Zeile n
```
---
## 🔹 Löschen
|Befehl|Wirkung|
|---|---|
|`x`|Zeichen löschen|
|`dd`|Zeile löschen|
|`dw`|Wort löschen|
|`d$`|Bis Zeilenende löschen|
|`d0`|Bis Zeilenanfang löschen|
💡 Kombination: `d` + Bewegung funktioniert immer
(z.B. `d3w` = 3 Wörter löschen)
---
## 🔹 Kopieren & Einfügen
|Befehl|Wirkung|
|---|---|
|`yy`|Zeile kopieren|
|`yw`|Wort kopieren|
|`p`|Nach Cursor einfügen|
|`P`|Vor Cursor einfügen|
#### Register
Vor alle Kopieren oder Einfügen Befehle kann ein `"3` gestellt werden, um ins 3. Register zu schreiben bzw. daraus heraus zu lesen. Z.b. kopiert `"7yw` das Wort ins 7. Register und `"4p` fügt das 4. Register nach dem Curser ein.
💡 Das spezielle Register `+`/`*` ist das System-Clipboard, sehr Praktisch zum Austausch von Text mit anderen Programmen
Alle Register ansehen: `:reg`
💡 Das spezielle Register `%` enthält den aktuellen Dateipfad -> aktuelle Dateipfad in System-Clipboard: `:let @+=@%`.
---
## 🔹 Undo / Redo
```
u Undo
Ctrl+r Redo
```
---
## 🔹 Visual Mode
|Befehl|Wirkung|
|---|---|
|`v`|Zeichenweise markieren|
|`V`|Ganze Zeile markieren|
|`Ctrl+v`|Block markieren|
Nach Markierung:
```
d löschen
y kopieren
> einrücken
< ausrücken
```
---
## 🔹 Suchen & Ersetzen
```
/text Vorwärts suchen
?text Rückwärts suchen
n Nächstes Ergebnis
N Vorheriges Ergebnis
```
Ersetzen:
```
:%s/alt/neu/g Ganze Datei
:s/alt/neu/g Aktuelle Zeile
:%s/alt/neu/gc Mit Bestätigung
```
Nutze "echtes" RegEx ("very magic"):
```
/\v...
```
zB
```
/\vab?c
```
findet `abc` und `ac` . Das würde mit herkömmlicher Vim RegEx nicht funktionieren
Suchen und ersetzen
```
:%s/\vfoo (ab?c)(bar)/bas \1 \2/
```
---
## 🔹 Speichern & Beenden
```
:w Speichern
:q Beenden
:wq Speichern & Beenden
:x Speichern & Beenden
:q! Ohne Speichern beenden
```
---
## 🔹 Fenster & Tabs
```
:split Horizontal teilen
:vsplit Vertikal teilen
Ctrl+w w Zwischen Fenstern wechseln
:tabnew Neuer Tab
gt Nächster Tab
gT Vorheriger Tab
```
---
## 🔹 Nützliche Shortcuts
```
. Letzte Aktion wiederholen
>> Zeile einrücken
<< Zeile ausrücken
ciw Wort ändern
cc Zeile ändern
J Zeilen zusammenführen
```
---
## 🔹 Makros
```
qa Aufnahme in Register a starten
q Aufnahme stoppen
@a Makro a ausführen
@@ Letztes Makro wiederholen
```
---
## 🔹 Zahlen-Präfixe (Sehr wichtig!)
Viele Befehle lassen sich multiplizieren:
```
3dd 3 Zeilen löschen
5w 5 Wörter vor
2yy 2 Zeilen kopieren
```
---
# Zeilennummern aus- und anschalten
---
## 🔹 Absolute Zeilennummern
### Einschalten:
```vim
:set number
```
### Ausschalten:
```vim
:set nonumber
```
### Toggle:
```vim
:set number!
```
---
## 🔹 Relative Zeilennummern
### Einschalten:
```vim
:set relativenumber
```
### Ausschalten:
```vim
:set norelativenumber
```
### Toggle:
```vim
:set relativenumber!
```
---
## 🔹 Absolute + Relative kombinieren (Sehr beliebt 🔥)
Viele nutzen diese Kombination:
```vim
:set number relativenumber
```
👉 Ergebnis:
* Aktuelle Zeile = **absolute Nummer**
* Alle anderen Zeilen = **relative Nummern**
Beispiel:
```
8
2
1
10 ← aktuelle Zeile
1
2
3
```
Das ist perfekt für Bewegungen wie:
```
5j
3k
```
---
## 🔹 Dauerhaft aktivieren (.vimrc)
In deiner `~/.vimrc`:
```vim
set number
set relativenumber
```
---
## 🔹 Smart Toggle Mapping (Optional ⭐)
Viele nutzen ein Keybinding:
```vim
nnoremap <leader>n :set number! relativenumber!<CR>
```
Dann kannst du mit:
```
\ n
```
(beim Standard-`leader`) beide gleichzeitig toggeln.
---
# Block Aus- und Einkommentieren
---
# 🔹 1️⃣ Rein mit Vim (ohne Plugin)
## ✅ Ganze Zeilen im Visual Mode kommentieren
### Schritt 1: Block markieren
* `V` → Zeilenweise markieren
* `j / k` → Bereich wählen
### Schritt 2: Kommentarzeichen einfügen
Beispiel für `#`:
```vim
:s/^/# /
```
Im Visual Mode einfach:
```vim
:'<,'>s/^/# /
```
👉 Fügt `# ` am Anfang jeder markierten Zeile ein.
---
## 🔹 Auskommentieren
```vim
:'<,'>s/^# //
```
---
## 🔹 Noch schneller (ohne `:` tippen)
Markieren mit `V`, dann:
```vim
:s/^/# /
```
Vim setzt `'<,'>` automatisch.
---
# 🔹 2️⃣ Noch effizienter: Visual Block Mode (Sehr elegant ⚡)
Perfekt für feste Kommentarzeichen wie `#`, `//`, `--`.
### Schritt 1
```
Ctrl + v
```
### Schritt 2
Mit `j/k` mehrere Zeilen markieren (nur Spalte 0)
### Schritt 3
```
Shift + i
#
Esc
```
💥 Vim fügt das in alle markierten Zeilen ein.
---
## 🔹 Entfernen mit Block Mode
1. `Ctrl + v`
2. Erste 2 Zeichen (`# `) markieren
3. `d`
---
# 🔹 3️⃣ Beste Lösung: Plugin (Empfohlen 🔥)
Wenn du regelmäßig kommentierst → nimm ein Plugin.
Sehr beliebt:
* vim-commentary von Tim Pope
### Installation (mit vim-plug):
```vim
Plug 'tpope/vim-commentary'
```
### Nutzung:
* `gcc` → aktuelle Zeile toggeln
* `gc` (im Visual Mode) → Block toggeln
💎 Vorteil:
* erkennt automatisch Kommentarzeichen je nach Dateityp
* funktioniert mit `//`, `#`, `--`, `/* */`, etc.
---
# 🔹 4️⃣ Absolute Power-User Lösung (Ohne Plugin, aber smart)
In `.vimrc`:
```vim
vnoremap <leader>c :s/^/# /<CR>
vnoremap <leader>u :s/^# //<CR>
```
Dann:
```
\c → kommentieren
\u → auskommentieren
```
---
# 🔥 Meine Empfehlung
| Wenn du... | Lösung |
| ----------------------------- | ----------------- |
| Nur selten kommentierst | Visual Block Mode |
| Viel programmierst | vim-commentary |
| Minimalistisch bleiben willst | eigenes Mapping |
---
# Verschiedenes
- `%`: zur nächsten Klammer
- `TOhtml`: HTML Export
- `:ls`: Buffer anzeigen -> `:b 3` den 3. Buffer öffnen
- `.` : letzte Aktion wiederholen
- `:e path/to/file` öffnet Datei, nur `:e` aktualisiert die geöffnete Datei, `:e!` verwirft dabei alle Änderungen
- `q:` : öffne Befehlsbuffer
- Dort kann man z.B. mit `"+yy` Befehle ins Clipboard kopieren
-
+214
View File
@@ -0,0 +1,214 @@
## Modi
```text
i In den Insert-Modus (vor Cursor)
I Insert am Zeilenanfang
a Insert nach Cursor
A Insert am Zeilenende
o Neue Zeile unterhalb + Insert
O Neue Zeile oberhalb + Insert
<Esc> Zurück in Normalmodus
v Visueller Modus (Zeichenweise)
V Visueller Modus (Zeilenweise)
<C-v> Visueller Blockmodus
```
## Navigation (Normalmodus)
```text
h j k l Links / runter / hoch / rechts
0 Zeilenanfang
^ Erstes nicht-leer Zeichen
$ Zeilenende
w Zum nächsten Wortanfang
b Zum vorherigen Wortanfang
e Zum Wortende
W B E Wie oben, aber Worte durch Leerzeichen getrennt
gg Erste Zeile
G Letzte Zeile
ngg / nG Zu Zeile n
H Oberer Bildschirmrand
M Mittlerer Bildschirmrand
L Unterer Bildschirmrand
Ctrl-u Halbe Seite hoch
Ctrl-d Halbe Seite runter
Ctrl-b Seite hoch
Ctrl-f Seite runter
```
## Basis-Bearbeitung
```text
x Zeichen unter Cursor löschen
X Zeichen links vom Cursor löschen
r<char> Zeichen ersetzen
dd Zeile löschen (cut)
D Bis zum Zeilenende löschen
cc Zeile ändern (delete + insert)
C Bis zum Zeilenende ändern
yy Zeile kopieren
Y Alias für yy
p Einfügen NACH Cursor/Zeile
P Einfügen VOR Cursor/Zeile
u Undo
Ctrl-r Redo
J Nächste Zeile an aktuelle anhängen
>> Zeile einrücken (indent)
<< Zeile ausrücken (unindent)
```
## Mit Counts & Bewegungen
Viele Befehle funktionieren mit einer Anzahl (count) und einer Bewegung:
```text
3w 3 Wörter vor
5j 5 Zeilen runter
d3w 3 Wörter löschen
c$ Bis Zeilenende ändern
y0 Bis Zeilenanfang kopieren
```
## Textobjekte (im Normal- / Visuellen Modus)
```text
aw A word (inkl. Leerzeichen)
iw Inner word
as A sentence
is Inner sentence
ap A paragraph
ip Inner paragraph
a" / i" Text in Anführungszeichen
a' / i' Text in einfachen Quotes
a) / i) Text in Klammern (usw. für {}, [], <>)
Beispiele:
ci" Inhalt von "..." ändern
da( Klammerausdruck inklusive Klammern löschen
viw Wort unter Cursor markieren
```
## Suchen & Ersetzen
```text
/word Vorwärts nach „word“ suchen
?word Rückwärts suchen
n Nächster Treffer
N Vorheriger Treffer
* Wort unter Cursor vorwärts suchen
# Wort unter Cursor rückwärts suchen
:%s/alt/neu/g In gesamter Datei ersetzen
:%s/alt/neu/gc Mit Bestätigung
:.,$s/alt/neu/g Von aktueller Zeile bis Ende
:10,20s/alt/neu/g In Zeilen 10–20
```
## Dateien, Buffers, Splits & Tabs
```text
:e datei Datei öffnen
:w Speichern
:w name Unter anderem Namen speichern
:q Beenden
:q! Beenden ohne Speichern
:wq / :x Speichern und beenden
:qa Alle Fenster schließen
:qa! Alle schließen ohne Speichern
" Buffer (Dateien im Speicher)
:ls Buffer-Liste
:buffer n Buffer n öffnen
:bnext / :bn Nächster Buffer
:bprev / :bp Vorheriger Buffer
:bdelete Buffer schließen
" Splits
:split datei Horizontaler Split
:vsplit datei Vertikaler Split
Ctrl-w s Split horizontal
Ctrl-w v Split vertikal
Ctrl-w w Zum nächsten Split
Ctrl-w h/j/k/l Split wechseln
Ctrl-w q Split schließen
" Tabs
:tabnew Neuer Tab
:tabclose Tab schließen
:tabnext / :tn Nächster Tab
:tabprev / :tp Vorheriger Tab
```
## Visual Mode Aktionen
```text
v / V / Ctrl-v Auswahl starten
y Auswahl kopieren
d Auswahl löschen
c Auswahl ändern
> Einrücken
< Ausrücken
= Auto-Indent (z.B. für Code)
: Befehl auf Auswahl anwenden
(Bereich wird automatisch eingetragen)
```
## Makros & Wiederholung
```text
. Letzte Änderung wiederholen
q<a> Macro in Register a aufzeichnen
(z.B. qa)
... Aktionen ausführen
q Aufzeichnung beenden
@a Macro a ausführen
3@a Macro 3x ausführen
@@ Letztes Macro wiederholen
```
## Register
```text
"0 Zuletzt kopiertes (y) ohne delete
"1–"9 Verlaufsregister
"" Default-Register
"+ System-Clipboard (kopieren/einfügen mit OS)
"* Auswahl-Clipboard (unter Linux/X11)
Beispiele:
"ayw Wort in Register a kopieren
"ap Inhalt von Register a einfügen
"+y In System-Clipboard kopieren
"+p Aus System-Clipboard einfügen
```
## Kommandomodus (Ex-Befehle)
```text
:!cmd Externen Befehl ausführen
:r !cmd Ausgabe von cmd einfügen
:r datei Datei unter Cursor-Zeile einfügen
:set nu Zeilennummern an
:set nonu Zeilennummern aus
:set relativenumber Relative Nummern
:set tabstop=4 shiftwidth=4 expandtab
```
## Einfache .vimrc-Beispiele
```vim
" Zeilennummern
set number
set relativenumber
" Einrückung
set tabstop=4
set shiftwidth=4
set expandtab
set smartindent
" Suche
set ignorecase
set smartcase
set hlsearch
set incsearch
" Maus
set mouse=a
```
@@ -0,0 +1,111 @@
In Vim kannst du mit regulären Ausdrücken über *mehrere Dateien* suchen, typischerweise über das Quickfix-/Location-List-System. Die wichtigsten Befehle dafür sind `:vimgrep` und `:grep`.
---
## 1. Mehrdatei-Suche mit `:vimgrep`
Grundform:
```vim
:vimgrep /MUSTER/ {Dateiliste}
```
Beispiele:
```vim
" In allen .py-Dateien im aktuellen Verzeichnis
:vimgrep /foo/ *.py
" Rekursiv in allen .py-Dateien
:vimgrep /foo/ **/*.py
" In allen Dateien des aktuellen Git-Repos (falls du Pfade generierst)
:vimgrep /foo/ `git ls-files`
```
Danach:
- Quickfix-Fenster öffnen:
```vim
:copen
```
- Zum nächsten Treffer springen:
```vim
:cn
```
- Zum vorherigen Treffer springen:
```vim
:cp
```
---
## 2. Regex-Varianten: Standard vs. „very magic“
Vim-Regex kann per Präfix gesteuert werden:
- Standard (abhängig von `'magic'`-Option)
- `\v` = *very magic* (fast alles ist Meta-Zeichen)
- `\m` = *magic*
- `\M` = *nomagic*
- `\V` = *very nomagic*
Du kannst das direkt im Suchmuster verwenden:
```vim
" Very magic: ( ) + ? | etc. sind sofort Metazeichen
:vimgrep /\vfoo(bar|baz)\d+/ **/*.txt
" Standard-/Default-Verhalten (meistens wie :set magic)
:vimgrep /foo\(bar\|baz\)\d\+/ **/*.txt
```
Kurz gesagt:
- Wenn du „normale“ moderne RegEx-Syntax willst, nimm einfach `\v` am Anfang des Patterns.
---
## 3. Suche mit `:grep` (externes Tool)
Wenn `grepprg` entsprechend gesetzt ist (z.B. auf `rg`, `ag` oder `grep`):
```vim
:grep foo **/*.py
:copen
```
Auch hier gilt: das Muster ist in vielen Fällen *nicht* Vim-Regex, sondern die Regex-Syntax des externen Tools (z.B. ripgrep).
Wenn du explizit Vim-Regex willst, bleib bei `:vimgrep`.
---
## 4. Dateien vorher definieren und dann suchen
Du kannst zuerst eine Dateiliste definieren und dann in dieser Liste suchen:
```vim
" Alle C-Dateien rekursiv in die Argumentliste
:args **/*.c
" Jetzt in allen Dateien aus :args suchen
:vimgrep /\vmy_func\(/ ##
" ## bedeutet: alle Dateien in der aktuellen Argumentliste
```
---
## 5. Treffern zur bestehenden Liste hinzufügen
Wenn du mehrere Suchläufe kombinieren willst:
```vim
:vimgrep /foo/ **/*.py
:vimgrepadd /bar/ **/*.py " fügt Treffer für bar hinzu
:copen
```
---
Wenn du mir sagst, ob du eher mit `rg`/`ag` arbeitest oder nur mit purem Vim, kann ich dir ein paar konkrete Konfig-/Mapping-Beispiele geben.
File diff suppressed because it is too large Load Diff
+780
View File
@@ -0,0 +1,780 @@
---
# 🐳 Einführung in Docker
## 1. Was ist Docker?
Docker ist eine Plattform, mit der du **Container** erstellen, starten und verwalten kannst.
Ein Container ist eine Art "leichtgewichtige virtuelle Maschine":
- Enthält **nur das Nötigste** (Programm, Abhängigkeiten, Bibliotheken).
- Läuft isoliert, aber nutzt den Kernel des Host-Systems (kein eigener Kernel wie bei einer VM).
- Ist **schneller** und **ressourcenschonender** als klassische VMs.
👉 Bildlich: Statt für jedes Programm einen eigenen PC (VM) aufzubauen, packst du nur das Programm in eine "Transportbox" (Container), die überall läuft, solange Docker installiert ist.
---
## 2. Vorteile und typische Anwendungsfälle
### Vorteile
- **Portabilität**: „Läuft auf meinem Rechner“ = „läuft auch auf Servern“.
- **Isolierung**: Verschiedene Programme/Versionen stören sich nicht.
- **Leichtgewicht**: Start in Sekunden statt Minuten wie bei VMs.
- **Reproduzierbarkeit**: Gleiche Umgebung für Entwicklung, Test und Produktion.
- **Einfache Verteilung**: Images können über Docker Hub oder private Registries geteilt werden.
### Typische Anwendungsfälle
- 🚀 **Entwicklung**: Z. B. [[Python]] 3.10 testen, obwohl auf dem System Python 3.12 läuft.
- 🗄️ **Datenbanken**: [[MySQL]], PostgreSQL, Redis, MongoDB zum Testen ohne Installation.
- 🌐 **Web-Apps**: Schnell mal eine fertige Anwendung ausprobieren (WordPress, Nextcloud, GitLab etc.).
- 🧪 **Testing**: Mehrere Umgebungen simulieren (verschiedene OS, Bibliotheksversionen).
- 📦 **Deployment**: Gleiche App auf mehreren Servern identisch bereitstellen.
---
## 3. Hauptfunktionalitäten von Docker
- **Docker Engine**: Herzstück, das Container ausführt.
- **Docker Images**: Baupläne (Templates) für Container (z. B. Python 3.12 + Flask).
- **Docker Containers**: Laufende Instanzen von Images.
- **Docker Hub/Registry**: Cloud-Marktplatz für fertige Images.
- **Docker Compose**: Orchestrierung mehrerer Container (z. B. App + DB + Cache).
---
## 4. Installation unter Linux (Beispiel: Ubuntu/Debian)
```bash
# 1. Alte Versionen entfernen
sudo apt-get remove docker docker-engine docker.io containerd runc
# 2. Repository vorbereiten
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# Docker GPG-Key hinzufügen
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Repository einrichten
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 3. Docker installieren
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 4. Testen
sudo docker run hello-world
```
👉 Danach kannst du optional dich in die `docker`-Gruppe aufnehmen (sonst musst du immer `sudo` schreiben):
```bash
sudo usermod -aG docker $USER
# Abmelden/neu anmelden, damit es wirkt
```
---
## 5. Erste Schritte in der Praxis
### Beispiel 1: Linux — Container starten
```bash
# Einen Ubuntu-Container starten (interaktiv)
docker run -it ubuntu bash
# Danach bist du im Container:
root@<id>:/# cat /etc/os-release
```
Wenn du rausgehst (`exit`), bleibt der Container gespeichert.
---
### Beispiel 2: Linux — Nginx-Webserver starten
```bash
# Nginx starten, Port 8080 weiterleiten
docker run -d -p 8080:80 nginx
# Nun im Browser: http://localhost:8080
```
---
### Beispiel 3: Python im Container
Nehmen wir an, du willst ein Python-Skript in einer isolierten Umgebung ausführen.
**hello.py**
```python
print("Hello from Dockerized Python!")
```
**Dockerfile**
```dockerfile
FROM python:3.11-slim
# Skript ins Image kopieren
COPY hello.py /app/hello.py
# Arbeitsverzeichnis setzen
WORKDIR /app
# Default-Befehl
CMD ["python", "hello.py"]
```
**Bauen und starten**
```bash
# Image bauen
docker build -t mypythonapp .
# Container starten
docker run --rm mypythonapp
```
Ausgabe:
```
Hello from Dockerized Python!
```
---
### Beispiel 4: Python mit externer Bibliothek
```python
# requirements.txt
flask==3.0.0
```
**app.py**
```python
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, Docker!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
```
**Dockerfile**
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
```
**Starten**
```bash
docker build -t flaskapp .
docker run -d -p 5000:5000 flaskapp
```
👉 Browser öffnen: `http://localhost:5000`
---
## 6. Nützliche Docker-Befehle (Cheatsheet)
- `docker ps` – laufende Container
- `docker ps -a` – alle Container (inkl. gestoppter)
- `docker images` – vorhandene Images
- `docker stop <id>` – Container stoppen
- `docker rm <id>` – Container löschen
- `docker rmi <image>` – Image löschen
- `docker exec -it <id> bash` – in Container einsteigen
---
✅ Damit hast du einen vollständigen Überblick über Docker:
- **Grundidee**
- **Vorteile/Anwendungsfälle**
- **Installation**
- **Praxis mit Linux und Python**
---
# Anwendungsbeispiel
# 🐳 Docker Anwendungsbeispiel - Detaillierte Erklärung für Einsteiger
## 📚 Was ist Docker überhaupt?
**Docker** ist wie ein **"Umzugskarton für Software"**:
- Stell Dir vor, Du willst Deine App an einen Freund verschicken
- Statt nur den Code zu senden, packst Du **alles** ein: Code, Python, alle Bibliotheken, Konfiguration
- Dein Freund öffnet den "Karton" (Container) und alles läuft sofort - egal welches Betriebssystem er hat
---
## 📁 Projektstruktur mit Erklärungen
```
python-docker-project/
├── app/ # 📂 Unser Python-Code
│ ├── __init__.py # (macht 'app' zu einem Python-Paket)
│ ├── main.py # Hauptprogramm
│ ├── data_processor.py # Modul für Datenverarbeitung
│ └── database.py # Modul für Datenbankzugriff
├── input/ # 📁 Hier liegen die Input-Dateien (vom Host)
│ └── sample_data.csv # Beispieldatei
├── output/ # 📁 Hier kommen verarbeitete Dateien rein
├── requirements.txt # 📝 Liste aller Python-Pakete die wir brauchen
├── Dockerfile # 🐳 "Bauanleitung" für unseren Container
├── docker-compose.yml # 🎼 "Dirigent" für mehrere Container
└── .env # 🔐 Geheime Einstellungen (Passwörter etc.)
```
---
## 🐍 Python-Code (wie gewohnt)
### **requirements.txt** - "Einkaufsliste" für Python-Pakete
```txt
# 🛒 Diese Pakete braucht unser Programm
pandas==2.1.4 # Für Excel/CSV-Verarbeitung
psycopg2-binary==2.9.9 # Um mit PostgreSQL zu sprechen
python-dotenv==1.0.0 # Um .env-Dateien zu lesen
sqlalchemy==2.0.23 # Einfache Datenbankanbindung
```
**💡 Warum brauche ich das?**
- Ohne Docker müsstest Du auf jedem PC manuell `pip install pandas` etc. machen
- Mit Docker installiert sich das automatisch im Container
### **app/main.py** - Unser Hauptprogramm
```python
#!/usr/bin/env python3
"""
🎯 Das macht unser Programm:
1. Schaut in /app/input nach CSV-Dateien
2. Verarbeitet sie (quadriert Werte, etc.)
3. Speichert Ergebnis in PostgreSQL-Datenbank
4. Exportiert auch als CSV in /app/output
"""
import os
import time
from pathlib import Path
from dotenv import load_dotenv
from .data_processor import DataProcessor
from .database import DatabaseManager
def main():
print("🚀 Starte Data Processing Pipeline...")
# 📁 Diese Pfade sind INSIDE dem Container!
input_dir = Path("/app/input") # Gemountet von Host ./input/
output_dir = Path("/app/output") # Gemountet von Host ./output/
output_dir.mkdir(exist_ok=True)
# 🗄️ Verbindung zur Datenbank (anderer Container!)
db_manager = DatabaseManager()
processor = DataProcessor(db_manager)
# 📊 Alle CSV-Dateien finden und verarbeiten
csv_files = list(input_dir.glob("*.csv"))
if not csv_files:
print("❌ Keine CSV-Dateien im Input-Verzeichnis gefunden!")
return
for csv_file in csv_files:
print(f"📄 Verarbeite: {csv_file.name}")
# 1️⃣ Daten aus CSV laden und verarbeiten
result_data = processor.process_file(csv_file)
# 2️⃣ In PostgreSQL-Container speichern
processor.save_to_database(result_data, csv_file.stem)
# 3️⃣ Als neue CSV-Datei exportieren
output_file = output_dir / f"processed_{csv_file.name}"
result_data.to_csv(output_file, index=False)
print(f"💾 Gespeichert als: {output_file}")
print("✅ Pipeline abgeschlossen!")
if __name__ == "__main__":
main()
```
### **app/database.py** - Spricht mit der Datenbank
```python
import os
import pandas as pd
from sqlalchemy import create_engine, text
class DatabaseManager:
def __init__(self):
# 🔌 Diese Werte kommen aus der docker-compose.yml!
self.host = os.getenv('DB_HOST', 'postgres') # Name des DB-Containers!
self.port = os.getenv('DB_PORT', '5432')
self.database = os.getenv('DB_NAME', 'dataprocessing')
self.user = os.getenv('DB_USER', 'postgres')
self.password = os.getenv('DB_PASSWORD', 'password')
# 🌐 Connection String - wie eine Adresse zur Datenbank
self.connection_string = (
f"postgresql://{self.user}:{self.password}@"
f"{self.host}:{self.port}/{self.database}"
)
self.engine = None
self._connect()
def _connect(self):
"""Verbindung zur Datenbank herstellen"""
try:
self.engine = create_engine(self.connection_string)
# 🏓 Kurzer Test: "Hallo Datenbank!"
with self.engine.connect() as conn:
conn.execute(text("SELECT 1"))
print("✅ Datenbankverbindung erfolgreich")
except Exception as e:
print(f"❌ Datenbankverbindung fehlgeschlagen: {e}")
raise
def save_dataframe(self, df: pd.DataFrame, table_name: str):
"""Speichert DataFrame als Tabelle in PostgreSQL"""
df.to_sql(
name=table_name,
con=self.engine,
if_exists='replace', # Überschreibt existierende Tabelle
index=False
)
```
*(Die anderen Python-Dateien bleiben gleich)*
---
## 🐳 Dockerfile - "Bauanleitung" für unseren Container
```dockerfile
# 🏗️ SCHRITT 1: Basis-Image wählen
# Das ist wie ein "Rohbau" - Linux + Python sind schon installiert
FROM python:3.11-slim
# 🛠️ SCHRITT 2: System-Tools installieren
# Wir brauchen gcc und libpq-dev für PostgreSQL-Verbindung
RUN apt-get update && apt-get install -y \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
# 💡 WARUM: psycopg2 (PostgreSQL-Driver) braucht diese Tools zum Kompilieren
# 📂 SCHRITT 3: Arbeitsverzeichnis setzen
WORKDIR /app
# Das ist wie "cd /app" - alle folgenden Befehle laufen hier
# 📦 SCHRITT 4: Python-Pakete installieren
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 💡 WARUM separat? Docker cached diesen Layer - muss nur neu gebaut werden wenn requirements.txt ändert
# 📋 SCHRITT 5: Unseren Code ins Container kopieren
COPY app/ ./app/
# Kopiert alles aus Host-Ordner "app/" nach Container "/app/app/"
# 📁 SCHRITT 6: Verzeichnisse erstellen
RUN mkdir -p /app/input /app/output
# Diese werden später durch Volume-Mounts "überschrieben"
# ⚙️ SCHRITT 7: Umgebungsvariablen setzen
ENV PYTHONPATH=/app # Python findet unsere Module
ENV PYTHONUNBUFFERED=1 # Print-Ausgaben erscheinen sofort
# 🚀 SCHRITT 8: Was soll beim Container-Start passieren?
CMD ["python", "-m", "app.main"]
# Startet unser Hauptprogramm
```
**🤔 Was passiert beim `docker build`?**
1. Docker lädt `python:3.11-slim` herunter (falls nicht da)
2. Installiert gcc und PostgreSQL-Tools
3. Kopiert `requirements.txt` und installiert Python-Pakete
4. Kopiert unseren Code rein
5. Setzt Umgebungsvariablen
6. **Ergebnis:** Ein fertiger Container mit allem was wir brauchen!
---
## 🎼 docker-compose.yml - "Dirigent" für mehrere Container
```yaml
# 🎯 docker-compose orchestriert MEHRERE Container gleichzeitig
version: '3.8'
services:
# 🗄️ CONTAINER 1: PostgreSQL-Datenbank
postgres:
image: postgres:15 # Fertiges PostgreSQL-Image von Docker Hub
environment: # Umgebungsvariablen für PostgreSQL
POSTGRES_DB: dataprocessing # Name der Datenbank die erstellt wird
POSTGRES_USER: postgres # Benutzername
POSTGRES_PASSWORD: password # 🔐 Passwort (in Produktion geheimer!)
volumes:
- postgres_data:/var/lib/postgresql/data # 💾 Daten persistent speichern
- ./db_init:/docker-entrypoint-initdb.d # 📂 Optional: SQL-Skripts beim Start
ports:
- "5432:5432" # Port freigeben (Host:Container)
networks:
- app_network # 🌐 Internes Netzwerk für Container-Kommunikation
# 🐍 CONTAINER 2: Unsere Python-Anwendung
python_app:
build: . # 🏗️ Baue Container aus Dockerfile in diesem Verzeichnis
environment: # Diese Variablen kann unser Python-Code lesen
DB_HOST: postgres # ❗ WICHTIG: Name des DB-Containers (nicht localhost!)
DB_PORT: 5432
DB_NAME: dataprocessing
DB_USER: postgres
DB_PASSWORD: password
volumes: # 📂 Verbinde Host-Verzeichnisse mit Container
- ./input:/app/input:ro # Host ./input → Container /app/input (read-only)
- ./output:/app/output # Host ./output → Container /app/output (read-write)
depends_on: # ⏱️ Warte bis postgres-Container läuft
- postgres
networks:
- app_network # 🌐 Gleiches Netzwerk = können miteinander sprechen
restart: unless-stopped # 🔄 Automatisch neu starten bei Absturz
# 🌐 CONTAINER 3: pgAdmin (Web-Interface für PostgreSQL)
pgadmin:
image: dpage/pgadmin4:8
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin
ports:
- "8080:80" # 🌐 Zugriff via http://localhost:8080
depends_on:
- postgres
networks:
- app_network
# 💾 VOLUMES: Persistente Datenspeicherung
volumes:
postgres_data: # Docker verwaltet diesen Speicher automatisch
# 💡 Auch wenn Container gelöscht wird, bleiben Daten erhalten
# 🌐 NETWORKS: Virtuelle Netzwerke für Container-Kommunikation
networks:
app_network:
driver: bridge # Standard-Netzwerk-Typ
# 💡 Alle Container in diesem Netzwerk können sich über Namen erreichen
```
**🤔 Warum docker-compose?**
- **Ohne compose:** `docker run postgres`, dann `docker run python_app` - sehr umständlich!
- **Mit compose:** Ein Befehl (`docker-compose up`) startet ALLES automatisch
- **Networks:** Container können sich über Namen finden (`postgres` statt IP-Adresse)
- **Volumes:** Daten gehen nicht verloren beim Container-Neustart
---
## 🔧 .env - Geheime Konfiguration
```env
# 🔐 Sensible Daten sollten NICHT in docker-compose.yml stehen
# Diese Datei wird von docker-compose automatisch gelesen
# Datenbankverbindung
DB_HOST=postgres
DB_PORT=5432
DB_NAME=dataprocessing
DB_USER=postgres
DB_PASSWORD=password # ❗ In Produktion: sicheres Passwort!
# Python-Einstellungen
PYTHONPATH=/app
PYTHONUNBUFFERED=1
```
**💡 Wichtig:** Die `.env`-Datei niemals in Git committen! (→ `.gitignore`)
---
## 📊 Beispiel-Daten
### **input/sample_data.csv**
```csv
id,name,value,category
1,Item A,10,electronics
2,Item B,25,clothing
3,Item C,15,electronics
4,Item D,30,books
5,Item E,8,clothing
```
**💡 Das ist eine normale CSV-Datei auf Deinem Host-PC**
- Liegt in `./input/sample_data.csv`
- Wird in den Container als `/app/input/sample_data.csv` "gemountet"
- Unser Python-Code kann sie lesen, als wäre sie im Container
---
## 🚀 Schritt-für-Schritt Anleitung
### **1. Projekt erstellen**
```bash
# Verzeichnis erstellen
mkdir python-docker-project
cd python-docker-project
# Struktur erstellen
mkdir -p app input output
touch requirements.txt Dockerfile docker-compose.yml .env
touch app/__init__.py app/main.py app/data_processor.py app/database.py
```
### **2. Code schreiben**
- Alle Dateien wie oben gezeigt erstellen und befüllen
### **3. Container bauen und starten**
```bash
# Alle Container bauen und starten
docker-compose up --build
# 🔍 Was passiert:
# 1. Docker baut unseren Python-Container (aus Dockerfile)
# 2. Lädt PostgreSQL-Image herunter
# 3. Lädt pgAdmin-Image herunter
# 4. Erstellt Netzwerk "app_network"
# 5. Startet postgres-Container
# 6. Startet python_app-Container (wartet auf postgres)
# 7. Startet pgAdmin-Container
```
### **4. Überprüfen ob alles läuft**
```bash
# Laufende Container anzeigen
docker-compose ps
# Logs ansehen
docker-compose logs python_app
docker-compose logs postgres
# In pgAdmin einloggen: http://localhost:8080
# Email: admin@example.com, Passwort: admin
```
### **5. Neue Daten verarbeiten**
```bash
# Neue CSV-Datei ins input-Verzeichnis kopieren
cp neue_daten.csv input/
# Python-App neu starten um neue Dateien zu verarbeiten
docker-compose restart python_app
# Ergebnis ansehen
ls -la output/
```
### **6. System stoppen**
```bash
# Alle Container stoppen
docker-compose down
# Container stoppen UND Daten löschen (Vorsicht!)
docker-compose down -v
```
---
## 🔍 Docker-Befehle erklärt
### **Grundlegende Container-Befehle**
```bash
# 📋 Alle laufenden Container anzeigen
docker ps
# 📋 Alle Container anzeigen (auch gestoppte)
docker ps -a
# 🔍 Container-Logs ansehen
docker logs <container-name>
# 🔑 In laufenden Container "einsteigen"
docker exec -it <container-name> bash
# 🗑️ Container stoppen
docker stop <container-name>
# 🗑️ Container löschen
docker rm <container-name>
```
### **Image-Befehle**
```bash
# 📋 Alle Images anzeigen
docker images
# 🏗️ Image aus Dockerfile bauen
docker build -t mein-python-app .
# 🗑️ Image löschen
docker rmi <image-name>
# 🧹 Unbenutzte Images löschen
docker image prune
```
### **docker-compose-Befehle**
```bash
# 🚀 Alle Services starten
docker-compose up
# 🚀 Im Hintergrund starten
docker-compose up -d
# 🏗️ Images neu bauen und starten
docker-compose up --build
# 🔄 Einzelnen Service neu starten
docker-compose restart python_app
# 📋 Status aller Services
docker-compose ps
# 🔍 Logs aller Services
docker-compose logs
# 🔍 Logs eines bestimmten Service
docker-compose logs python_app
# 📈 Live-Logs verfolgen
docker-compose logs -f python_app
# 🔑 In Container einsteigen
docker-compose exec python_app bash
docker-compose exec postgres psql -U postgres -d dataprocessing
# ⏹️ Alle Services stoppen
docker-compose down
# 🗑️ Services stoppen und Volumes löschen
docker-compose down -v
```
---
## 🌟 Die wichtigsten Docker-Konzepte
### **1. Images vs Container**
- **Image** = "Bauplan" (wie ein Kuchenrezept)
- **Container** = "Laufende Instanz" (wie ein gebackener Kuchen)
- Ein Image kann viele Container erstellen
### **2. Volumes**
```yaml
volumes:
- ./input:/app/input # Host-Verzeichnis → Container-Verzeichnis
```
- **Warum?** Container-Dateisystem ist temporär
- **Volume** = persistenter Speicher der überlebt
### **3. Networks**
- Container in gleichem Netzwerk können sich über Namen erreichen
- `python_app` kann `postgres` kontaktieren (nicht IP-Adresse!)
### **4. Environment Variables**
```yaml
environment:
DB_HOST: postgres # Diese Variable kann Python-Code lesen
```
### **5. Ports**
```yaml
ports:
- "8080:80" # Host-Port : Container-Port
```
- Container-Port 80 wird auf Host-Port 8080 freigegeben
- Zugriff: `http://localhost:8080`
---
## ❓ Häufige Anfänger-Probleme
### **Problem 1: "Connection refused" zur Datenbank**
```
❌ FALSCH: DB_HOST=localhost
✅ RICHTIG: DB_HOST=postgres
```
- In Docker ist `localhost` der Container selbst
- Verwende den Service-Namen aus `docker-compose.yml`
### **Problem 2: "File not found"**
```
❌ FALSCH: input_dir = Path("./input")
✅ RICHTIG: input_dir = Path("/app/input")
```
- Pfade sind INSIDE dem Container, nicht auf dem Host
### **Problem 3: "Module not found"**
```
❌ FALSCH: Umgebungsvariable vergessen
✅ RICHTIG: ENV PYTHONPATH=/app in Dockerfile
```
### **Problem 4: Änderungen nicht sichtbar**
```bash
# Nach Code-Änderungen Container neu bauen:
docker-compose up --build
```
### **Problem 5: Port bereits belegt**
```
❌ Error: Port 5432 already in use
✅ Lösung: Anderen Port verwenden: "5433:5432"
```
---
## 🎯 Zusammenfassung - Was macht was?
| Datei/Komponente | Was es macht | Warum wichtig |
|------------------|--------------|---------------|
| **Dockerfile** | "Bauanleitung" für Python-Container | Definiert was IN den Container kommt |
| **docker-compose.yml** | Orchestriert mehrere Container | Ein Befehl startet alles |
| **requirements.txt** | Liste der Python-Pakete | Automatische Installation |
| **.env** | Geheime Konfiguration | Passwörter nicht in Code |
| **volumes** | Datenaustausch Host ↔ Container | Input/Output-Dateien |
| **networks** | Container-Kommunikation | python_app kann postgres erreichen |
| **ports** | Zugriff von außen | Web-Interface erreichbar |
**🚀 Mit einem Befehl hast Du:**
- ✅ Python-Umgebung mit allen Paketen
- ✅ PostgreSQL-Datenbank
- ✅ Web-Interface für DB
- ✅ Automatische File-Verarbeitung
- ✅ Persistente Datenspeicherung
**Das ist die Macht von Docker! 🐳**
+1
View File
@@ -0,0 +1 @@
https://www.librechat.ai/
+140
View File
@@ -0,0 +1,140 @@
Kurz gesagt: **Nein – GNU Stow führt keine Skripte aus.**
Und das ist auch Absicht 🙂
GNU Stow macht **nur eine Sache**:
> Es erzeugt und entfernt Symlinks.
Keine Hooks.
Keine Post-Deploy-Skripte.
Keine Automatik.
---
# 🧠 Warum ist das so?
Stow ist bewusst:
* minimalistisch
* deterministisch
* side-effect-frei
Dadurch bleibt dein Setup transparent und reproduzierbar.
---
# ✅ Aber: Man kann es kombinieren
Wenn du beim „Deploy“ zusätzlich Dinge tun willst (z. B. Monitor-Symlink setzen, Pakete installieren, Cache leeren, etc.), gibt es saubere Lösungen:
---
# 🔹 Lösung 1: Bootstrap-Script (empfohlen)
Du schreibst dir ein Script wie:
```bash
#!/bin/bash
set -e
cd ~/dotfiles
echo "→ Stowing configs"
stow hypr
stow waybar
stow zsh
echo "→ Setting monitor config"
ln -sf desktop.conf hypr/.config/hypr/monitors/current.conf
echo "→ Reloading Hyprland"
hyprctl reload
```
Dann einfach:
```bash
./install.sh
```
💡 Das ist die professionellste Lösung.
---
# 🔹 Lösung 2: Hostname-basierte Logik im Script
```bash
HOST=$(hostname)
if [[ "$HOST" == "desktop" ]]; then
ln -sf desktop.conf hypr/.config/hypr/monitors/current.conf
elif [[ "$HOST" == "laptop" ]]; then
ln -sf laptop.conf hypr/.config/hypr/monitors/current.conf
fi
```
Dann musst du nichts manuell wählen.
---
# 🔹 Lösung 3: Makefile (sehr elegant)
Beispiel:
```make
install:
stow hypr
stow waybar
./scripts/select-monitor.sh
```
Dann:
```bash
make install
```
Sehr beliebt in Dotfile-Repos.
---
# 🔹 Lösung 4: „echte“ Dotfile-Manager
Wenn du wirklich Logik + Templates willst:
* chezmoi
* yadm
Diese können:
* Hostname erkennen
* Variablen verwenden
* Templates generieren
* Skripte ausführen
Aber sie sind komplexer als Stow.
---
# 🎯 Empfehlung für dich (Hyprland + mehrere Systeme)
Da du:
* Monitor-Configs pro System brauchst
* wahrscheinlich Arch nutzt
* modular arbeiten willst
👉 **Stow + Bootstrap-Script** ist die perfekte Balance.
---
# 💬 Kurzantwort auf deine Frage
| Frage | Antwort |
| ------------------------ | ----------------- |
| Führt Stow Skripte aus? | ❌ Nein |
| Kann man es kombinieren? | ✅ Ja |
| Beste Praxis? | Stow + install.sh |
---
+15
View File
@@ -0,0 +1,15 @@
[[Linux Musikprogramme]]
[[Softlinks 1]]
[[Synchronisation & Backup 1]]
# Konsolen Know-How
[[Linux Konsole Zeichen löschen]]
[[Paketinstallation aus tar.gz]]
[[Disable KVM for VirtualBox]]
[[Linux Terminal Shortcut]]
[[Drives & Mounts 1]]
[[Computerkram/find]]
[[Link-Verknüpfung in Linux]]
+458
View File
@@ -0,0 +1,458 @@
Hier ist ein kompaktes, aber vollständiges **VIM Cheat Sheet** 📝
---
## 🔹 Modi in VIM
|Modus|Bedeutung|Wechsel|
|---|---|---|
|**Normal Mode**|Navigation & Befehle|`Esc`|
|**Insert Mode**|Texteingabe|`i`, `a`, `o`, etc.|
|**Visual Mode**|Text markieren|`v`, `V`, `Ctrl+v`|
|**Command Mode**|Speichern, Beenden, etc.|`:`|
---
## 🔹 Insert Mode Befehle
|Befehl|Wirkung|
|---|---|
|`i`|Vor Cursor einfügen|
|`a`|Nach Cursor einfügen|
|`I`|Am Zeilenanfang einfügen|
|`A`|Am Zeilenende einfügen|
|`o`|Neue Zeile unterhalb|
|`O`|Neue Zeile oberhalb|
---
## 🔹 Navigation (Normal Mode)
### Zeichenweise
```
h ← j ↓ k ↑ l →
```
### Wortweise
```
w nächstes Wort
b vorheriges Wort
e Wortende
```
### Zeilenweise
```
0 Zeilenanfang
^ Erstes Nicht-Leerzeichen
$ Zeilenende
```
### Datei
```
gg Anfang der Datei
G Ende der Datei
:n Gehe zu Zeile n
```
---
## 🔹 Löschen
|Befehl|Wirkung|
|---|---|
|`x`|Zeichen löschen|
|`dd`|Zeile löschen|
|`dw`|Wort löschen|
|`d$`|Bis Zeilenende löschen|
|`d0`|Bis Zeilenanfang löschen|
💡 Kombination: `d` + Bewegung funktioniert immer
(z.B. `d3w` = 3 Wörter löschen)
---
## 🔹 Kopieren & Einfügen
|Befehl|Wirkung|
|---|---|
|`yy`|Zeile kopieren|
|`yw`|Wort kopieren|
|`p`|Nach Cursor einfügen|
|`P`|Vor Cursor einfügen|
#### Register
Vor alle Kopieren oder Einfügen Befehle kann ein `"3` gestellt werden, um ins 3. Register zu schreiben bzw. daraus heraus zu lesen. Z.b. kopiert `"7yw` das Wort ins 7. Register und `"4p` fügt das 4. Register nach dem Curser ein.
💡 Das spezielle Register `+`/`*` ist das System-Clipboard, sehr Praktisch zum Austausch von Text mit anderen Programmen
Alle Register ansehen: `:reg`
💡 Das spezielle Register `%` enthält den aktuellen Dateipfad -> aktuelle Dateipfad in System-Clipboard: `:let @+=@%`.
---
## 🔹 Undo / Redo
```
u Undo
Ctrl+r Redo
```
---
## 🔹 Visual Mode
|Befehl|Wirkung|
|---|---|
|`v`|Zeichenweise markieren|
|`V`|Ganze Zeile markieren|
|`Ctrl+v`|Block markieren|
Nach Markierung:
```
d löschen
y kopieren
> einrücken
< ausrücken
```
---
## 🔹 Suchen & Ersetzen
```
/text Vorwärts suchen
?text Rückwärts suchen
n Nächstes Ergebnis
N Vorheriges Ergebnis
```
Ersetzen:
```
:%s/alt/neu/g Ganze Datei
:s/alt/neu/g Aktuelle Zeile
:%s/alt/neu/gc Mit Bestätigung
```
---
## 🔹 Speichern & Beenden
```
:w Speichern
:q Beenden
:wq Speichern & Beenden
:x Speichern & Beenden
:q! Ohne Speichern beenden
```
---
## 🔹 Fenster & Tabs
```
:split Horizontal teilen
:vsplit Vertikal teilen
Ctrl+w w Zwischen Fenstern wechseln
:tabnew Neuer Tab
gt Nächster Tab
gT Vorheriger Tab
```
---
## 🔹 Nützliche Shortcuts
```
. Letzte Aktion wiederholen
>> Zeile einrücken
<< Zeile ausrücken
ciw Wort ändern
cc Zeile ändern
J Zeilen zusammenführen
```
---
## 🔹 Makros
```
qa Aufnahme in Register a starten
q Aufnahme stoppen
@a Makro a ausführen
@@ Letztes Makro wiederholen
```
---
## 🔹 Zahlen-Präfixe (Sehr wichtig!)
Viele Befehle lassen sich multiplizieren:
```
3dd 3 Zeilen löschen
5w 5 Wörter vor
2yy 2 Zeilen kopieren
```
---
# Zeilennummern aus- und anschalten
---
## 🔹 Absolute Zeilennummern
### Einschalten:
```vim
:set number
```
### Ausschalten:
```vim
:set nonumber
```
### Toggle:
```vim
:set number!
```
---
## 🔹 Relative Zeilennummern
### Einschalten:
```vim
:set relativenumber
```
### Ausschalten:
```vim
:set norelativenumber
```
### Toggle:
```vim
:set relativenumber!
```
---
## 🔹 Absolute + Relative kombinieren (Sehr beliebt 🔥)
Viele nutzen diese Kombination:
```vim
:set number relativenumber
```
👉 Ergebnis:
* Aktuelle Zeile = **absolute Nummer**
* Alle anderen Zeilen = **relative Nummern**
Beispiel:
```
8
2
1
10 ← aktuelle Zeile
1
2
3
```
Das ist perfekt für Bewegungen wie:
```
5j
3k
```
---
## 🔹 Dauerhaft aktivieren (.vimrc)
In deiner `~/.vimrc`:
```vim
set number
set relativenumber
```
---
## 🔹 Smart Toggle Mapping (Optional ⭐)
Viele nutzen ein Keybinding:
```vim
nnoremap <leader>n :set number! relativenumber!<CR>
```
Dann kannst du mit:
```
\ n
```
(beim Standard-`leader`) beide gleichzeitig toggeln.
---
# Block Aus- und Einkommentieren
---
# 🔹 1️⃣ Rein mit Vim (ohne Plugin)
## ✅ Ganze Zeilen im Visual Mode kommentieren
### Schritt 1: Block markieren
* `V` → Zeilenweise markieren
* `j / k` → Bereich wählen
### Schritt 2: Kommentarzeichen einfügen
Beispiel für `#`:
```vim
:s/^/# /
```
Im Visual Mode einfach:
```vim
:'<,'>s/^/# /
```
👉 Fügt `# ` am Anfang jeder markierten Zeile ein.
---
## 🔹 Auskommentieren
```vim
:'<,'>s/^# //
```
---
## 🔹 Noch schneller (ohne `:` tippen)
Markieren mit `V`, dann:
```vim
:s/^/# /
```
Vim setzt `'<,'>` automatisch.
---
# 🔹 2️⃣ Noch effizienter: Visual Block Mode (Sehr elegant ⚡)
Perfekt für feste Kommentarzeichen wie `#`, `//`, `--`.
### Schritt 1
```
Ctrl + v
```
### Schritt 2
Mit `j/k` mehrere Zeilen markieren (nur Spalte 0)
### Schritt 3
```
Shift + i
#
Esc
```
💥 Vim fügt das in alle markierten Zeilen ein.
---
## 🔹 Entfernen mit Block Mode
1. `Ctrl + v`
2. Erste 2 Zeichen (`# `) markieren
3. `d`
---
# 🔹 3️⃣ Beste Lösung: Plugin (Empfohlen 🔥)
Wenn du regelmäßig kommentierst → nimm ein Plugin.
Sehr beliebt:
* vim-commentary von Tim Pope
### Installation (mit vim-plug):
```vim
Plug 'tpope/vim-commentary'
```
### Nutzung:
* `gcc` → aktuelle Zeile toggeln
* `gc` (im Visual Mode) → Block toggeln
💎 Vorteil:
* erkennt automatisch Kommentarzeichen je nach Dateityp
* funktioniert mit `//`, `#`, `--`, `/* */`, etc.
---
# 🔹 4️⃣ Absolute Power-User Lösung (Ohne Plugin, aber smart)
In `.vimrc`:
```vim
vnoremap <leader>c :s/^/# /<CR>
vnoremap <leader>u :s/^# //<CR>
```
Dann:
```
\c → kommentieren
\u → auskommentieren
```
---
# 🔥 Meine Empfehlung
| Wenn du... | Lösung |
| ----------------------------- | ----------------- |
| Nur selten kommentierst | Visual Block Mode |
| Viel programmierst | vim-commentary |
| Minimalistisch bleiben willst | eigenes Mapping |
---
# Verschiedenes
- `%`: zur nächsten Klammer
- `TOhtml`: HTML Export
- `:ls`: Buffer anzeigen -> `:b 3` den 3. Buffer öffnen
- `.` : letzte Aktion wiederholen
- `:e path/to/file` öffnet Datei, nur `:e` aktualisiert die geöffnete Datei, `:e!` verwirft dabei alle Änderungen
+207
View File
@@ -0,0 +1,207 @@
**Open WebUI is an [extensible](https://docs.openwebui.com/features/plugin/), feature-rich, and user-friendly self-hosted AI platform designed to operate entirely offline.** It supports various LLM runners like **Ollama** and **OpenAI-compatible APIs**, with **built-in inference engine** for RAG, making it a **powerful AI deployment solution**.
Passionate about open-source AI? [Join our team →](https://careers.openwebui.com/)
![GitHub stars](https://img.shields.io/github/stars/open-webui/open-webui?style=social) ![GitHub forks](https://img.shields.io/github/forks/open-webui/open-webui?style=social) ![GitHub watchers](https://img.shields.io/github/watchers/open-webui/open-webui?style=social) ![GitHub repo size](https://img.shields.io/github/repo-size/open-webui/open-webui) ![GitHub language count](https://img.shields.io/github/languages/count/open-webui/open-webui) ![GitHub top language](https://img.shields.io/github/languages/top/open-webui/open-webui) ![GitHub last commit](https://img.shields.io/github/last-commit/open-webui/open-webui?color=red) [![Discord](https://img.shields.io/badge/Discord-Open_WebUI-blue?logo=discord&logoColor=white)](https://discord.gg/5rJgQTnV4s) [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/tjbck)
![Open WebUI Demo](https://docs.openwebui.com/assets/images/demo-d3952c8561c4808c1d447fc061c71174.gif)
tip
**Looking for an [Enterprise Plan](https://docs.openwebui.com/enterprise)?** — **[Speak with Our Sales Team Today!](mailto:sales@openwebui.com)**
Get **enhanced capabilities**, including **custom theming and branding**, **Service Level Agreement (SLA) support**, **Long-Term Support (LTS) versions**, and **more!**
## Quick Start with [[Docker]] 🐳
info
**WebSocket** support is required for Open WebUI to function correctly. Ensure that your network configuration allows WebSocket connections.
**If Ollama is on your computer**, use this command:
```
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
```
**To run Open WebUI with Nvidia GPU support**, use this command:
```
docker run -d -p 3000:8080 --gpus all --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:cuda
```
For environments with limited storage or bandwidth, Open WebUI offers slim image variants that exclude pre-bundled models. These images are significantly smaller but download required models on first use:
```
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main-slim
```
### Open WebUI Bundled with Ollama
This installation method uses a single container image that bundles Open WebUI with Ollama, allowing for a streamlined setup via a single command. Choose the appropriate command based on your hardware setup:
- **With GPU Support**: Utilize GPU resources by running the following command:
```
docker run -d -p 3000:8080 --gpus=all -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama
```
- **For CPU Only**: If you're not using a GPU, use this command instead:
```
docker run -d -p 3000:8080 -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama
```
Both commands facilitate a built-in, hassle-free installation of both Open WebUI and Ollama, ensuring that you can get everything up and running swiftly.
After installation, you can access Open WebUI at [http://localhost:3000](http://localhost:3000). Enjoy! 😄
### Using the Dev Branch 🌙
warning
The `:dev` branch contains the latest unstable features and changes. Use it at your own risk as it may have bugs or incomplete features.
If you want to try out the latest bleeding-edge features and are okay with occasional instability, you can use the `:dev` tag like this:
```
docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:dev
```
For the slim variant of the dev branch:
```
docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:dev-slim
```
### Updating Open WebUI
To update Open WebUI container easily, follow these steps:
#### Manual Update
Use [Watchtower](https://containrrr.dev/watchtower) to update your Docker container manually:
```
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --run-once open-webui
```
#### Automatic Updates
Keep your container updated automatically every 5 minutes:
```
docker run -d --name watchtower --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --interval 300 open-webui
```
🔧 **Note**: Replace `open-webui` with your container name if it's different.
## Manual Installation
info
### Platform Compatibility
Open WebUI works on macOS, [[Linux]] (x86_64 and ARM64, including Raspberry Pi and other ARM boards), and Windows.
There are two main ways to install and run Open WebUI: using the `uv` runtime manager or Python's `pip`. While both methods are effective, **we strongly recommend using `uv`** as it simplifies environment management and minimizes potential conflicts.
### Installation with `uv` (Recommended)
The `uv` runtime manager ensures seamless Python environment management for applications like Open WebUI. Follow these steps to get started:
#### 1. Install `uv`
Pick the appropriate installation command for your operating system:
- **macOS/Linux**:
```
curl -LsSf https://astral.sh/uv/install.sh | sh
```
- **Windows**:
```
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
#### 2. Run Open WebUI
Once `uv` is installed, running Open WebUI is a breeze. Use the command below, ensuring to set the `DATA_DIR` environment variable to avoid data loss. Example paths are provided for each platform:
- **macOS/Linux**:
```
DATA_DIR=~/.open-webui uvx --python 3.11 open-webui@latest serve
```
- **Windows**:
```
$env:DATA_DIR="C:\open-webui\data"; uvx --python 3.11 open-webui@latest serve
```
note
**For PostgreSQL Support:**
The default installation now uses a slimmed-down package. If you need **PostgreSQL support**, install with all optional dependencies:
```
pip install open-webui[all]
```
### Installation with `pip`
For users installing Open WebUI with [[Python]]'s package manager `pip`, **it is strongly recommended to use Python runtime managers like `uv` or `conda`**. These tools help manage Python environments effectively and avoid conflicts.
Python 3.11 is the development environment. Python 3.12 seems to work but has not been thoroughly tested. Python 3.13 is entirely untested and some dependencies do not work with Python 3.13 yet—**use at your own risk**.
1. **Install Open WebUI**:
Open your terminal and run the following command:
```
pip install open-webui
```
- **Start Open WebUI**:
Once installed, start the server using:
```
open-webui serve
```
### Updating Open WebUI
To update to the latest version, simply run:
```
pip install --upgrade open-webui
```
This method installs all necessary dependencies and starts Open WebUI, allowing for a simple and efficient setup. After installation, you can access Open WebUI at [http://localhost:8080](http://localhost:8080). Enjoy! 😄
## Other Installation Methods
We offer various installation alternatives, including non-Docker native installation methods, Docker Compose, Kustomize, and Helm. Visit our [Open WebUI Documentation](https://docs.openwebui.com/getting-started/) or join our [Discord community](https://discord.gg/5rJgQTnV4s) for comprehensive guidance.
Continue with the full [getting started guide](https://docs.openwebui.com/getting-started).
### Desktop App
We also have an **experimental** desktop app, which is actively a **work in progress (WIP)**. While it offers a convenient way to run Open WebUI natively on your system without Docker or manual setup, it is **not yet stable**.
👉 For stability and production use, we strongly recommend installing via **Docker** or **Python (`uv` or `pip`)**.
+1 -1
View File
@@ -1,4 +1,4 @@
```md
---
title: "Rust Tutorial (für Python-Erfahrene)"
tags: [rust, tutorial, programming]
+214
View File
@@ -0,0 +1,214 @@
## Modi
```text
i In den Insert-Modus (vor Cursor)
I Insert am Zeilenanfang
a Insert nach Cursor
A Insert am Zeilenende
o Neue Zeile unterhalb + Insert
O Neue Zeile oberhalb + Insert
<Esc> Zurück in Normalmodus
v Visueller Modus (Zeichenweise)
V Visueller Modus (Zeilenweise)
<C-v> Visueller Blockmodus
```
## Navigation (Normalmodus)
```text
h j k l Links / runter / hoch / rechts
0 Zeilenanfang
^ Erstes nicht-leer Zeichen
$ Zeilenende
w Zum nächsten Wortanfang
b Zum vorherigen Wortanfang
e Zum Wortende
W B E Wie oben, aber Worte durch Leerzeichen getrennt
gg Erste Zeile
G Letzte Zeile
ngg / nG Zu Zeile n
H Oberer Bildschirmrand
M Mittlerer Bildschirmrand
L Unterer Bildschirmrand
Ctrl-u Halbe Seite hoch
Ctrl-d Halbe Seite runter
Ctrl-b Seite hoch
Ctrl-f Seite runter
```
## Basis-Bearbeitung
```text
x Zeichen unter Cursor löschen
X Zeichen links vom Cursor löschen
r<char> Zeichen ersetzen
dd Zeile löschen (cut)
D Bis zum Zeilenende löschen
cc Zeile ändern (delete + insert)
C Bis zum Zeilenende ändern
yy Zeile kopieren
Y Alias für yy
p Einfügen NACH Cursor/Zeile
P Einfügen VOR Cursor/Zeile
u Undo
Ctrl-r Redo
J Nächste Zeile an aktuelle anhängen
>> Zeile einrücken (indent)
<< Zeile ausrücken (unindent)
```
## Mit Counts & Bewegungen
Viele Befehle funktionieren mit einer Anzahl (count) und einer Bewegung:
```text
3w 3 Wörter vor
5j 5 Zeilen runter
d3w 3 Wörter löschen
c$ Bis Zeilenende ändern
y0 Bis Zeilenanfang kopieren
```
## Textobjekte (im Normal- / Visuellen Modus)
```text
aw A word (inkl. Leerzeichen)
iw Inner word
as A sentence
is Inner sentence
ap A paragraph
ip Inner paragraph
a" / i" Text in Anführungszeichen
a' / i' Text in einfachen Quotes
a) / i) Text in Klammern (usw. für {}, [], <>)
Beispiele:
ci" Inhalt von "..." ändern
da( Klammerausdruck inklusive Klammern löschen
viw Wort unter Cursor markieren
```
## Suchen & Ersetzen
```text
/word Vorwärts nach „word“ suchen
?word Rückwärts suchen
n Nächster Treffer
N Vorheriger Treffer
* Wort unter Cursor vorwärts suchen
# Wort unter Cursor rückwärts suchen
:%s/alt/neu/g In gesamter Datei ersetzen
:%s/alt/neu/gc Mit Bestätigung
:.,$s/alt/neu/g Von aktueller Zeile bis Ende
:10,20s/alt/neu/g In Zeilen 10–20
```
## Dateien, Buffers, Splits & Tabs
```text
:e datei Datei öffnen
:w Speichern
:w name Unter anderem Namen speichern
:q Beenden
:q! Beenden ohne Speichern
:wq / :x Speichern und beenden
:qa Alle Fenster schließen
:qa! Alle schließen ohne Speichern
" Buffer (Dateien im Speicher)
:ls Buffer-Liste
:buffer n Buffer n öffnen
:bnext / :bn Nächster Buffer
:bprev / :bp Vorheriger Buffer
:bdelete Buffer schließen
" Splits
:split datei Horizontaler Split
:vsplit datei Vertikaler Split
Ctrl-w s Split horizontal
Ctrl-w v Split vertikal
Ctrl-w w Zum nächsten Split
Ctrl-w h/j/k/l Split wechseln
Ctrl-w q Split schließen
" Tabs
:tabnew Neuer Tab
:tabclose Tab schließen
:tabnext / :tn Nächster Tab
:tabprev / :tp Vorheriger Tab
```
## Visual Mode Aktionen
```text
v / V / Ctrl-v Auswahl starten
y Auswahl kopieren
d Auswahl löschen
c Auswahl ändern
> Einrücken
< Ausrücken
= Auto-Indent (z.B. für Code)
: Befehl auf Auswahl anwenden
(Bereich wird automatisch eingetragen)
```
## Makros & Wiederholung
```text
. Letzte Änderung wiederholen
q<a> Macro in Register a aufzeichnen
(z.B. qa)
... Aktionen ausführen
q Aufzeichnung beenden
@a Macro a ausführen
3@a Macro 3x ausführen
@@ Letztes Macro wiederholen
```
## Register
```text
"0 Zuletzt kopiertes (y) ohne delete
"1–"9 Verlaufsregister
"" Default-Register
"+ System-Clipboard (kopieren/einfügen mit OS)
"* Auswahl-Clipboard (unter Linux/X11)
Beispiele:
"ayw Wort in Register a kopieren
"ap Inhalt von Register a einfügen
"+y In System-Clipboard kopieren
"+p Aus System-Clipboard einfügen
```
## Kommandomodus (Ex-Befehle)
```text
:!cmd Externen Befehl ausführen
:r !cmd Ausgabe von cmd einfügen
:r datei Datei unter Cursor-Zeile einfügen
:set nu Zeilennummern an
:set nonu Zeilennummern aus
:set relativenumber Relative Nummern
:set tabstop=4 shiftwidth=4 expandtab
```
## Einfache .vimrc-Beispiele
```vim
" Zeilennummern
set number
set relativenumber
" Einrückung
set tabstop=4
set shiftwidth=4
set expandtab
set smartindent
" Suche
set ignorecase
set smartcase
set hlsearch
set incsearch
" Maus
set mouse=a
```
+84
View File
@@ -0,0 +1,84 @@
[[Navidrome]]
## 🧩 **Option 1: Über die Web-Oberfläche**
Wenn du nur die Bibliothek neu scannen willst:
1. Melde dich als **Admin** in der Weboberfläche an.
2. Gehe zu **Settings → Admin → Rescan Library** (oder „Bibliothek neu scannen“).
3. Wähle **„Full Rescan“** (Vollständiger Scan) aus.
Das ist der einfachste Weg — aber wenn du den Vorgang **per Shell oder Skript** auslösen willst, siehe Option 2 oder 3.
---
## 🐳 **Option 2: Über die Docker Shell**
Wenn du direkten Zugriff auf den Container hast:
```bash
docker exec -it <container_name> navidrome rescan --force
```
🔹 `<container_name>` ersetzt du durch den tatsächlichen Namen deines Containers, z. B. `navidrome`.
🔹 Der Parameter `--force` erzwingt eine vollständige Neuindizierung (nicht nur eine inkrementelle).
Beispiel:
```bash
docker exec -it navidrome navidrome rescan --force
```
Falls `navidrome` nicht im `PATH` ist (z. B. je nach Image):
```bash
docker exec -it navidrome /app/navidrome rescan --force
```
---
## ⚙️ **Option 3: Durch Neustart mit Umgebungsvariable**
Wenn du den Container neu startest und gleich beim Start eine Neuindizierung erzwingen willst, kannst du temporär folgende Umgebungsvariable setzen:
```bash
docker run -d \
-e ND_SCAN_ON_STARTUP=true \
-e ND_SCAN_FORCED=true \
...
--name navidrome \
deluan/navidrome:latest
```
Oder, wenn du `docker-compose` nutzt:
```yaml
environment:
- ND_SCAN_ON_STARTUP=true
- ND_SCAN_FORCED=true
```
Dann einmal:
```bash
docker compose restart navidrome
```
Das löst bei jedem Start eine **vollständige Neuindizierung** aus.
---
## 🧠 **Zusatzinfos**
- `navidrome rescan` akzeptiert auch `--quiet` (ohne Logausgabe).
- Der Fortschritt erscheint in den Logs:
```bash
docker logs -f navidrome
```
- Die Indizierung kann bei großen Bibliotheken einige Zeit dauern.
+17
View File
@@ -0,0 +1,17 @@
```bash
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/nvme0n1p2 during installation
UUID=4d4554dc-e3fc-499c-991c-074655585d11 / ext4 errors=remount-ro 0 1
# /boot/efi was on /dev/nvme0n1p1 during installation
UUID=FCBD-00BE /boot/efi vfat umask=0077 0 1
/swapfile none swap sw 0 0
UUID=04F6962EF6961FCA /media/mathias/Anbau2 ntfs-3g defaults,umask=000,uid=1000,gid=1000 0 0
UUID=A8F0EC77F0EC4D5E /media/mathias/Bilder ntfs-3g defaults,umask=000,uid=1000,gid=1000 0 0
UUID=a642b8a8-2cdd-4635-a094-e408073a236d /media/mathieu/vault ext4 defaults 0 2
```
+1247
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
Pydantic ist ein zentrales Werkzeug im heutigen Python-Ökosystem, vor allem im Umfeld von APIs (z.B. [[FastAPI]]), Konfiguration und Datenvalidierung.
hPydantic ist ein zentrales Werkzeug im heutigen Python-Ökosystem, vor allem im Umfeld von APIs (z.B. [[FastAPI]]), Konfiguration und Datenvalidierung.
Im Folgenden bekommst du eine systematische Einführung mit praxisnahen Beispielen.
**Hinweis:** Die Beispiele orientieren sich an **Pydantic v2** (aktuelle Hauptversion). In v1 ist die Syntax ähnlich, aber es gibt einige Unterschiede (z.B. `@validator` vs. `@field_validator`).