# TUI-FM En terminalbaserad filhanterare skriven i Rust med fullt musstöd, ikonvisning och intuitiv navigation. ``` ┌─────────────────────────────────────────────────────────────────────┐ │ TUI-FM v0.1.0 │ ├──────────────────┬──────────────────────────────────────────────────┤ │ FAVORITER │ /home/user/Documents │ │ ────────── │ ────────────────────────────────────────────── │ │ 🏠 Hem │ 📁 projekt/ │ │ 📁 Dokument ◄ │ 📁 bilder/ │ │ 📁 Nedladdnin │ 📄 rapport.pdf 120 KB │ │ 📁 Skrivbord │ 📄 anteckningar.txt 4 KB │ │ ────────── │ 🖼 foto.png 2.3 MB │ │ ROOT │ 📦 arkiv.zip 540 KB │ │ ────────── │ 🦀 main.rs 8 KB │ │ / │ │ │ /home │ │ │ /etc │ │ │ /usr │ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ Högerklicksmeny │ │ │ [+ Favorit] │ │ ────────────────────────────── │ │ │ │ │ 📋 Kopiera │ │ │ │ │ ✂️ Klipp ut │ │ │ │ │ 📌 Klistra in │ │ │ │ │ ✏️ Byt namn │ │ │ │ │ ℹ️ Egenskaper │ │ │ │ │ ➕ Ny ▶ ┌──────────────────┐ │ │ │ │ └────────── │ 📄 Ny fil │ │ │ │ │ │ 📁 Ny mapp │ │ │ │ │ └──────────────────┘ │ │ ├──────────────────┴──────────────────────────────────────────────────┤ │ Sökväg: /home/user/Documents/_________ [Enter för att navigera] │ └─────────────────────────────────────────────────────────────────────┘ ``` ## Funktioner ### Huvudvy (mitten) - Visar filer och mappar med ikoner baserat på filtyp - **Dubbelklick** på mapp → navigerar in i mappen - **Enkelklick** → markerar fil/mapp - **Ctrl+klick** → flermarkering - Filstorlek visas till höger ### Sidopanel (vänster) - **Favoriter** – sparade sökvägar, klicka för att navigera direkt - **Root-mappar** – snabbnavigering till `/`, `/home`, `/etc`, `/usr` etc. - Knapp `[+ Favorit]` lägger till nuvarande mapp i favoriter - Högerklick på favorit för att ta bort den ### Nedre statusfält - Visar nuvarande sökväg - Textruta för manuell sökväginmatning - **Enter** navigerar till inskriven/inklistrad sökväg - Stöd för kopiera/klistra in i textfältet ### Högerklicksmeny (kontextmeny) Högerklick på fil(er)/mapp(ar) öppnar meny med: - **Kopiera** – kopierar markerade filer - **Klipp ut** – klipper ut markerade filer - **Klistra in** – klistrar in i markerad mapp (kräver att en mapp är markerad) - **Byt namn** – byter namn på fil/mapp - **Egenskaper** – visar storlek, rättigheter, ägare - Om flera är markerade visas gemensam storlek (beräknas rekursivt) och antal filer - **Ny ▶** (submeny) - Skapa ny fil - Skapa ny mapp ### Musstöd - Klick, dubbelklick, högerklick - Scrollning i filvisaren och sidopanelen - Markering av text i sökvägsrutan för kopiera/klistra in ### Ikontyper | Typ | Ikon | |------------|------| | Mapp | 📁 | | Textfil | 📄 | | Bild | 🖼 | | Video | 🎬 | | Ljud | 🎵 | | Arkiv/zip | 📦 | | Rust-fil | 🦀 | | Körbar | ⚙️ | | Okänd | 📎 | ## Bygga appen ### Krav - [Rust toolchain](https://rustup.rs/) (stable) - För cross-kompilering till Windows: `mingw-w64` eller [cross](https://github.com/cross-rs/cross) ### Bygga för Linux ```bash cargo build --release # Binären hamnar i: build/linux/tui-fm ``` Eller via VS Code task: **Build - Linux** ### Bygga för Windows ```bash # Lägg till Windows-target först: rustup target add x86_64-pc-windows-gnu # Installera mingw (Ubuntu/Debian): sudo apt install gcc-mingw-w64-x86-64 cargo build --release --target x86_64-pc-windows-gnu # Binären hamnar i: build/windows/tui-fm.exe ``` Eller via VS Code task: **Build - Windows** ### Output-mappar ``` build/ ├── linux/ │ └── tui-fm └── windows/ └── tui-fm.exe ``` ## Tangentbordsgenvägar | Tangent | Funktion | |---------------|-----------------------------------| | `q` / `Esc` | Avsluta | | `Enter` | Öppna mapp / navigera till sökväg | | `Backspace` | Gå upp en nivå | | `F2` | Byt namn | | `Delete` | Ta bort markerade | | `Ctrl+C` | Kopiera | | `Ctrl+X` | Klipp ut | | `Ctrl+V` | Klistra in | | `Ctrl+A` | Markera alla | | `Tab` | Växla fokus (panel ↔ filvy) | ## Beroenden (Rust crates) | Crate | Version | Används för | |-------|---------|------------| | [`ratatui`](https://github.com/ratatui-org/ratatui) | 0.29 | TUI-ramverk för all rendering. Används med: `Table`+`TableState` (filvisaren med kolumner och stateful scroll), `Scrollbar`+`ScrollbarState` (scrollindikator i filvy och sidebar), `List`+`ListItem` (sidopanelen), `Block`+`Borders` (alla ramar), `Paragraph` (textelement och dialoger), `Layout`+`Constraint` (layoutberäkning), `Clear` (overlay för menyer/dialoger), `Line`/`Span`/`Style` (styling och färger) | | [`crossterm`](https://github.com/crossterm-rs/crossterm) | 0.28 | Cross-platform terminalhantering (Windows + Linux/macOS). Hanterar: raw mode, alternate screen, mushändelser (`MouseEvent`, `MouseButton`, `MouseEventKind::Moved/Down/ScrollUp/ScrollDown`), tangentbordshändelser, terminalstorlek | | [`serde`](https://serde.rs/) | 1 | Serialiserings-/deserialiseringsramverk med `#[derive(Serialize, Deserialize)]`. Används på `Config`-structen för att spara/läsa favoriter | | [`serde_json`](https://docs.rs/serde_json) | 1 | JSON-backend till serde. Skriver konfigurationsfilen `~/.config/tui-fm/config.json` med `to_string_pretty` och läser den med `from_str` | | [`dirs`](https://docs.rs/dirs) | 5 | Plattformsoberoende sökvägar till systemkataloger. Används för `dirs::home_dir()` (startkatalog) och `dirs::config_dir()` (var konfigurationsfilen sparas: `~/.config/` på Linux, `%APPDATA%` på Windows) | | [`fs_extra`](https://docs.rs/fs_extra) | 1 | Utökade filoperationer som saknas i standardbiblioteket. Används för `dir::copy` och `dir::move_dir` – kopierar/flyttar kataloger rekursivt med alla underkataloger och filer | | [`unicode-width`](https://docs.rs/unicode-width) | 0.2 | Beräknar visuell bredd av Unicode-tecken (t.ex. CJK-tecken är 2 kolumner breda). Används för korrekt texttrunkering i filnamn och sökvägar | ### Varför ratatui? ratatui är det ledande Rust-biblioteket för terminalgränssnitt och valdes av dessa anledningar: - **Stöder Windows + Linux** via crossterm-backenden – ett krav för detta projekt - **`Table`-widget** ger kolumnjusterad visning utan manuell strängpadding; hanterar dynamiska terminalbredder automatiskt via `Constraint::Min` / `Constraint::Length` - **`StatefulWidget`-mönstret** (`TableState`, `ScrollbarState`, `ListState`) separerar renderingstillstånd från applikationstillstånd – man lagrar bara `scroll_offset` i `App` och skapar en `TableState` per frame - **`Scrollbar`-widget** renderar en komplett scrollindikator (spår, tumme, pilar) utan att man behöver beräkna positioner manuellt - **`Clear`-widget** möjliggör popup-menyer och dialoger ovanpå befintligt innehåll - **Immediate-mode rendering** – hela UI ritas om varje frame (~50 ms), vilket gör stathantering enkel: det finns ingen knapp-"tillståndsmaskin" att hålla synkroniserad