Support Ubuntu image preview backend

This commit is contained in:
vrubelroman 2026-04-24 22:53:12 +03:00
parent ded9b9fdfb
commit e229cbc6cc
5 changed files with 70 additions and 32 deletions

View file

@ -1,5 +1,5 @@
pkgname=vcom pkgname=vcom
pkgver=0.1.5 pkgver=0.1.7
pkgrel=1 pkgrel=1
pkgdesc="Terminal file manager inspired by Midnight Commander" pkgdesc="Terminal file manager inspired by Midnight Commander"
arch=("x86_64" "aarch64") arch=("x86_64" "aarch64")

View file

@ -64,26 +64,26 @@ go build -o vcom ./cmd/vcom
Run directly from the flake: Run directly from the flake:
```bash ```bash
nix run github:vrubelroman/vcom?ref=v0.1.5 nix run github:vrubelroman/vcom?ref=v0.1.7
``` ```
Install into user profile: Install into user profile:
```bash ```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. The Nix package wraps `vcom` with `ueberzugpp` in `PATH`, so image preview works in non-`kitty` terminals out of the box.
### Debian / Ubuntu ### Debian / Ubuntu
Download the release `.deb` for `v0.1.5`, then install: Download the release `.deb` for `v0.1.7`, then install:
```bash ```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): Install a Nerd Font (example):
@ -136,7 +136,7 @@ Built-in themes:
## Releases ## 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 - runs tests
- vendors Go modules - vendors Go modules
@ -146,9 +146,9 @@ Pushing a tag like `v0.1.5` triggers GitHub Actions release workflow (`.github/w
Release artifacts: Release artifacts:
- `vcom-v0.1.5-x86_64-unknown-linux-gnu.tar.gz` - `vcom-v0.1.7-x86_64-unknown-linux-gnu.tar.gz`
- `vcom_0.1.5_amd64.deb` - `vcom_0.1.7_amd64.deb`
- `vcom-v0.1.5-checksums.txt` - `vcom-v0.1.7-checksums.txt`
## Notes ## Notes

View file

@ -13,7 +13,7 @@
lib = pkgs.lib; lib = pkgs.lib;
packageBase = pkgs.buildGoModule { packageBase = pkgs.buildGoModule {
pname = "vcom"; pname = "vcom";
version = "0.1.5"; version = "0.1.7";
src = ./.; src = ./.;
vendorHash = null; vendorHash = null;

View file

@ -127,14 +127,31 @@ func (m *imageOverlayManager) startBackend(backend string) error {
return nil 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 { func (m *imageOverlayManager) ensureStarted() error {
if m.running { if m.running {
return nil return nil
} }
if _, err := exec.LookPath("ueberzugpp"); err != nil {
return err
}
if _, err := exec.LookPath("ueberzugpp"); err == nil {
var lastErr error var lastErr error
for _, backend := range m.backendList() { for _, backend := range m.backendList() {
if err := m.startBackend(backend); err != nil { if err := m.startBackend(backend); err != nil {
@ -152,11 +169,26 @@ func (m *imageOverlayManager) ensureStarted() error {
} }
return nil return nil
} }
if lastErr != nil { if lastErr != nil {
return lastErr return lastErr
} }
return fmt.Errorf("could not start ueberzugpp overlay") }
if _, err := exec.LookPath("ueberzug"); err == nil {
if err := m.startLegacyBackend(); err != nil {
return err
}
if err := m.send(map[string]any{
"action": "remove",
"identifier": m.identifier,
}); err != nil {
m.stop()
return err
}
return nil
}
return fmt.Errorf("could not start image overlay backend")
} }
func (m *imageOverlayManager) send(payload map[string]any) error { func (m *imageOverlayManager) send(payload map[string]any) error {
@ -202,12 +234,16 @@ func (m *imageOverlayManager) show(path string, rect overlayRect) error {
"path": path, "path": path,
"x": rect.x, "x": rect.x,
"y": rect.y, "y": rect.y,
"max_width": rect.width, }
"max_height": rect.height, if m.backend == "ueberzug" {
"scaler": "fit_contain", 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 { if err := m.send(payload); err == nil {
m.backend = "ueberzugpp"
m.visible = true m.visible = true
m.lastPath = path m.lastPath = path
m.lastRect = rect m.lastRect = rect
@ -215,8 +251,10 @@ func (m *imageOverlayManager) show(path string, rect overlayRect) error {
} }
m.stop() m.stop()
if len(m.backends) > 0 { if m.backend != "ueberzug" && len(m.backends) > 0 {
m.backends = append(m.backends[1:], m.backends[0]) m.backends = append(m.backends[1:], m.backends[0])
} else {
break
} }
} }
return fmt.Errorf("could not render image overlay") return fmt.Errorf("could not render image overlay")
@ -229,7 +267,7 @@ func (m *imageOverlayManager) hide() {
switch m.backend { switch m.backend {
case "kitty": case "kitty":
m.clearKitty() m.clearKitty()
case "ueberzugpp": case "ueberzugpp", "ueberzug":
if m.running { if m.running {
_ = m.send(map[string]any{ _ = m.send(map[string]any{
"action": "remove", "action": "remove",

View file

@ -29,7 +29,7 @@ Section: utils
Priority: optional Priority: optional
Architecture: amd64 Architecture: amd64
Maintainer: Roman Vrubel <roman@vrubel.dev> Maintainer: Roman Vrubel <roman@vrubel.dev>
Depends: ueberzugpp Depends: ueberzug | ueberzugpp
Description: Terminal file manager inspired by Midnight Commander Description: Terminal file manager inspired by Midnight Commander
A two-pane terminal file manager with inspect mode and text previews. A two-pane terminal file manager with inspect mode and text previews.
EOF EOF