summaryrefslogtreecommitdiff
path: root/files/config/suckless/st/icat-mini.sh
diff options
context:
space:
mode:
Diffstat (limited to 'files/config/suckless/st/icat-mini.sh')
-rwxr-xr-xfiles/config/suckless/st/icat-mini.sh801
1 files changed, 0 insertions, 801 deletions
diff --git a/files/config/suckless/st/icat-mini.sh b/files/config/suckless/st/icat-mini.sh
deleted file mode 100755
index 0a8ebab..0000000
--- a/files/config/suckless/st/icat-mini.sh
+++ /dev/null
@@ -1,801 +0,0 @@
-#!/bin/sh
-
-# vim: shiftwidth=4
-
-script_name="$(basename "$0")"
-
-short_help="Usage: $script_name [OPTIONS] <image_file>
-
-This is a script to display images in the terminal using the kitty graphics
-protocol with Unicode placeholders. It is very basic, please use something else
-if you have alternatives.
-
-Options:
- -h Show this help.
- -s SCALE The scale of the image, may be floating point.
- -c N, --cols N The number of columns.
- -r N, --rows N The number of rows.
- --max-cols N The maximum number of columns.
- --max-rows N The maximum number of rows.
- --cell-size WxH The cell size in pixels.
- -m METHOD The uploading method, may be 'file', 'direct' or 'auto'.
- --speed SPEED The multiplier for the animation speed (float).
-"
-
-# Exit the script on keyboard interrupt
-trap "echo 'icat-mini was interrupted' >&2; exit 1" INT
-
-cols=""
-rows=""
-file=""
-tty="/dev/tty"
-uploading_method="auto"
-cell_size=""
-scale=1
-max_cols=""
-max_rows=""
-speed=""
-
-# Parse the command line.
-while [ $# -gt 0 ]; do
- case "$1" in
- -c|--columns|--cols)
- cols="$2"
- shift 2
- ;;
- -r|--rows|-l|--lines)
- rows="$2"
- shift 2
- ;;
- -s|--scale)
- scale="$2"
- shift 2
- ;;
- -h|--help)
- echo "$short_help"
- exit 0
- ;;
- -m|--upload-method|--uploading-method)
- uploading_method="$2"
- shift 2
- ;;
- --cell-size)
- cell_size="$2"
- shift 2
- ;;
- --max-cols)
- max_cols="$2"
- shift 2
- ;;
- --max-rows)
- max_rows="$2"
- shift 2
- ;;
- --speed)
- speed="$2"
- shift 2
- ;;
- --)
- file="$2"
- shift 2
- ;;
- -*)
- echo "Unknown option: $1" >&2
- exit 1
- ;;
- *)
- if [ -n "$file" ]; then
- echo "Multiple image files are not supported: $file and $1" >&2
- exit 1
- fi
- file="$1"
- shift
- ;;
- esac
-done
-
-file="$(realpath "$file")"
-
-#####################################################################
-# Adjust the terminal state
-#####################################################################
-
-stty_orig="$(stty -g < "$tty")"
-stty -echo < "$tty"
-# Disable ctrl-z. Pressing ctrl-z during image uploading may cause some
-# horrible issues otherwise.
-stty susp undef < "$tty"
-stty -icanon < "$tty"
-
-restore_echo() {
- [ -n "$stty_orig" ] || return
- stty $stty_orig < "$tty"
-}
-
-trap restore_echo EXIT TERM
-
-#####################################################################
-# Detect imagemagick
-#####################################################################
-
-# If there is the 'magick' command, use it instead of separate 'convert' and
-# 'identify' commands.
-if command -v magick > /dev/null; then
- identify="magick identify"
- convert="magick"
-else
- identify="identify"
- convert="convert"
-fi
-
-#####################################################################
-# Detect tmux
-#####################################################################
-
-# Check if we are inside tmux.
-inside_tmux=""
-if [ -n "$TMUX" ]; then
- case "$TERM" in
- *tmux*|*screen*)
- inside_tmux=1
- ;;
- esac
-fi
-
-#####################################################################
-# Compute the number of rows and columns
-#####################################################################
-
-is_pos_int() {
- if [ -z "$1" ]; then
- return 1 # false
- fi
- if [ -z "$(printf '%s' "$1" | tr -d '[:digit:]')" ]; then
- if [ "$1" -gt 0 ]; then
- return 0 # true
- fi
- fi
- return 1 # false
-}
-
-if [ -n "$cols" ] || [ -n "$rows" ]; then
- if [ -n "$max_cols" ] || [ -n "$max_rows" ]; then
- echo "You can't specify both max-cols/rows and cols/rows" >&2
- exit 1
- fi
-fi
-
-# Get the max number of cols and rows.
-[ -n "$max_cols" ] || max_cols="$(tput cols)"
-[ -n "$max_rows" ] || max_rows="$(tput lines)"
-if [ "$max_rows" -gt 255 ]; then
- max_rows=255
-fi
-
-python_ioctl_command="import array, fcntl, termios
-buf = array.array('H', [0, 0, 0, 0])
-fcntl.ioctl(0, termios.TIOCGWINSZ, buf)
-print(int(buf[2]/buf[1]), int(buf[3]/buf[0]))"
-
-# Get the cell size in pixels if either cols or rows are not specified.
-if [ -z "$cols" ] || [ -z "$rows" ]; then
- cell_width=""
- cell_height=""
- # If the cell size is specified, use it.
- if [ -n "$cell_size" ]; then
- cell_width="${cell_size%x*}"
- cell_height="${cell_size#*x}"
- if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
- echo "Invalid cell size: $cell_size" >&2
- exit 1
- fi
- fi
- # Otherwise try to use TIOCGWINSZ ioctl via python.
- if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then
- cell_size_ioctl="$(python3 -c "$python_ioctl_command" < "$tty" 2> /dev/null)"
- cell_width="${cell_size_ioctl% *}"
- cell_height="${cell_size_ioctl#* }"
- if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
- cell_width=""
- cell_height=""
- fi
- fi
- # If it didn't work, try to use csi XTWINOPS.
- if [ -z "$cell_width" ] || [ -z "$cell_height" ]; then
- if [ -n "$inside_tmux" ]; then
- printf '\ePtmux;\e\e[16t\e\\' >> "$tty"
- else
- printf '\e[16t' >> "$tty"
- fi
- # The expected response will look like ^[[6;<height>;<width>t
- term_response=""
- while true; do
- char=$(dd bs=1 count=1 <"$tty" 2>/dev/null)
- if [ "$char" = "t" ]; then
- break
- fi
- term_response="$term_response$char"
- done
- cell_height="$(printf '%s' "$term_response" | cut -d ';' -f 2)"
- cell_width="$(printf '%s' "$term_response" | cut -d ';' -f 3)"
- if ! is_pos_int "$cell_height" || ! is_pos_int "$cell_width"; then
- cell_width=8
- cell_height=16
- fi
- fi
-fi
-
-# Compute a formula with bc and round to the nearest integer.
-bc_round() {
- LC_NUMERIC=C printf '%.0f' "$(printf '%s\n' "scale=2;($1) + 0.5" | bc)"
-}
-
-# Compute the number of rows and columns of the image.
-if [ -z "$cols" ] || [ -z "$rows" ]; then
- # Get the size of the image and its resolution. If it's an animation, use
- # the first frame.
- format_output="$($identify -format '%w %h\n' "$file" | head -1)"
- img_width="$(printf '%s' "$format_output" | cut -d ' ' -f 1)"
- img_height="$(printf '%s' "$format_output" | cut -d ' ' -f 2)"
- if ! is_pos_int "$img_width" || ! is_pos_int "$img_height"; then
- echo "Couldn't get image size from identify: $format_output" >&2
- echo >&2
- exit 1
- fi
- opt_cols_expr="(${scale}*${img_width}/${cell_width})"
- opt_rows_expr="(${scale}*${img_height}/${cell_height})"
- if [ -z "$cols" ] && [ -z "$rows" ]; then
- # If columns and rows are not specified, compute the optimal values
- # using the information about rows and columns per inch.
- cols="$(bc_round "$opt_cols_expr")"
- rows="$(bc_round "$opt_rows_expr")"
- # Make sure that automatically computed rows and columns are within some
- # sane limits
- if [ "$cols" -gt "$max_cols" ]; then
- rows="$(bc_round "$rows * $max_cols / $cols")"
- cols="$max_cols"
- fi
- if [ "$rows" -gt "$max_rows" ]; then
- cols="$(bc_round "$cols * $max_rows / $rows")"
- rows="$max_rows"
- fi
- elif [ -z "$cols" ]; then
- # If only one dimension is specified, compute the other one to match the
- # aspect ratio as close as possible.
- cols="$(bc_round "${opt_cols_expr}*${rows}/${opt_rows_expr}")"
- elif [ -z "$rows" ]; then
- rows="$(bc_round "${opt_rows_expr}*${cols}/${opt_cols_expr}")"
- fi
-
- if [ "$cols" -lt 1 ]; then
- cols=1
- fi
- if [ "$rows" -lt 1 ]; then
- rows=1
- fi
-fi
-
-#####################################################################
-# Generate an image id
-#####################################################################
-
-image_id=""
-while [ -z "$image_id" ]; do
- image_id="$(shuf -i 16777217-4294967295 -n 1)"
- # Check that the id requires 24-bit fg colors.
- if [ "$(expr \( "$image_id" / 256 \) % 65536)" -eq 0 ]; then
- image_id=""
- fi
-done
-
-#####################################################################
-# Uploading the image
-#####################################################################
-
-# Choose the uploading method
-if [ "$uploading_method" = "auto" ]; then
- if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] || [ -n "$SSH_CONNECTION" ]; then
- uploading_method="direct"
- else
- uploading_method="file"
- fi
-fi
-
-# Functions to emit the start and the end of a graphics command.
-if [ -n "$inside_tmux" ]; then
- # If we are in tmux we have to wrap the command in Ptmux.
- graphics_command_start='\ePtmux;\e\e_G'
- graphics_command_end='\e\e\\\e\\'
-else
- graphics_command_start='\e_G'
- graphics_command_end='\e\\'
-fi
-
-start_gr_command() {
- printf "$graphics_command_start" >> "$tty"
-}
-end_gr_command() {
- printf "$graphics_command_end" >> "$tty"
-}
-
-# Send a graphics command with the correct start and end
-gr_command() {
- start_gr_command
- printf '%s' "$1" >> "$tty"
- end_gr_command
-}
-
-# Send an uploading command. Usage: gr_upload <action> <command> <file>
-# Where <action> is a part of command that specifies the action, it will be
-# repeated for every chunk (if the method is direct), and <command> is the rest
-# of the command that specifies the image parameters. <action> and <command>
-# must not include the transmission method or ';'.
-# Example:
-# gr_upload "a=T,q=2" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file"
-gr_upload() {
- arg_action="$1"
- arg_command="$2"
- arg_file="$3"
- if [ "$uploading_method" = "file" ]; then
- # base64-encode the filename
- encoded_filename=$(printf '%s' "$arg_file" | base64 -w0)
- gr_command "${arg_action},${arg_command},t=f;${encoded_filename}"
- fi
- if [ "$uploading_method" = "direct" ]; then
- # Create a temporary directory to store the chunked image.
- chunkdir="$(mktemp -d)"
- if [ ! "$chunkdir" ] || [ ! -d "$chunkdir" ]; then
- echo "Can't create a temp dir" >&2
- exit 1
- fi
- # base64-encode the file and split it into chunks. The size of each
- # graphics command shouldn't be more than 4096, so we set the size of an
- # encoded chunk to be 3968, slightly less than that.
- chunk_size=3968
- cat "$arg_file" | base64 -w0 | split -b "$chunk_size" - "$chunkdir/chunk_"
-
- # Issue a command indicating that we want to start data transmission for
- # a new image.
- gr_command "${arg_action},${arg_command},t=d,m=1"
-
- # Transmit chunks.
- for chunk in "$chunkdir/chunk_"*; do
- start_gr_command
- printf '%s' "${arg_action},i=${image_id},m=1;" >> "$tty"
- cat "$chunk" >> "$tty"
- end_gr_command
- rm "$chunk"
- done
-
- # Tell the terminal that we are done.
- gr_command "${arg_action},i=$image_id,m=0"
-
- # Remove the temporary directory.
- rmdir "$chunkdir"
- fi
-}
-
-delayed_frame_dir_cleanup() {
- arg_frame_dir="$1"
- sleep 2
- if [ -n "$arg_frame_dir" ]; then
- for frame in "$arg_frame_dir"/frame_*.png; do
- rm "$frame"
- done
- rmdir "$arg_frame_dir"
- fi
-}
-
-upload_image_and_print_placeholder() {
- # Check if the file is an animation.
- frame_count=$($identify -format '%n\n' "$file" | head -n 1)
- if [ "$frame_count" -gt 1 ]; then
- # The file is an animation, decompose into frames and upload each frame.
- frame_dir="$(mktemp -d)"
- frame_dir="$HOME/temp/frames${frame_dir}"
- mkdir -p "$frame_dir"
- if [ ! "$frame_dir" ] || [ ! -d "$frame_dir" ]; then
- echo "Can't create a temp dir for frames" >&2
- exit 1
- fi
-
- # Decompose the animation into separate frames.
- $convert "$file" -coalesce "$frame_dir/frame_%06d.png"
-
- # Get all frame delays at once, in centiseconds, as a space-separated
- # string.
- delays=$($identify -format "%T " "$file")
-
- frame_number=1
- for frame in "$frame_dir"/frame_*.png; do
- # Read the delay for the current frame and convert it from
- # centiseconds to milliseconds.
- delay=$(printf '%s' "$delays" | cut -d ' ' -f "$frame_number")
- delay=$((delay * 10))
- # If the delay is 0, set it to 100ms.
- if [ "$delay" -eq 0 ]; then
- delay=100
- fi
-
- if [ -n "$speed" ]; then
- delay=$(bc_round "$delay / $speed")
- fi
-
- if [ "$frame_number" -eq 1 ]; then
- # Upload the first frame with a=T
- gr_upload "q=2,a=T" "f=100,U=1,i=${image_id},c=${cols},r=${rows}" "$frame"
- # Set the delay for the first frame and also play the animation
- # in loading mode (s=2).
- gr_command "a=a,v=1,s=2,r=${frame_number},z=${delay},i=${image_id}"
- # Print the placeholder after the first frame to reduce the wait
- # time.
- print_placeholder
- else
- # Upload subsequent frames with a=f
- gr_upload "q=2,a=f" "f=100,i=${image_id},z=${delay}" "$frame"
- fi
-
- frame_number=$((frame_number + 1))
- done
-
- # Play the animation in loop mode (s=3).
- gr_command "a=a,v=1,s=3,i=${image_id}"
-
- # Remove the temporary directory, but do it in the background with a
- # delay to avoid removing files before they are loaded by the terminal.
- delayed_frame_dir_cleanup "$frame_dir" 2> /dev/null &
- else
- # The file is not an animation, upload it directly
- gr_upload "q=2,a=T" "U=1,i=${image_id},f=100,c=${cols},r=${rows}" "$file"
- # Print the placeholder
- print_placeholder
- fi
-}
-
-#####################################################################
-# Printing the image placeholder
-#####################################################################
-
-print_placeholder() {
- # Each line starts with the escape sequence to set the foreground color to
- # the image id.
- blue="$(expr "$image_id" % 256 )"
- green="$(expr \( "$image_id" / 256 \) % 256 )"
- red="$(expr \( "$image_id" / 65536 \) % 256 )"
- line_start="$(printf "\e[38;2;%d;%d;%dm" "$red" "$green" "$blue")"
- line_end="$(printf "\e[39;m")"
-
- id4th="$(expr \( "$image_id" / 16777216 \) % 256 )"
- eval "id_diacritic=\$d${id4th}"
-
- # Reset the brush state, mostly to reset the underline color.
- printf "\e[0m"
-
- # Fill the output with characters representing the image
- for y in $(seq 0 "$(expr "$rows" - 1)"); do
- eval "row_diacritic=\$d${y}"
- printf '%s' "$line_start"
- for x in $(seq 0 "$(expr "$cols" - 1)"); do
- eval "col_diacritic=\$d${x}"
- # Note that when $x is out of bounds, the column diacritic will
- # be empty, meaning that the column should be guessed by the
- # terminal.
- if [ "$x" -ge "$num_diacritics" ]; then
- printf '%s' "${placeholder}${row_diacritic}"
- else
- printf '%s' "${placeholder}${row_diacritic}${col_diacritic}${id_diacritic}"
- fi
- done
- printf '%s\n' "$line_end"
- done
-
- printf "\e[0m"
-}
-
-d0="̅"
-d1="̍"
-d2="̎"
-d3="̐"
-d4="̒"
-d5="̽"
-d6="̾"
-d7="̿"
-d8="͆"
-d9="͊"
-d10="͋"
-d11="͌"
-d12="͐"
-d13="͑"
-d14="͒"
-d15="͗"
-d16="͛"
-d17="ͣ"
-d18="ͤ"
-d19="ͥ"
-d20="ͦ"
-d21="ͧ"
-d22="ͨ"
-d23="ͩ"
-d24="ͪ"
-d25="ͫ"
-d26="ͬ"
-d27="ͭ"
-d28="ͮ"
-d29="ͯ"
-d30="҃"
-d31="҄"
-d32="҅"
-d33="҆"
-d34="҇"
-d35="֒"
-d36="֓"
-d37="֔"
-d38="֕"
-d39="֗"
-d40="֘"
-d41="֙"
-d42="֜"
-d43="֝"
-d44="֞"
-d45="֟"
-d46="֠"
-d47="֡"
-d48="֨"
-d49="֩"
-d50="֫"
-d51="֬"
-d52="֯"
-d53="ׄ"
-d54="ؐ"
-d55="ؑ"
-d56="ؒ"
-d57="ؓ"
-d58="ؔ"
-d59="ؕ"
-d60="ؖ"
-d61="ؗ"
-d62="ٗ"
-d63="٘"
-d64="ٙ"
-d65="ٚ"
-d66="ٛ"
-d67="ٝ"
-d68="ٞ"
-d69="ۖ"
-d70="ۗ"
-d71="ۘ"
-d72="ۙ"
-d73="ۚ"
-d74="ۛ"
-d75="ۜ"
-d76="۟"
-d77="۠"
-d78="ۡ"
-d79="ۢ"
-d80="ۤ"
-d81="ۧ"
-d82="ۨ"
-d83="۫"
-d84="۬"
-d85="ܰ"
-d86="ܲ"
-d87="ܳ"
-d88="ܵ"
-d89="ܶ"
-d90="ܺ"
-d91="ܽ"
-d92="ܿ"
-d93="݀"
-d94="݁"
-d95="݃"
-d96="݅"
-d97="݇"
-d98="݉"
-d99="݊"
-d100="߫"
-d101="߬"
-d102="߭"
-d103="߮"
-d104="߯"
-d105="߰"
-d106="߱"
-d107="߳"
-d108="ࠖ"
-d109="ࠗ"
-d110="࠘"
-d111="࠙"
-d112="ࠛ"
-d113="ࠜ"
-d114="ࠝ"
-d115="ࠞ"
-d116="ࠟ"
-d117="ࠠ"
-d118="ࠡ"
-d119="ࠢ"
-d120="ࠣ"
-d121="ࠥ"
-d122="ࠦ"
-d123="ࠧ"
-d124="ࠩ"
-d125="ࠪ"
-d126="ࠫ"
-d127="ࠬ"
-d128="࠭"
-d129="॑"
-d130="॓"
-d131="॔"
-d132="ྂ"
-d133="ྃ"
-d134="྆"
-d135="྇"
-d136="፝"
-d137="፞"
-d138="፟"
-d139="៝"
-d140="᤺"
-d141="ᨗ"
-d142="᩵"
-d143="᩶"
-d144="᩷"
-d145="᩸"
-d146="᩹"
-d147="᩺"
-d148="᩻"
-d149="᩼"
-d150="᭫"
-d151="᭭"
-d152="᭮"
-d153="᭯"
-d154="᭰"
-d155="᭱"
-d156="᭲"
-d157="᭳"
-d158="᳐"
-d159="᳑"
-d160="᳒"
-d161="᳚"
-d162="᳛"
-d163="᳠"
-d164="᷀"
-d165="᷁"
-d166="᷃"
-d167="᷄"
-d168="᷅"
-d169="᷆"
-d170="᷇"
-d171="᷈"
-d172="᷉"
-d173="᷋"
-d174="᷌"
-d175="᷑"
-d176="᷒"
-d177="ᷓ"
-d178="ᷔ"
-d179="ᷕ"
-d180="ᷖ"
-d181="ᷗ"
-d182="ᷘ"
-d183="ᷙ"
-d184="ᷚ"
-d185="ᷛ"
-d186="ᷜ"
-d187="ᷝ"
-d188="ᷞ"
-d189="ᷟ"
-d190="ᷠ"
-d191="ᷡ"
-d192="ᷢ"
-d193="ᷣ"
-d194="ᷤ"
-d195="ᷥ"
-d196="ᷦ"
-d197="᷾"
-d198="⃐"
-d199="⃑"
-d200="⃔"
-d201="⃕"
-d202="⃖"
-d203="⃗"
-d204="⃛"
-d205="⃜"
-d206="⃡"
-d207="⃧"
-d208="⃩"
-d209="⃰"
-d210="⳯"
-d211="⳰"
-d212="⳱"
-d213="ⷠ"
-d214="ⷡ"
-d215="ⷢ"
-d216="ⷣ"
-d217="ⷤ"
-d218="ⷥ"
-d219="ⷦ"
-d220="ⷧ"
-d221="ⷨ"
-d222="ⷩ"
-d223="ⷪ"
-d224="ⷫ"
-d225="ⷬ"
-d226="ⷭ"
-d227="ⷮ"
-d228="ⷯ"
-d229="ⷰ"
-d230="ⷱ"
-d231="ⷲ"
-d232="ⷳ"
-d233="ⷴ"
-d234="ⷵ"
-d235="ⷶ"
-d236="ⷷ"
-d237="ⷸ"
-d238="ⷹ"
-d239="ⷺ"
-d240="ⷻ"
-d241="ⷼ"
-d242="ⷽ"
-d243="ⷾ"
-d244="ⷿ"
-d245="꙯"
-d246="꙼"
-d247="꙽"
-d248="꛰"
-d249="꛱"
-d250="꣠"
-d251="꣡"
-d252="꣢"
-d253="꣣"
-d254="꣤"
-d255="꣥"
-d256="꣦"
-d257="꣧"
-d258="꣨"
-d259="꣩"
-d260="꣪"
-d261="꣫"
-d262="꣬"
-d263="꣭"
-d264="꣮"
-d265="꣯"
-d266="꣰"
-d267="꣱"
-d268="ꪰ"
-d269="ꪲ"
-d270="ꪳ"
-d271="ꪷ"
-d272="ꪸ"
-d273="ꪾ"
-d274="꪿"
-d275="꫁"
-d276="︠"
-d277="︡"
-d278="︢"
-d279="︣"
-d280="︤"
-d281="︥"
-d282="︦"
-d283="𐨏"
-d284="𐨸"
-d285="𝆅"
-d286="𝆆"
-d287="𝆇"
-d288="𝆈"
-d289="𝆉"
-d290="𝆪"
-d291="𝆫"
-d292="𝆬"
-d293="𝆭"
-d294="𝉂"
-d295="𝉃"
-d296="𝉄"
-
-num_diacritics="297"
-
-placeholder="􎻮"
-
-#####################################################################
-# Upload the image and print the placeholder
-#####################################################################
-
-upload_image_and_print_placeholder