nsxiv image viewer debian 11 bash script

Slug: nsxiv

14905 characters 1672 words
#!/bin/bash set -euo pipefail # Script to build and install nsxiv (Neo Simple X Image Viewer) # Target: Debian 11 (Bullseye) on ARM64 RK3588 # Purpose: Automates dependencies, Imlib2 compilation (fixing version issues), # nsxiv compilation (with optimizations), and post-install configuration. # --- Configuration Variables --- BUILD_DIR="$HOME/build" NSXIV_REPO_URL="https://codeberg.org/nsxiv/nsxiv.git" NSXIV_DIR="$BUILD_DIR/nsxiv" CONFIG_DIR="$HOME/.config/nsxiv/exec" IMLIB2_VERSION="1.12.6" IMLIB2_URL="https://downloads.sourceforge.net/enlightenment/imlib2-${IMLIB2_VERSION}.tar.xz" IMLIB2_DIR="$BUILD_DIR/imlib2-${IMLIB2_VERSION}" LD_CONF_FILE="/etc/ld.so.conf.d/local-libs.conf" # --- Helper Functions --- # Function to check if a command exists and install its package if missing ensure_tool_installed() { local tool_name="$1" local package_name="${2:-$tool_name}" # Use second arg as package name if provided, else tool_name if ! command -v "$tool_name" >/dev/null 2>&1; then echo "Tool '$tool_name' not found. Installing '$package_name'..." if ! sudo apt install -y "$package_name"; then echo "Error: Failed to install '$package_name'." >&2 exit 1 fi echo "'$package_name' installed successfully." else echo "Tool '$tool_name' is already installed." fi } # Setup trap for cleanup on exit trap 'echo "Script execution finished or interrupted."' EXIT SIGINT SIGTERM # --- Main Script --- echo "Starting nsxiv build and installation script for RK3588..." # --- Phase 1: Preparation & Dependencies --- echo "Updating package lists..." if ! sudo apt update; then echo "Error: Failed to update package lists." >&2 exit 1 fi echo "Package lists updated." echo "Installing build dependencies and required tools..." # Core build tools ensure_tool_installed "git" ensure_tool_installed "make" "build-essential" ensure_tool_installed "gcc" ensure_tool_installed "wget" # Specific library development headers and runtime tools # Note: 'gimp' and 'rawtherapee' are added because the default key-handler script uses them. PACKAGES_TO_INSTALL=( "libx11-dev" "libimlib2-dev" # Needed initially for dependencies, will be overridden by custom build "libxft-dev" "libexif-dev" "libfontconfig1-dev" "xclip" "libjpeg-progs" "imagemagick" "exiv2" "gimp" "rawtherapee" "libjpeg-dev" "libpng-dev" "libtiff-dev" "libgif-dev" "libwebp-dev" "libfreetype6-dev" "libxext-dev" "libxcb1-dev" ) echo "Installing packages: ${PACKAGES_TO_INSTALL[*]}" if ! sudo apt install -y "${PACKAGES_TO_INSTALL[@]}"; then echo "Error: Failed to install dependencies." >&2 exit 1 fi echo "Dependencies installed successfully." # --- Phase 2: Handling Imlib2 Version Issue --- echo "Checking Imlib2 version requirements..." # Debian 11 has an old Imlib2. We need to build a newer one. # Remove system libimlib2-dev to avoid conflicts during build if dpkg -s libimlib2-dev >/dev/null 2>&1; then echo "Removing system libimlib2-dev to prevent conflicts with custom build..." if ! sudo apt remove -y libimlib2-dev; then echo "Error: Failed to remove libimlib2-dev." >&2 exit 1 fi echo "System libimlib2-dev removed." fi # Create build directory if [ ! -d "$BUILD_DIR" ]; then mkdir -p "$BUILD_DIR" echo "Created build directory: $BUILD_DIR" fi # Download and Extract Imlib2 if [ ! -d "$IMLIB2_DIR" ]; then echo "Downloading Imlib2 ${IMLIB2_VERSION}..." cd "$BUILD_DIR" if ! wget "$IMLIB2_URL"; then echo "Error: Failed to download Imlib2." >&2 exit 1 fi echo "Extracting Imlib2..." if ! tar -xf "imlib2-${IMLIB2_VERSION}.tar.xz"; then echo "Error: Failed to extract Imlib2." >&2 exit 1 fi else echo "Imlib2 source directory already exists. Skipping download." fi echo "Configuring and compiling Imlib2..." cd "$IMLIB2_DIR" # Clean previous builds if any if [ -f "Makefile" ]; then make clean || true fi # Configure with specific flags to avoid issues with old system libs (avif, heif, jxl) # We install to /usr/local to keep it separate from system packages if ! ./configure --prefix=/usr/local --without-avif --without-heif --without-jxl; then echo "Error: Imlib2 configuration failed." >&2 exit 1 fi echo "Compiling Imlib2 (this may take a while)..." if ! make -j$(nproc); then echo "Error: Imlib2 compilation failed." >&2 exit 1 fi echo "Installing Imlib2..." if ! sudo make install; then echo "Error: Imlib2 installation failed." >&2 exit 1 fi echo "Updating library cache..." # Ensure /usr/local/lib is in the linker search path if [ ! -f "$LD_CONF_FILE" ]; then echo "Creating linker config file $LD_CONF_FILE..." echo "/usr/local/lib" | sudo tee "$LD_CONF_FILE" > /dev/null else # Check if it already contains the path if ! grep -q "/usr/local/lib" "$LD_CONF_FILE"; then echo "/usr/local/lib" | sudo tee -a "$LD_CONF_FILE" > /dev/null echo "Added /usr/local/lib to $LD_CONF_FILE" fi fi if ! sudo ldconfig; then echo "Error: Failed to update library cache with ldconfig." >&2 exit 1 fi echo "Imlib2 installed and library cache updated." # --- Phase 3: Downloading and Building nsxiv --- echo "Preparing to build nsxiv..." if [ ! -d "$NSXIV_DIR" ]; then echo "Cloning nsxiv repository..." cd "$BUILD_DIR" if ! git clone "$NSXIV_REPO_URL"; then echo "Error: Failed to clone nsxiv repository." >&2 exit 1 fi else echo "nsxiv repository already exists. Pulling latest changes..." cd "$NSXIV_DIR" git pull fi cd "$NSXIV_DIR" # Clean previous builds make clean || true # Configure config.mk for RK3588 optimization echo "Configuring config.mk for ARM64 optimization..." # Replace CFLAGS with optimized version for Cortex-A76/A55 if [ -f "config.mk" ]; then sed -i 's/^CFLAGS = -Wall -pedantic -O2 -DNDEBUG/CFLAGS = -Wall -pedantic -O3 -mcpu=native -DNDEBUG/' config.mk echo "config.mk updated." else echo "Error: config.mk not found in nsxiv directory." >&2 exit 1 fi # Generate config.h echo "Generating config.h..." if ! make config.h; then echo "Error: Failed to generate config.h." >&2 exit 1 fi # Edit config.h settings echo "Applying custom settings to config.h..." # Increase cache size to 10% (using flexible regex for whitespace) sed -i 's/static const int CACHE_SIZE_MEM_PERCENTAGE[[:space:]]*=[[:space:]]*3;/static const int CACHE_SIZE_MEM_PERCENTAGE = 10;/' config.h # Change font to monospace-10 (using flexible regex) # Matches: static const char *BAR_FONT[] = { "Nsxiv.bar.font", "monospace-8" }; sed -i 's/static const char \*BAR_FONT\[\][[:space:]]*=[[:space:]]*{[[:space:]]*"Nsxiv.bar.font",[[:space:]]*"monospace-8"[[:space:]]*};/static const char *BAR_FONT[] = { "Nsxiv.bar.font", "monospace-10" };/' config.h echo "config.h updated." # Set environment variables to ensure compiler finds the new Imlib2 headers/libs export CPATH="/usr/local/include:${CPATH:-}" export LIBRARY_PATH="/usr/local/lib:${LIBRARY_PATH:-}" export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH:-}" echo "Compiling nsxiv..." if ! make; then echo "Error: nsxiv compilation failed." >&2 exit 1 fi echo "Installing nsxiv..." if ! sudo make install-all; then echo "Error: nsxiv installation failed." >&2 exit 1 fi echo "nsxiv installed successfully." # --- Phase 4: Post-Install Integration --- echo "Setting up post-install scripts and configuration..." # Create config directory if [ ! -d "$CONFIG_DIR" ]; then mkdir -p "$CONFIG_DIR" echo "Created configuration directory: $CONFIG_DIR" fi # Copy example scripts echo "Copying example scripts..." if cp etc/examples/* "$CONFIG_DIR/"; then echo "Scripts copied." else echo "Error: Failed to copy example scripts." >&2 exit 1 fi # Make scripts executable chmod +x "$CONFIG_DIR"/* echo "Scripts made executable." # Fix key-handler script for Alacritty/Zutty support KEY_HANDLER_SCRIPT="$CONFIG_DIR/key-handler" echo "Modifying key-handler script for terminal compatibility..." # Overwrite key-handler with the corrected content cat << 'EOF' > "$KEY_HANDLER_SCRIPT" #!/bin/sh # Example for $XDG_CONFIG_HOME/nsxiv/exec/key-handler # Called by nsxiv(1) after the external prefix key (C-x by default) is pressed. # The next key combo is passed as its first argument. Passed via stdin are the # images to act upon: all marked images, if in thumbnail mode and at least one # image has been marked, otherwise the current image. nsxiv(1) will block until # the handler terminates. It then checks which images have been modified and # reloads them. # The key combo argument has the following form: "[C-][M-][S-]KEY", # where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X # keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix. # If KEY has an uppercase equivalent, S-KEY is resolved into it. For instance, # K replaces S-k and Scedilla replaces S-scedilla, but S-Delete is sent as-is. # By default nsxiv(1) will send one image per-line to stdin, however when using # -0 the image list will be NULL separated and the environment variable # "$NSXIV_USING_NULL" will be set to 1. [ "$NSXIV_USING_NULL" = 1 ] && DELIM='\0' || DELIM='\n' rotate() { tr "$DELIM" '\0' | xargs -0 realpath -z | sort -z -u | xargs -0 -I {} sh -c ' degree="$1" case "$(file -b -i "{}")" in image/jpeg*) jpegtran -rotate "$degree" -copy all -outfile "{}" "{}" ;; *) mogrify -rotate "$degree" "{}" ;; esac ' -- "$1" } spawn_term() { title=$1 shift # If you set PREF_TERM, we'll honor it *if available*. if [ "${PREF_TERM:-}" = "alacritty" ] && command -v alacritty >/dev/null 2>&1; then alacritty -T "$title" -e "$@" return fi if [ "${PREF_TERM:-}" = "zutty" ] && command -v zutty >/dev/null 2>&1; then zutty -bg "#444" -fg "#eee" -saveLines 0 -title "$title" -e "$@" return fi # Auto-select. If both exist, this prefers alacritty; swap the order if you prefer zutty. if command -v alacritty >/dev/null 2>&1; then alacritty -T "$title" -e "$@" elif command -v zutty >/dev/null 2>&1; then zutty -bg "#444" -fg "#eee" -saveLines 0 -title "$title" -e "$@" else printf >&2 'No supported terminal found (need alacritty and/or zutty)\n' return 127 fi } case "$1" in "C-x") xclip -in -filter | tr '\n' ' ' | xclip -in -selection clipboard ;; "C-c") while read file; do xclip -selection clipboard -target image/png "$file"; done ;; "C-e") if [ "${PREF_TERM:-}" = "alacritty" ] && command -v alacritty >/dev/null 2>&1; then T=alacritty; elif [ "${PREF_TERM:-}" = "zutty" ] && command -v zutty >/dev/null 2>&1; then T=zutty; elif command -v alacritty >/dev/null 2>&1; then T=alacritty; elif command -v zutty >/dev/null 2>&1; then T=zutty; else T=; printf >&2 'No supported terminal found (need alacritty and/or zutty)\n'; fi; if [ -n "$T" ]; then while IFS= read -r file; do if [ "$T" = alacritty ]; then alacritty -T "$file" -e sh -c 'exiv2 -q -pa pr "$1" | less' sh "$file" & else zutty -bg "#444" -fg "#eee" -saveLines 0 -title "$file" -e sh -c 'exiv2 -q -pa pr "$1" | less' sh "$file" & fi; done; fi ;; "C-g") tr '\n' '\0' | xargs -0 gimp & ;; "C-r") while read file; do rawtherapee "$file" & done ;; "C-comma") rotate 270 ;; "C-period") rotate 90 ;; "C-slash") rotate 180 ;; esac EOF echo "key-handler script updated." # --- Phase 5: Verification --- echo "Verifying installation..." if nsxiv -v; then echo "nsxiv version check passed." else echo "Error: nsxiv version check failed." >&2 exit 1 fi echo "Checking library linking..." if ldd "$(which nsxiv)" | grep -q "/usr/local/lib/libImlib2.so"; then echo "Library linking check passed: nsxiv is using the correct Imlib2." else echo "Warning: nsxiv might be linking to the wrong Imlib2 library." echo "Current link:" ldd "$(which nsxiv)" | grep Imlib2 echo "Please verify manually." fi echo "----------------------------------------------------------------" echo "Installation Complete!" echo "You can now use 'nsxiv' to view images." echo "Example: nsxiv ~/Pictures" echo "----------------------------------------------------------------" exit 0
URL: https://ib.bsb.br/nsxiv