#!/bin/bash BASH_ARGV0=write-tty echo -n "$0" >/proc/$BASHPID/comm output_filter() { tokenize | colorize | soft_cursor } chr() { declare -i n="$*" printf "$(printf '\%o' "$n")" } colorize() { BASH_ARGV0=colorize echo -n "$0" >/proc/$BASHPID/comm while read -r do case "$REPLY" in \\[0-7][0-7][0-7] ) declare -i c=8#"${REPLY#?}" ;; \\U[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] ) declare -i c=16#"${REPLY#??}" ;; * ) printf '0 %s\n' "$REPLY" continue ;; esac if (( c > 128 + 127 )) then : elif (( c > 128 + 32 )) then REPLY=M-$(chr c - 128) elif (( c > 127 )) then REPLY=M-^$(chr c - 128 + 64) elif (( c < 32 )) then REPLY=^$(chr c + 64) fi printf '106 %s\n' "$REPLY" done } tokenize() { BASH_ARGV0=tokenize echo -n "$0" >/proc/$BASHPID/comm while read -r -n1 -d '' do if [[ "$REPLY" =~ [[:print:]] ]] then # Output one printable character per line. It may be a # multibyte unicode character. printf '%s\n' "$REPLY" continue elif [ "$REPLY" ] then # If it is a non-printable, then we output a # multi-character line. In this case we colorize it # later so that it won't be confused with multiple # printable characters. bytelen=$(LC_ALL=C; echo ${#REPLY}) if (( bytelen == 1 )) then printf '\\%.3o\n' "'$REPLY" else printf '\\U%.8x\n' "'$REPLY" fi else printf '\\%.3o\n' 0 fi done } padding() { for ((i=0; i<$1; ++i)) do echo -n ' ' done for ((i=0; i<$1; ++i)) do echo -en '\b' done } soft_cursor() { BASH_ARGV0=soft_cursor echo -n "$0" >/proc/$BASHPID/comm FMT=$'\e[m %s\b%s\e[%sm \b\e[m' REPLY= declare -i replylen=0 replycolor promptcolor=105 while printf "$FMT" "$(padding $replylen)" "$REPLY" "$promptcolor" do read -r replycolor REPLY || break replylen=${#REPLY} if (( $replycolor > 0 )) then printf -v REPLY '\e[%sm%s\e[m' "$replycolor" "$REPLY" fi done printf ' \b\n' } output_filter