From e229cbc6cc66103c0ad309d67e0b2232d56d836d Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Fri, 24 Apr 2026 22:53:12 +0300 Subject: [PATCH] Support Ubuntu image preview backend --- PKGBUILD | 2 +- README.md | 18 ++++----- flake.nix | 2 +- internal/ui/image_overlay.go | 78 +++++++++++++++++++++++++++--------- scripts/build-deb.sh | 2 +- 5 files changed, 70 insertions(+), 32 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 0d62887..3fe8eab 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=vcom -pkgver=0.1.5 +pkgver=0.1.7 pkgrel=1 pkgdesc="Terminal file manager inspired by Midnight Commander" arch=("x86_64" "aarch64") diff --git a/README.md b/README.md index 8b1fddd..48324f5 100644 --- a/README.md +++ b/README.md @@ -64,26 +64,26 @@ go build -o vcom ./cmd/vcom Run directly from the flake: ```bash -nix run github:vrubelroman/vcom?ref=v0.1.5 +nix run github:vrubelroman/vcom?ref=v0.1.7 ``` Install into user profile: ```bash -nix profile add github:vrubelroman/vcom?ref=v0.1.5 +nix profile add github:vrubelroman/vcom?ref=v0.1.7 ``` The Nix package wraps `vcom` with `ueberzugpp` in `PATH`, so image preview works in non-`kitty` terminals out of the box. ### Debian / Ubuntu -Download the release `.deb` for `v0.1.5`, then install: +Download the release `.deb` for `v0.1.7`, then install: ```bash -sudo apt install ./vcom_0.1.5_amd64.deb +sudo apt install ./vcom_0.1.7_amd64.deb ``` -The Debian package declares `ueberzugpp` as a dependency for image preview outside `kitty`. +The Debian package declares `ueberzug` (or `ueberzugpp` where available) as a dependency for image preview outside `kitty`. Install a Nerd Font (example): @@ -136,7 +136,7 @@ Built-in themes: ## Releases -Pushing a tag like `v0.1.5` triggers GitHub Actions release workflow (`.github/workflows/release.yml`) which: +Pushing a tag like `v0.1.7` triggers GitHub Actions release workflow (`.github/workflows/release.yml`) which: - runs tests - vendors Go modules @@ -146,9 +146,9 @@ Pushing a tag like `v0.1.5` triggers GitHub Actions release workflow (`.github/w Release artifacts: -- `vcom-v0.1.5-x86_64-unknown-linux-gnu.tar.gz` -- `vcom_0.1.5_amd64.deb` -- `vcom-v0.1.5-checksums.txt` +- `vcom-v0.1.7-x86_64-unknown-linux-gnu.tar.gz` +- `vcom_0.1.7_amd64.deb` +- `vcom-v0.1.7-checksums.txt` ## Notes diff --git a/flake.nix b/flake.nix index ffc238a..6f88575 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,7 @@ lib = pkgs.lib; packageBase = pkgs.buildGoModule { pname = "vcom"; - version = "0.1.5"; + version = "0.1.7"; src = ./.; vendorHash = null; diff --git a/internal/ui/image_overlay.go b/internal/ui/image_overlay.go index 5b271b4..54bcc01 100644 --- a/internal/ui/image_overlay.go +++ b/internal/ui/image_overlay.go @@ -127,36 +127,68 @@ func (m *imageOverlayManager) startBackend(backend string) error { return nil } +func (m *imageOverlayManager) startLegacyBackend() error { + cmd := exec.Command("ueberzug", "layer", "--parser", "json") + stdin, err := cmd.StdinPipe() + if err != nil { + return err + } + cmd.Stdout = io.Discard + cmd.Stderr = io.Discard + if err := cmd.Start(); err != nil { + _ = stdin.Close() + return err + } + m.cmd = cmd + m.stdin = stdin + m.running = true + m.backend = "ueberzug" + return nil +} + func (m *imageOverlayManager) ensureStarted() error { if m.running { return nil } - if _, err := exec.LookPath("ueberzugpp"); err != nil { - return err + + if _, err := exec.LookPath("ueberzugpp"); err == nil { + var lastErr error + for _, backend := range m.backendList() { + if err := m.startBackend(backend); err != nil { + lastErr = err + continue + } + // Probe command channel right away; some backends terminate instantly. + if err := m.send(map[string]any{ + "action": "remove", + "identifier": m.identifier, + }); err != nil { + lastErr = err + m.stop() + continue + } + return nil + } + if lastErr != nil { + return lastErr + } } - var lastErr error - for _, backend := range m.backendList() { - if err := m.startBackend(backend); err != nil { - lastErr = err - continue + if _, err := exec.LookPath("ueberzug"); err == nil { + if err := m.startLegacyBackend(); err != nil { + return err } - // Probe command channel right away; some backends terminate instantly. if err := m.send(map[string]any{ "action": "remove", "identifier": m.identifier, }); err != nil { - lastErr = err m.stop() - continue + return err } return nil } - if lastErr != nil { - return lastErr - } - return fmt.Errorf("could not start ueberzugpp overlay") + return fmt.Errorf("could not start image overlay backend") } func (m *imageOverlayManager) send(payload map[string]any) error { @@ -202,12 +234,16 @@ func (m *imageOverlayManager) show(path string, rect overlayRect) error { "path": path, "x": rect.x, "y": rect.y, - "max_width": rect.width, - "max_height": rect.height, - "scaler": "fit_contain", + } + if m.backend == "ueberzug" { + payload["width"] = rect.width + payload["height"] = rect.height + } else { + payload["max_width"] = rect.width + payload["max_height"] = rect.height + payload["scaler"] = "fit_contain" } if err := m.send(payload); err == nil { - m.backend = "ueberzugpp" m.visible = true m.lastPath = path m.lastRect = rect @@ -215,8 +251,10 @@ func (m *imageOverlayManager) show(path string, rect overlayRect) error { } m.stop() - if len(m.backends) > 0 { + if m.backend != "ueberzug" && len(m.backends) > 0 { m.backends = append(m.backends[1:], m.backends[0]) + } else { + break } } return fmt.Errorf("could not render image overlay") @@ -229,7 +267,7 @@ func (m *imageOverlayManager) hide() { switch m.backend { case "kitty": m.clearKitty() - case "ueberzugpp": + case "ueberzugpp", "ueberzug": if m.running { _ = m.send(map[string]any{ "action": "remove", diff --git a/scripts/build-deb.sh b/scripts/build-deb.sh index 9b9cab9..a3e3ddd 100755 --- a/scripts/build-deb.sh +++ b/scripts/build-deb.sh @@ -29,7 +29,7 @@ Section: utils Priority: optional Architecture: amd64 Maintainer: Roman Vrubel -Depends: ueberzugpp +Depends: ueberzug | ueberzugpp Description: Terminal file manager inspired by Midnight Commander A two-pane terminal file manager with inspect mode and text previews. EOF