aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetri Hienonen <petri.hienonen@gmail.com>2025-12-09 11:26:58 +0200
committerPetri Hienonen <petri.hienonen@gmail.com>2025-12-09 11:26:58 +0200
commit2a07311858bd81c620049c3856d623850336ff57 (patch)
tree5ed9b9d8a92416c4ba4e4c60981e5d78d66e3e0b
parent23ebca1a0cf38edce53f23e8d61254845e205e19 (diff)
downloadnixos-2a07311858bd81c620049c3856d623850336ff57.tar.zst
Add zaread
-rw-r--r--home/zaread.nix257
1 files changed, 257 insertions, 0 deletions
diff --git a/home/zaread.nix b/home/zaread.nix
new file mode 100644
index 0000000..487740a
--- /dev/null
+++ b/home/zaread.nix
@@ -0,0 +1,257 @@
+{ pkgs, lib, ... }:
+
+let
+ zareadScript = pkgs.writeShellScriptBin "zaread" ''
+ # zaread cache path
+ ZA_CACHE_DIR="''${XDG_CACHE_HOME:-"$HOME"/.cache}/zaread/"
+ # zaread config path
+ ZA_CONFIG="''${XDG_CONFIG_HOME:-"$HOME"/.config}/zaread/zareadrc"
+
+ # Default reader, i.e. command, which script uses to open pdf, epub and converted files
+ READER="${pkgs.zathura}/bin/zathura"
+ # Default converters, i.e. commands, which script uses to convert files to pdf
+ MOBI_CMD="${pkgs.calibre}/bin/ebook-convert"
+ OFFICE_CMD="${pkgs.libreoffice-fresh}/bin/soffice"
+ MD_CMD="${pkgs.md2pdf or pkgs.pandoc}/bin/${if pkgs ? md2pdf then "md2pdf" else "pandoc"}"
+ TYPST_CMD="${pkgs.typst}/bin/typst"
+ TYPST_ARG="compile" # Can be changed to "watch"
+ MD_ARG=""
+ MOBI_ARG=""
+ OFFICE_ARG="--headless"
+ # If you want to use other commands set these vars in $ZA_CONFIG. Some cli
+ # arguments are hardcoded so some commands won't work. Check that first.
+
+ # Sources the variables from config file if exists
+ # shellcheck disable=1090
+ [ -f "$ZA_CONFIG" ] && . "$ZA_CONFIG"
+
+ # if $ZA_CACHE_DIR doesn't exist, we create it.
+ [ ! -d "$ZA_CACHE_DIR" ] && mkdir -p "$ZA_CACHE_DIR"
+
+ # Exit if called without arguments
+ if [ "$#" = 0 ]; then
+ echo "No files to open."
+ exit
+ fi
+
+ if [ "$#" != 1 ]; then
+ echo "More than one filename given. Closing."
+ exit 1
+ fi
+
+ path="$1"
+
+ if [ ! -f "$path" ]; then
+ echo "File doesn't exist."
+ exit 1
+ fi
+
+ if ! command -v "$READER" >/dev/null; then
+ echo "$READER is not on the $PATH."
+ echo "Closing."
+ exit 1
+ fi
+
+ echo "\$READER='$READER' is in the \$PATH. Starting script..."
+
+ ## create position and file variables ##
+
+ # complete file name (path excluded):
+ file="$(basename "$path")"
+ echo "Filename: $file"
+ case "$path" in
+ # complete directory path:
+ # if it has been inserted absolute path ($path starts with '/')
+ /*)
+ directory="$(dirname "$path")"
+ ;;
+ # else (relative path inserted)
+ *)
+ directory="''${PWD}/$(dirname "$path")"
+ # directory="$(echo "$dir" | tr -s '/')"
+ ;;
+ esac
+
+ echo "Directory: $directory/"
+ echo "Path: $directory/$file"
+
+ # get file type
+
+ # if the file is itself a pdf, a djvu or an epub, or we already have a pdf converted version,
+ # then we don't need a converter. But if it's an already converted document, then
+ # file position is different: we must distinguish between original and converted files
+ file_mt="$(file --mime-type "$directory/$file")"
+ file_mt="''${file_mt#*: }"
+ echo "Mime type: $file_mt"
+
+ cd "$directory" || {
+ echo "Couldn't cd into $directory"
+ exit 1
+ }
+
+ # $pdffile is a string composed this way: CRC_BYTECOUNT_$filename.[pdf,epub]
+ # if the converted file exists, then it's named like $pdffile
+ pdffile="$(cksum "$file" | sed -E 's/^([0-9]+) ([0-9]+) (.*)$/\1_\2_\3.pdf/')"
+ echo "Converted pdf filename: $pdffile"
+
+ file_converter=""
+ # If the converted file exists we can just open it.
+ if [ -f "$ZA_CACHE_DIR/$pdffile" ]; then
+ file_converter="none_converted"
+ else
+ case "$file_mt" in
+ "application/pdf" | "image/vnd.djvu" | "application/epub+zip")
+ # If the file is a pdf, a djvu or an epub we don't need to convert it.
+ file_converter="none_original"
+ ;;
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | \
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | \
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation" | \
+ "application/msword" | \
+ "application/vnd.ms-excel" | \
+ "application/vnd.ms-powerpoint" | \
+ "application/vnd.oasis.opendocument.text" | \
+ "application/vnd.oasis.opendocument.spreadsheet" | \
+ "application/vnd.oasis.opendocument.presentation" | \
+ "text/rtf" | \
+ "text/csv")
+ # If the file is an office file (ooxml or the old format or an
+ # opendocument) we convert it using $OFFICE_CMD.
+ file_converter="$OFFICE_CMD"
+ ;;
+ "application/octet-stream" | \
+ "application/x-mobipocket-ebook")
+
+ case "$file" in
+ *.mobi)
+ # If the file is a mobi ebook we convert it using $MOBI_CMD.
+ file_converter="$MOBI_CMD"
+ ;;
+ esac
+ ;;
+ "text/plain" | \
+ "text/x-c" | \
+ "text/x-objective-c" | \
+ "text/x-script.python" )
+ case "$file" in
+ *.md)
+ # If the file is a markdown we convert it using $MD_CMD.
+ file_converter="$MD_CMD"
+ ;;
+ *.typ)
+ file_converter="$TYPST_CMD"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+
+ case "$file_converter" in
+ "")
+ echo "The file format is unsupported."
+ exit 2
+ ;;
+ "none_original")
+ echo "The file is already in PDF format. We just open it."
+ eval "$READER" \""$directory/$file"\"
+ ;;
+ "none_converted")
+ echo "We already converted this file. We just open it."
+ eval "$READER" \""$ZA_CACHE_DIR/$pdffile"\"
+ ;;
+ *)
+ # So the file is not a pdf or an epub, and a converted version
+ # doesn't exist, but its format may be convertible
+ if command -v "$file_converter" >/dev/null; then
+ echo "We are starting to convert the file \"$file\" using $file_converter"
+ # If converter tools are changed in $ZA_CONFIG check calling
+ # commands bellow. They may need to be called with different
+ # arguments and format.
+ case "$file_converter" in
+ "$OFFICE_CMD")
+ eval "$OFFICE_CMD" "$OFFICE_ARG" --convert-to pdf \""$directory/$file"\" --outdir \""$ZA_CACHE_DIR"\"
+ # We need to handle cases where file starts with a . and
+ # that's the only one . in filename, i.e. filename hasn't
+ # got extension
+ case "$file" in
+ .*.*)
+ # If it has one more . after the first character
+ # which is a ., we'll consider that as an
+ # extension, so we can use parameter expansion,
+ # and we need this case for the next one to work.
+ tmpfile="''${file%.*}.pdf"
+ ;;
+ .*)
+ # If this case was the first it would also match cases with 2 .'s in the filename.
+ # If the filename starts with a . and it hasn't got an
+ # extension, we just add .pdf to the filename to get
+ # tmpfilename
+ tmpfile="$file.pdf"
+ ;;
+ *)
+ # In the rest of cases we can use parameter expansion
+ tmpfile="''${file%.*}.pdf"
+ ;;
+ esac
+ mv "$ZA_CACHE_DIR/$tmpfile" "$ZA_CACHE_DIR/$pdffile"
+ ;;
+ "$MOBI_CMD")
+ eval "$MOBI_CMD" "$MOBI_ARG" \""$directory/$file"\" \""$ZA_CACHE_DIR/$pdffile"\"
+ ;;
+ "$MD_CMD")
+ if [ "$MD_CMD" = "${pkgs.pandoc}/bin/pandoc" ]; then
+ eval "$MD_CMD" "$MD_ARG" \""$directory/$file"\" -o \""$ZA_CACHE_DIR/$pdffile"\"
+ else
+ eval "$MD_CMD" "$MD_ARG" \""$directory/$file"\" -o \""$ZA_CACHE_DIR/$pdffile"\"
+ fi
+ ;;
+ "$TYPST_CMD")
+ eval "$TYPST_CMD" "$TYPST_ARG" \""$directory/$file"\" \""$ZA_CACHE_DIR/$pdffile"\" --open "$READER"
+ exit
+ ;;
+ esac
+ else
+ echo "The command we need to convert '$file_converter' is not in \$PATH."
+ exit 4
+ fi
+ echo "Now we can open the file $ZA_CACHE_DIR/$pdffile"
+ # ...and after the conversion we open the file
+ eval "$READER" \""$ZA_CACHE_DIR/$pdffile"\"
+ ;;
+ esac
+ '';
+in
+{
+ home.packages = [ zareadScript ];
+
+ xdg.desktopEntries.zaread = {
+ name = "zaread";
+ exec = "${zareadScript}/bin/zaread %f";
+ icon = "org.pwmt.zathura";
+ comment = "Lightweight ebook and office document reader";
+ terminal = false;
+ noDisplay = true;
+ categories = [
+ "Office"
+ "Viewer"
+ ];
+ mimeType = [
+ "application/pdf"
+ "image/vnd.djvu"
+ "application/epub+zip"
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation"
+ "application/msword"
+ "application/vnd.ms-excel"
+ "application/vnd.ms-powerpoint"
+ "application/vnd.oasis.opendocument.text"
+ "application/vnd.oasis.opendocument.spreadsheet"
+ "application/vnd.oasis.opendocument.presentation"
+ "text/rtf"
+ "text/csv"
+ "application/x-mobipocket-ebook"
+ "text/plain"
+ ];
+ };
+}