/rsop

Simple, fast & configurable tool to open and preview files

Primary LanguageRustMIT LicenseMIT

rsop

Build status AUR version License

Simple, fast & configurable tool to open and preview files.

Ideal for use with terminal file managers (ranger, lf, nnn, etc.). Can also be used as a general alternative to xdg-open and its various clones.

If you spend most time in a terminal, and are unsatisfied by current solutions to associate file types with handler programs, this tool may be for you.

Features

  • Start program to view/edit file according to extension or MIME type
  • Provides 4 commands (all symlinks to a single rsop binary):
    • rso: open file
    • rse: edit file (similar to rso in most cases, except when open to view or edit have a different handler)
    • rsp: preview files in terminal, to be used for example in terminal file managers or fzf preview panel
    • rsi: to identify MIME type
  • Supports opening and previewing from data piped on stdin (very handy for advanced shell scripting, see below)
  • Supports chainable filters to preprocess data (for example to transparently handle .log.xz files)
  • Simple config file (no regex or funky conditionals) to describe file formats, handlers, and associate both
  • xdg-open compatibility mode

Compared to other xdg-open alternatives:

  • rsop is consistent and accurate, unlike say ranger
  • rsop does not rely on .desktop files (see section Why no .desktop support)
  • rsop does opening and previewing with a single self contained tool and config file
  • rsop is not tied to a file manager or a runtime environment, you only need the rsop binary and your config file and can use it in interactive terminal sessions, file managers, fzf invocations...
  • rsop is taylored for terminal users (especially the preview feature)
  • rsop is very fast (see performance section)

Installation

From source

You need a Rust build environment for example from rustup.

cargo build --release
install -Dm 755 -t /usr/local/bin target/release/rsop
ln -rsv /usr/local/bin/rs{op,p}
ln -rsv /usr/local/bin/rs{op,o}
ln -rsv /usr/local/bin/rs{op,e}
ln -rsv /usr/local/bin/rs{op,i}
# to replace system xdg-open:
ln -rsv /usr/local/bin/{rsop,xdg-open}

From the AUR

Arch Linux users can install the rsop-open AUR package.

Configuration

When first started, rsop will create a minimal configuration file usually in ~/.config/rsop/config.toml.

See comments and example in that file to set up file types and handlers for your needs.

A more advanced example configuration file is also available here.

Usage with ranger

Warning: because ranger is built on Python's old ncurses version, the preview panel only supports 8bit colors (see ranger/ranger#690 (comment)), so if the output seems wrong you may need to tweak handlers to generate 8bit colors instead of 24.

In rifle.conf:

= rso "$@"

In scope.sh:

#!/bin/sh
COLUMNS="$2" LINES="$3" exec rsp "$1"

Dont forget to make it executable with chmod +x ~/.config/ranger/scope.sh.

Usage with lf

Add in lfrc:

set filesep "\n"
set ifs "\n"
set previewer ~/.config/lf/preview
cmd open ${{
   for f in ${fx[@]}; do rso "${f}"; done
   lf -remote "send $id redraw"
}}

And create ~/.config/lf/preview with:

#!/bin/sh
COLUMNS="$2" LINES="$3" exec rsp "$1"

Show me some cool stuff rsop can do

  • Simple file explorer with fuzzy searching, using fd and fzf, using rso to preview files and rsp to open them:
fd . | fzf --preview='rsp {}' | xargs -r rso

file explorer

  • Preview files inside an archive, without decompressing it entirely, select one and open it (uses bsdtar, fzf and rso/rsp):
# preview archive (.tar, .tar.gz, .zip, .7z, etc.)
# usage: pa <archive file path>
pa() {
    local -r archive="${1:?}"
    bsdtar -tf "${archive}" |
        grep -v '/$' |
        fzf --preview="bsdtar -xOf \"${archive}\" {} | rsp" |
        xargs -r bsdtar -xOf "${archive}" |
        rso
}

preview archive

This is now integrated in the advanced config example, so you can just run rso <archive> and get the same result.

Performance

rsop is quite fast. In practice it rarely matters because choosing with which program to open or preview files is usually so quick it is not perceptible. However performance can matter if for example you are decompressing a huge tar.gz archive to preview its content. To help with that, rsop uses the splice system call if available on your platform. In the .tar.gz example this allows decompressing data with gzip or pigz and passing it to tar (or whatever you have configured to handle application/x-tar MIME type), without wasting time to copy data in user space between the two programs. This was previously done using a custom code path, but is now done transparently by the standard library.

Other stuff rsop does to remain quick:

  • it is written in Rust (setting aside the RiiR memes, this avoid the 20-50ms startup time of for example Python interpreters)
  • it uses hashtables to search for handlers from MIME types or extensions in constant time
  • it uses the great tree_magic_mini crate for fast MIME identification

FAQ

Why no .desktop support?

  • .desktop do not provide a preview action separate from open.
  • One may need to pipe several programs to get to desired behavior, .desktop files does not help with this.
  • Many programs do not ship one, especially command line tools, so this would be incomplete anyway.
  • On a philosophical level, with .desktop files, the program's author (or packager) decides which MIME types to support, and which arguments to pass to the program. This is a wrong paradidm, as this is fundamentally a user's decision.

What does rsop stands for?

"Really Simple Opener/Previewer" or "Reliable Simple Opener/Previewer" or "RuSt Opener/Previewer"

I haven't really decided yet...

What is the difference between the open, edit and preview actions?

Each action has customizable handlers, so they only do what you set them to do.

However the philosophy is the following :

  • preview is non interactive, typically with only terminal UI, and a maximum number of lines in the output
  • open can be interactive or not, and can open graphical windows or not
  • edit is interactive, defaults to the open handler if no edit handler is set, and only makes sense if you need an action separate from open, for example to edit images with GIMP versus to view them with just an image viewer

License

MIT