From 2a61134e2fb5d6fdd904484df1bf74ec24df0148 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Sun, 16 Apr 2023 07:47:27 -0500 Subject: [PATCH] some fun iterm2 drawing (#449) --- imaging/README.md | 4 ++ imaging/divider.nu | 8 +++ imaging/divider.sh | 9 +++ imaging/imgcat.nu | 91 ++++++++++++++++++++++++++ imaging/imgcat.sh | 157 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 269 insertions(+) create mode 100644 imaging/README.md create mode 100644 imaging/divider.nu create mode 100755 imaging/divider.sh create mode 100644 imaging/imgcat.nu create mode 100755 imaging/imgcat.sh diff --git a/imaging/README.md b/imaging/README.md new file mode 100644 index 0000000..40bc0ec --- /dev/null +++ b/imaging/README.md @@ -0,0 +1,4 @@ +These nushell scripts are semi-clones of the shell scripts in the same folder. They work with iterm2 on MacOS and maybe other shells. + +- divider.nu will print a thick divider line for us with a nushell hook +- imgcat.nu will print a png image to the terminal screen \ No newline at end of file diff --git a/imaging/divider.nu b/imaging/divider.nu new file mode 100644 index 0000000..713bd51 --- /dev/null +++ b/imaging/divider.nu @@ -0,0 +1,8 @@ +def divider [] { + let a = "\e]1337;File=inline=1;width=100%%;height=1;preserveAspectRatio=0" + let b = ":" + # this is just a 1x1 white png image + let c = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/RIOikRRaiFgsEkVEISiIpcbCJkiICkZtknWTCNl12U0QsRVsLAQL0cZX4T/QVrBVEARFELHyB/hqJKx3jJAgySyz9+PMnMvMGfDH8rrpNkbAtApOYiqqzScXtKZXAoQIMkBPSnftiXg8Rt3xdY9P1bsh1av+vpqjddlwdfA1C4/qtlMQHheOrRVsxdvCHXoutSx8JDzoyAGFr5WeLvOL4myZPxQ7s4lJ8KueWraK01Ws5xxTuF84bOaL+t951E2ChjU3I7VLZjcuCaaIopGmyAp5CgxJtSSz2r7Ir2+aVfHo8rdZxxFHlpx4B0UtSldDakZ0Q7486yr3/3m6mZHhcvdgFALPnvfeC027UNrxvO9jzyudQMMTXFoV/6rkNPYp+k5FCx9CaBPOrypaeg8utqDz0U45qV+pQaY/k4G3M2hLQvsttCyWs/pb5/QBZjfkiW5g/wD6ZH9o6Qf3IWgGVlxmOAAAAANQTFRF////p8QbyAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAAApJREFUCFtjYAAAAAIAAWJAT2gAAAAASUVORK5CYII=' + let d = "\a" + [ $a $b $c $d ] | str join +} \ No newline at end of file diff --git a/imaging/divider.sh b/imaging/divider.sh new file mode 100755 index 0000000..b980355 --- /dev/null +++ b/imaging/divider.sh @@ -0,0 +1,9 @@ +#!/bin/bash +if [ $# -eq 0 ]; then + echo "Usage: divider file" + exit 1 +fi +printf '\033]1337;File=inline=1;width=100%%;height=1;preserveAspectRatio=0' +printf ":" +base64 < "$1" +printf '\a\n' diff --git a/imaging/imgcat.nu b/imaging/imgcat.nu new file mode 100644 index 0000000..a503ad4 --- /dev/null +++ b/imaging/imgcat.nu @@ -0,0 +1,91 @@ +# https://iterm2.com/documentation-images.html + +def print_osc [] { + if $env.TERM == screen* { + "\ePtmux;\e\e]" + } else { + "\e]" + } +} + +def print_st [] { + if $env.TERM == screen* { + "\a\e\\" + } else { + "\a" + } +} + +def-env b64_encode [fn] { + open $fn | encode base64 +} + +def-env b64_decode [fn] { + $fn | decode base64 -b +} + +def print_image [ + filename # Filename to convey to client + inline # 0 or 1 + base64contents # Base64-encoded contents + print_filename # If non-empty, print the filename before outputting the image +] { + let a = (print_osc) + let b = "1337;File=" + let c = (if ($filename | length) > 0 { + let b64_enc_data = (b64_encode $filename) + $"name=($b64_enc_data);" + }) + let b64_dec_data = (b64_decode $base64contents) + let d = $"size=($b64_dec_data | bytes length)" + let e = $";inline=($inline)" + let f = ":" + let g = $base64contents + let h = print_st + let i = "\n" + let j = (if ($print_filename | length) > 0 { + print -n $filename + }) + + [ $a $b $c $d $e $f $g $h $i $j ] | str join +} + +def error [] { + print "Error: ($env.LAST_EXIT_CODE)" +} + +def show_help [] { + print "Usage: imgcat [-p] filename ..." + print " or: cat filename | imgcat" +} + +# imgcat.nu shows images in your terminal if your terminal supports it +def imgcat [ + --help(-h) # Help/Usage message + --print(-p) # Print filename + --url(-u) # Use a URL + filename # The filename to show +] { + if $help { + show_help + } + + let print_filename = ( + if $print { + 1 + } + ) + + let url_img = ( + if $url { + let encoded_image = (b64_encode (http get $url)) + print_image $url 1 $encoded_image $print_filename + } + ) + + if ($filename | path exists) { + print_image $filename 1 (b64_encode $filename) $print_filename + } else { + print $"imgcat: ($filename): No such file or directory" + } +} \ No newline at end of file diff --git a/imaging/imgcat.sh b/imaging/imgcat.sh new file mode 100755 index 0000000..bb007af --- /dev/null +++ b/imaging/imgcat.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux; +# ST, and for all ESCs in to be replaced with ESC ESC. It +# only accepts ESC backslash for ST. We use TERM instead of TMUX because TERM +# gets passed through ssh. +function print_osc() { + if [[ $TERM == screen* ]]; then + printf "\033Ptmux;\033\033]" + else + printf "\033]" + fi +} + +# More of the tmux workaround described above. +function print_st() { + if [[ $TERM == screen* ]]; then + printf "\a\033\\" + else + printf "\a" + fi +} + +function load_version() { + if [ -z ${IMGCAT_BASE64_VERSION+x} ]; then + IMGCAT_BASE64_VERSION=$(base64 --version 2>&1) + export IMGCAT_BASE64_VERSION + fi +} + +function b64_encode() { + load_version + if [[ $IMGCAT_BASE64_VERSION =~ GNU ]]; then + # Disable line wrap + base64 -w0 + else + base64 + fi +} + +function b64_decode() { + load_version + if [[ $IMGCAT_BASE64_VERSION =~ fourmilab ]]; then + BASE64ARG=-d + elif [[ $IMGCAT_BASE64_VERSION =~ GNU ]]; then + BASE64ARG=-di + else + BASE64ARG=-D + fi + base64 $BASE64ARG +} + +# print_image filename inline base64contents print_filename +# filename: Filename to convey to client +# inline: 0 or 1 +# base64contents: Base64-encoded contents +# print_filename: If non-empty, print the filename +# before outputting the image +function print_image() { + print_osc + printf '1337;File=' + if [[ -n $1 ]]; then + printf "name=%s;" "$(printf "%s" "$1" | b64_encode)" + fi + + printf "%s" "$3" | b64_decode | wc -c | awk '{printf "size=%d",$1}' + printf ";inline=%s" "$2" + printf ":" + printf "%s" "$3" + print_st + printf '\n' + if [[ -n $4 ]]; then + echo "$1" + fi +} + +function error() { + echo "ERROR: $*" 1>&2 +} + +function show_help() { + echo "Usage: imgcat [-p] filename ..." 1>&2 + echo " or: cat filename | imgcat" 1>&2 +} + +function check_dependency() { + if ! (builtin command -V "$1" >/dev/null 2>&1); then + echo "imgcat: missing dependency: can't find $1" 1>&2 + exit 1 + fi +} + +## Main + +if [ -t 0 ]; then + has_stdin=f +else + has_stdin=t +fi + +# Show help if no arguments and no stdin. +if [ $has_stdin = f ] && [ $# -eq 0 ]; then + show_help + exit +fi + +check_dependency awk +check_dependency base64 +check_dependency wc + +# Look for command line flags. +while [ $# -gt 0 ]; do + case "$1" in + -h | --h | --help) + show_help + exit + ;; + -p | --p | --print) + print_filename=1 + ;; + -u | --u | --url) + check_dependency curl + encoded_image=$(curl -s "$2" | b64_encode) || ( + error "No such file or url $2" + exit 2 + ) + has_stdin=f + print_image "$2" 1 "$encoded_image" "$print_filename" + set -- "${@:1:1}" "-u" "${@:3}" + if [ "$#" -eq 2 ]; then + exit + fi + ;; + -*) + error "Unknown option flag: $1" + show_help + exit 1 + ;; + *) + if [ -r "$1" ]; then + has_stdin=f + print_image "$1" 1 "$(b64_encode <"$1")" "$print_filename" + else + error "imgcat: $1: No such file or directory" + exit 2 + fi + ;; + esac + shift +done + +# Read and print stdin +if [ $has_stdin = t ]; then + print_image "" 1 "$(cat | b64_encode)" "" +fi + +exit 0 \ No newline at end of file