summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Zhao <jeff.no.zhao@gmail.com>2022-01-16 15:15:33 -0500
committerJeff Zhao <jeff.no.zhao@gmail.com>2022-01-16 15:15:33 -0500
commit821b69f0b460783554d793c925d26e844f34a632 (patch)
tree1843daf4f8f0c5560469887142fb1ce9e0881cd6
parent8bdd74f821344be79692d369c0762bcb85d05661 (diff)
rework file previews to have better argument handling
-rw-r--r--config/joshuto.toml2
-rwxr-xr-xdocs/preview_file.sh258
-rw-r--r--src/preview/preview_file.rs45
3 files changed, 299 insertions, 6 deletions
diff --git a/config/joshuto.toml b/config/joshuto.toml
index f7b3bbb..612d7e2 100644
--- a/config/joshuto.toml
+++ b/config/joshuto.toml
@@ -27,7 +27,7 @@ reverse = false
[preview]
max_preview_size = 2097152 # 2MB
preview_images = false
-preview_script = "~/.config/joshuto/preview.sh"
+preview_script = "~/.config/joshuto/preview_file.sh"
[tab]
# inherit, home, root
diff --git a/docs/preview_file.sh b/docs/preview_file.sh
new file mode 100755
index 0000000..f71d8bb
--- /dev/null
+++ b/docs/preview_file.sh
@@ -0,0 +1,258 @@
+#!/usr/bin/env bash
+
+set -o noclobber -o noglob -o nounset -o pipefail
+IFS=$'\n'
+
+## If the option `use_preview_script` is set to `true`,
+## then this script will be called and its output will be displayed in ranger.
+## ANSI color codes are supported.
+## STDIN is disabled, so interactive scripts won't work properly
+
+## This script is considered a configuration file and must be updated manually.
+## It will be left untouched if you upgrade ranger.
+
+## Because of some automated testing we do on the script #'s for comments need
+## to be doubled up. Code that is commented out, because it's an alternative for
+## example, gets only one #.
+
+## Meanings of exit codes:
+## code | meaning | action of ranger
+## -----+------------+-------------------------------------------
+## 0 | success | Display stdout as preview
+## 1 | no preview | Display no preview at all
+## 2 | plain text | Display the plain content of the file
+## 3 | fix width | Don't reload when width changes
+## 4 | fix height | Don't reload when height changes
+## 5 | fix both | Don't ever reload
+## 6 | image | Display the image `$IMAGE_CACHE_PATH` points to as an image preview
+## 7 | image | Display the file directly as an image
+
+FILE_PATH=""
+PREVIEW_IMAGE_ENABLED=0
+PREVIEW_WIDTH=10
+PREVIEW_HEIGHT=10
+PREVIEW_X_COORD=0
+PREVIEW_Y_COORD=0
+IMAGE_CACHE_PATH=""
+
+# echo "$@"
+
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ "--path")
+ shift
+ FILE_PATH="$1"
+ ;;
+ "--preview-width")
+ shift
+ PREVIEW_WIDTH="$1"
+ ;;
+ "--preview-height")
+ shift
+ PREVIEW_HEIGHT="$1"
+ ;;
+ "--x-coord")
+ shift
+ PREVIEW_X_COORD="$1"
+ ;;
+ "--y-coord")
+ shift
+ PREVIEW_Y_COORD="$1"
+ ;;
+ "--preview-images")
+ shift
+ PREVIEW_IMAGE_ENABLED="$1"
+ ;;
+ "--image-cache")
+ shift
+ IMAGE_CACHE_PATH="$1"
+ ;;
+ esac
+ shift
+done
+
+FILE_EXTENSION="${FILE_PATH##*.}"
+FILE_EXTENSION_LOWER="$(printf "%s" "${FILE_EXTENSION}" | tr '[:upper:]' '[:lower:]')"
+
+MIMETYPE=$(file --mime-type -Lb "${FILE_PATH}")
+
+## Settings
+HIGHLIGHT_SIZE_MAX=262143 # 256KiB
+HIGHLIGHT_TABWIDTH="${HIGHLIGHT_TABWIDTH:-8}"
+HIGHLIGHT_STYLE="${HIGHLIGHT_STYLE:-pablo}"
+HIGHLIGHT_OPTIONS="--replace-tabs=${HIGHLIGHT_TABWIDTH} --style=${HIGHLIGHT_STYLE} ${HIGHLIGHT_OPTIONS:-}"
+PYGMENTIZE_STYLE="${PYGMENTIZE_STYLE:-autumn}"
+OPENSCAD_IMGSIZE="${RNGR_OPENSCAD_IMGSIZE:-1000,1000}"
+OPENSCAD_COLORSCHEME="${RNGR_OPENSCAD_COLORSCHEME:-Tomorrow Night}"
+
+handle_extension() {
+ case "${FILE_EXTENSION_LOWER}" in
+ ## Archive
+ a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
+ rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
+ atool --list -- "${FILE_PATH}" && exit 5
+ bsdtar --list --file "${FILE_PATH}" && exit 5
+ exit 1;;
+ rar)
+ ## Avoid password prompt by providing empty password
+ unrar lt -p- -- "${FILE_PATH}" && exit 5
+ exit 1;;
+ 7z)
+ ## Avoid password prompt by providing empty password
+ 7z l -p -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## PDF
+ ## pdf)
+ ## Preview as text conversion
+ ## pdftotext -l 10 -nopgbrk -q -- "${FILE_PATH}" - | \
+ ## fmt -w "${PREVIEW_WIDTH}" && exit 5
+ ## mutool draw -F txt -i -- "${FILE_PATH}" 1-10 | \
+ ## fmt -w "${PREVIEW_WIDTH}" && exit 5
+ ## exiftool "${FILE_PATH}" && exit 5
+ ## exit 1;;
+
+ ## BitTorrent
+ torrent)
+ transmission-show -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## OpenDocument
+ odt|ods|odp|sxw)
+ ## Preview as text conversion
+ odt2txt "${FILE_PATH}" && exit 5
+ ## Preview as markdown conversion
+ pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## XLSX
+ xlsx)
+ ## Preview as csv conversion
+ ## Uses: https://github.com/dilshod/xlsx2csv
+ xlsx2csv -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## HTML
+ htm|html|xhtml)
+ ## Preview as text conversion
+ w3m -dump "${FILE_PATH}" && exit 5
+ lynx -dump -- "${FILE_PATH}" && exit 5
+ elinks -dump "${FILE_PATH}" && exit 5
+ pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
+ ;;
+
+ ## JSON
+ json|ipynb)
+ jq --color-output . "${FILE_PATH}" && exit 5
+ python -m json.tool -- "${FILE_PATH}" && exit 5
+ ;;
+
+ ## Direct Stream Digital/Transfer (DSDIFF) and wavpack aren't detected
+ ## by file(1).
+ dff|dsf|wv|wvc)
+ mediainfo "${FILE_PATH}" && exit 5
+ exiftool "${FILE_PATH}" && exit 5
+ ;; # Continue with next handler on failure
+ esac
+}
+
+handle_image() {
+ ## Size of the preview if there are multiple options or it has to be
+ ## rendered from vector graphics. If the conversion program allows
+ ## specifying only one dimension while keeping the aspect ratio, the width
+ ## will be used.
+ local DEFAULT_SIZE="40x30"
+
+ local mimetype="${1}"
+ case "${mimetype}" in
+ ## Image
+ image/*)
+ # kitty +kitten icat --clear
+ kitty +kitten icat \
+ --transfer-mode file \
+ --place "${PREVIEW_WIDTH}x${PREVIEW_HEIGHT}@${PREVIEW_X_COORD}x${PREVIEW_Y_COORD}" \
+ "${FILE_PATH}"
+ exit 7
+ ;;
+ esac
+}
+
+handle_mime() {
+ local mimetype="${1}"
+
+ case "${mimetype}" in
+ ## RTF and DOC
+ text/rtf|*msword)
+ ## Preview as text conversion
+ ## note: catdoc does not always work for .doc files
+ ## catdoc: http://www.wagner.pp.ru/~vitus/software/catdoc/
+ catdoc -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## DOCX, ePub, FB2 (using markdown)
+ ## You might want to remove "|epub" and/or "|fb2" below if you have
+ ## uncommented other methods to preview those formats
+ *wordprocessingml.document|*/epub+zip|*/x-fictionbook+xml)
+ ## Preview as markdown conversion
+ pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## E-mails
+ message/rfc822)
+ ## Parsing performed by mu: https://github.com/djcb/mu
+ mu view -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## XLS
+ *ms-excel)
+ ## Preview as csv conversion
+ ## xls2csv comes with catdoc:
+ ## http://www.wagner.pp.ru/~vitus/software/catdoc/
+ xls2csv -- "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## Text
+ text/* | */xml)
+ bat --color=always --paging=never \
+ --style=plain \
+ --terminal-width="${PREVIEW_WIDTH}" \
+ "${FILE_PATH}" && exit 5
+ exit 2;;
+
+ ## DjVu
+ image/vnd.djvu)
+ ## Preview as text conversion (requires djvulibre)
+ djvutxt "${FILE_PATH}" | fmt -w "${PREVIEW_WIDTH}" && exit 5
+ exiftool "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## Image
+ image/*)
+ ## Preview as text conversion
+ # img2txt --gamma=0.6 --width="${PREVIEW_WIDTH}" -- "${FILE_PATH}" && exit 4
+ exiftool "${FILE_PATH}" && exit 5
+ exit 1;;
+
+ ## Video and audio
+ ## video/* | audio/*)
+ ## mediainfo "${FILE_PATH}" && exit 5
+ ## exiftool "${FILE_PATH}" && exit 5
+ ## exit 1;;
+ esac
+}
+
+handle_fallback() {
+ # echo '----- File Type Classification -----' && file --dereference --brief -- "${FILE_PATH}" && exit 5
+ exit 1
+}
+
+
+MIMETYPE="$( file --dereference --brief --mime-type -- "${FILE_PATH}" )"
+if [[ "${PREVIEW_IMAGE_ENABLED}" -eq 1 ]]; then
+ handle_image "${MIMETYPE}"
+fi
+handle_extension
+handle_mime "${MIMETYPE}"
+handle_fallback
+
+exit 1
diff --git a/src/preview/preview_file.rs b/src/preview/preview_file.rs
index 7f0d1ff..9d270e6 100644
--- a/src/preview/preview_file.rs
+++ b/src/preview/preview_file.rs
@@ -44,8 +44,8 @@ impl Foreground {
backend: &mut TuiBackend,
p: path::PathBuf,
) -> io::Result<Output> {
- let preview_options = context.config_ref().preview_options_ref();
let config = context.config_ref();
+ let preview_options = config.preview_options_ref();
match preview_options.preview_script.as_ref() {
None => Err(io::Error::new(
@@ -57,21 +57,40 @@ impl Foreground {
let display_options = config.display_options_ref();
let constraints: &[Constraint; 3] = &display_options.default_layout;
- let layout_rect = ui::build_layout(area, constraints, display_options)[2];
+ let ui_context = context.ui_context_ref();
+ if ui_context.layout.is_empty() {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "No preview area",
+ ));
+ }
+ let layout_rect = &ui_context.layout[ui_context.layout.len() - 1];
let file_full_path = p.as_path();
let preview_width = layout_rect.width;
let preview_height = layout_rect.height;
+ let preview_x_coord = layout_rect.x;
+ let preview_y_coord = layout_rect.y;
+
let image_cache = 0;
let preview_image = if preview_options.preview_images { 1 } else { 0 };
// spawn preview process
Command::new(script)
+ .arg("--path")
.arg(file_full_path)
+ .arg("--preview-width")
.arg(preview_width.to_string())
+ .arg("--preview-height")
.arg(preview_height.to_string())
- .arg(image_cache.to_string())
+ .arg("--x-coord")
+ .arg(preview_x_coord.to_string())
+ .arg("--y-coord")
+ .arg(preview_y_coord.to_string())
+ .arg("--preview-images")
.arg(preview_image.to_string())
+ .arg("--image-cache")
+ .arg(image_cache.to_string())
.output()
}
}
@@ -109,10 +128,17 @@ impl Background {
let display_options = config.display_options_ref();
let constraints: &[Constraint; 3] = &display_options.default_layout;
- let layout_rect = ui::build_layout(area, constraints, display_options)[2];
+ let ui_context = context.ui_context_ref();
+ if ui_context.layout.is_empty() {
+ return;
+ }
+ let layout_rect = &ui_context.layout[ui_context.layout.len() - 1];
let preview_width = layout_rect.width;
let preview_height = layout_rect.height;
+ let preview_x_coord = layout_rect.x;
+ let preview_y_coord = layout_rect.y;
+
let image_cache = 0;
let preview_image = if preview_options.preview_images { 1 } else { 0 };
@@ -122,11 +148,20 @@ impl Background {
let file_full_path = path.as_path();
let res = Command::new(script)
+ .arg("--path")
.arg(file_full_path)
+ .arg("--preview-width")
.arg(preview_width.to_string())
+ .arg("--preview-height")
.arg(preview_height.to_string())
- .arg(image_cache.to_string())
+ .arg("--x-coord")
+ .arg(preview_x_coord.to_string())
+ .arg("--y-coord")
+ .arg(preview_y_coord.to_string())
+ .arg("--preview-images")
.arg(preview_image.to_string())
+ .arg("--image-cache")
+ .arg(image_cache.to_string())
.output();
match res {
Ok(output) => {