update
This commit is contained in:
209
.iterm2/imgcat
209
.iterm2/imgcat
@@ -1,10 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST. We use TERM instead of TMUX because TERM
|
||||||
|
# gets passed through ssh.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]]; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -13,53 +16,131 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]]; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# print_image filename inline base64contents print_filename
|
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 width height preserve_aspect_ratio
|
||||||
# filename: Filename to convey to client
|
# filename: Filename to convey to client
|
||||||
# inline: 0 or 1
|
# inline: 0 or 1, if set to 1, the file will be displayed inline, otherwise, it will be downloaded
|
||||||
# base64contents: Base64-encoded contents
|
# base64contents: Base64-encoded contents
|
||||||
# print_filename: If non-empty, print the filename
|
# print_filename: 0 or 1, if set to 1, print the filename after outputting the image
|
||||||
# before outputting the image
|
# width: set output width of the image in character cells, pixels or percent
|
||||||
|
# height: set output height of the image in character cells, pixels or percent
|
||||||
|
# preserve_aspect_ratio: 0 or 1, if set to 1, fill the specified width and height as much as possible without stretching the image
|
||||||
|
# file: Empty string or file type like "application/json" or ".js".
|
||||||
function print_image() {
|
function print_image() {
|
||||||
print_osc
|
print_osc
|
||||||
printf '1337;File='
|
printf "1337;File=inline=%s" "$2"
|
||||||
if [[ -n "$1" ]]; then
|
printf ";size=%d" $(printf "%s" "$3" | b64_decode | wc -c)
|
||||||
printf 'name='`printf "%s" "$1" | base64`";"
|
[ -n "$1" ] && printf ";name=%s" "$(printf "%s" "$1" | b64_encode)"
|
||||||
fi
|
[ -n "$5" ] && printf ";width=%s" "$5"
|
||||||
|
[ -n "$6" ] && printf ";height=%s" "$6"
|
||||||
VERSION=$(base64 --version 2>&1)
|
[ -n "$7" ] && printf ";preserveAspectRatio=%s" "$7"
|
||||||
if [[ "$VERSION" =~ fourmilab ]]; then
|
[ -n "$8" ] && printf ";type=%s" "$8"
|
||||||
BASE64ARG=-d
|
printf ":%s" "$3"
|
||||||
elif [[ "$VERSION" =~ GNU ]]; then
|
|
||||||
BASE64ARG=-di
|
|
||||||
else
|
|
||||||
BASE64ARG=-D
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "%s" "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}'
|
|
||||||
printf ";inline=$2"
|
|
||||||
printf ":"
|
|
||||||
printf "%s" "$3"
|
|
||||||
print_st
|
print_st
|
||||||
printf '\n'
|
printf '\n'
|
||||||
if [[ -n "$4" ]]; then
|
[ "$4" == "1" ] && echo "$1"
|
||||||
echo $1
|
has_image_displayed=t
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function error() {
|
function error() {
|
||||||
echo "ERROR: $*" 1>&2
|
errcho "ERROR: $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function errcho() {
|
||||||
|
echo "$@" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
function show_help() {
|
function show_help() {
|
||||||
echo "Usage: imgcat [-p] filename ..." 1>& 2
|
errcho
|
||||||
echo " or: cat filename | imgcat" 1>& 2
|
errcho "Usage: imgcat [-p] [-n] [-W width] [-H height] [-r] [-s] [-u] [-t file-type] [-f] filename ..."
|
||||||
|
errcho " cat filename | imgcat [-W width] [-H height] [-r] [-s]"
|
||||||
|
errcho
|
||||||
|
errcho "Display images inline in the iTerm2 using Inline Images Protocol"
|
||||||
|
errcho
|
||||||
|
errcho "Options:"
|
||||||
|
errcho
|
||||||
|
errcho " -h, --help Display help message"
|
||||||
|
errcho " -p, --print Enable printing of filename or URL after each image"
|
||||||
|
errcho " -n, --no-print Disable printing of filename or URL after each image"
|
||||||
|
errcho " -u, --url Interpret following filename arguments as remote URLs"
|
||||||
|
errcho " -f, --file Interpret following filename arguments as regular Files"
|
||||||
|
errcho " -t, --type file-type Provides a type hint"
|
||||||
|
errcho " -r, --preserve-aspect-ratio When scaling image preserve its original aspect ratio"
|
||||||
|
errcho " -s, --stretch Stretch image to specified width and height (this option is opposite to -r)"
|
||||||
|
errcho " -W, --width N Set image width to N character cells, pixels or percent (see below)"
|
||||||
|
errcho " -H, --height N Set image height to N character cells, pixels or percent (see below)"
|
||||||
|
errcho
|
||||||
|
errcho " If you don't specify width or height an appropriate value will be chosen automatically."
|
||||||
|
errcho " The width and height are given as word 'auto' or number N followed by a unit:"
|
||||||
|
errcho " N character cells"
|
||||||
|
errcho " Npx pixels"
|
||||||
|
errcho " N% percent of the session's width or height"
|
||||||
|
errcho " auto the image's inherent size will be used to determine an appropriate dimension"
|
||||||
|
errcho
|
||||||
|
errcho " If a type is provided, it is used as a hint to disambiguate."
|
||||||
|
errcho " The file type can be a mime type like text/markdown, a language name like Java, or a file extension like .c"
|
||||||
|
errcho " The file type can usually be inferred from the extension or its contents. -t is most useful when"
|
||||||
|
errcho " a filename is not available, such as whe input comes from a pipe."
|
||||||
|
errcho
|
||||||
|
errcho "Examples:"
|
||||||
|
errcho
|
||||||
|
errcho " $ imgcat -W 250px -H 250px -s avatar.png"
|
||||||
|
errcho " $ cat graph.png | imgcat -W 100%"
|
||||||
|
errcho " $ imgcat -p -W 500px -u http://host.tld/path/to/image.jpg -W 80 -f image.png"
|
||||||
|
errcho " $ cat url_list.txt | xargs imgcat -p -W 40 -u"
|
||||||
|
errcho " $ imgcat -t application/json config.json"
|
||||||
|
errcho
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_dependency() {
|
||||||
|
if ! (builtin command -V "$1" >/dev/null 2>&1); then
|
||||||
|
error "missing dependency: can't find $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# verify that value is in the image sizing unit format: N / Npx / N% / auto
|
||||||
|
function validate_size_unit() {
|
||||||
|
if [[ ! "$1" =~ ^(:?[0-9]+(:?px|%)?|auto)$ ]]; then
|
||||||
|
error "Invalid image sizing unit - '$1'"
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## Main
|
## Main
|
||||||
@@ -71,34 +152,76 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Show help if no arguments and no stdin.
|
# Show help if no arguments and no stdin.
|
||||||
if [ $has_stdin = f -a $# -eq 0 ]; then
|
if [ $has_stdin = f ] && [ $# -eq 0 ]; then
|
||||||
show_help
|
show_help
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
check_dependency base64
|
||||||
|
check_dependency wc
|
||||||
|
file_type=""
|
||||||
|
|
||||||
# Look for command line flags.
|
# Look for command line flags.
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--h|--help)
|
-h | --h | --help)
|
||||||
show_help
|
show_help
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
-p|--p|--print)
|
-p | --p | --print)
|
||||||
print_filename=1
|
print_filename=1
|
||||||
;;
|
;;
|
||||||
|
-n | --n | --no-print)
|
||||||
|
print_filename=0
|
||||||
|
;;
|
||||||
|
-W | --W | --width)
|
||||||
|
validate_size_unit "$2"
|
||||||
|
width="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-H | --H | --height)
|
||||||
|
validate_size_unit "$2"
|
||||||
|
height="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-r | --r | --preserve-aspect-ratio)
|
||||||
|
preserve_aspect_ratio=1
|
||||||
|
;;
|
||||||
|
-s | --s | --stretch)
|
||||||
|
preserve_aspect_ratio=0
|
||||||
|
;;
|
||||||
|
-f | --f | --file)
|
||||||
|
has_stdin=f
|
||||||
|
is_url=f
|
||||||
|
;;
|
||||||
|
-u | --u | --url)
|
||||||
|
check_dependency curl
|
||||||
|
has_stdin=f
|
||||||
|
is_url=t
|
||||||
|
;;
|
||||||
|
-t | --t | --type)
|
||||||
|
file_type="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-*)
|
-*)
|
||||||
error "Unknown option flag: $1"
|
error "Unknown option flag: $1"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [ -r "$1" ] ; then
|
if [ "$is_url" == "t" ]; then
|
||||||
has_stdin=f
|
encoded_image=$(curl -fs "$1" | b64_encode) || {
|
||||||
print_image "$1" 1 "$(base64 < "$1")" "$print_filename"
|
error "Could not retrieve image from URL $1, error_code: $?"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
elif [ -r "$1" ]; then
|
||||||
|
encoded_image=$(cat "$1" | b64_encode)
|
||||||
else
|
else
|
||||||
error "imgcat: $1: No such file or directory"
|
error "imgcat: $1: No such file or directory"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
has_stdin=f
|
||||||
|
print_image "$1" 1 "$encoded_image" "$print_filename" "$width" "$height" "$preserve_aspect_ratio" "$file_type"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
@@ -106,7 +229,13 @@ done
|
|||||||
|
|
||||||
# Read and print stdin
|
# Read and print stdin
|
||||||
if [ $has_stdin = t ]; then
|
if [ $has_stdin = t ]; then
|
||||||
print_image "" 1 "$(cat | base64)" ""
|
print_image "" 1 "$(cat | b64_encode)" 0 "$width" "$height" "$preserve_aspect_ratio" "$file_type"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$has_image_displayed" != "t" ]; then
|
||||||
|
error "No image provided. Check command line options."
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
678
.iterm2/imgls
678
.iterm2/imgls
@@ -1,68 +1,624 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/perl
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# imgls: ls(1) listing supplemented with image thumbnails and dimensions
|
||||||
# only accepts ESC backslash for ST.
|
#
|
||||||
function print_osc() {
|
# Usage: imgls [--width #] [--height #] [--[no]preserve_ratio]
|
||||||
if [ x"$TERM" = "xscreen" ] ; then
|
# [--[no]dimensions] [--[no]unknown] [ls options] [file ...]
|
||||||
printf "\033Ptmux;\033\033]"
|
#
|
||||||
else
|
# Writing an image to an iTerm window is simple. See the official documentation
|
||||||
printf "\033]"
|
# at https://iterm2.com/documentation-images.html and the write_image() function below.
|
||||||
fi
|
#
|
||||||
|
# Many of ls' options are supported, but not all. The program does not support ls'
|
||||||
|
# default -C columnar output mode - output is always one entry per line. Writing
|
||||||
|
# images across the page in columns appears to be problematic.
|
||||||
|
#
|
||||||
|
# In addition, options are available to specify setting image properties (width, height,
|
||||||
|
# preserve aspect ratio), include inline image dimensions, and disable output of
|
||||||
|
# generic icons for unsupported image types. Finally, a table-based image dimensions
|
||||||
|
# lookup mechanism is employed to obtain image dimensions. It can call on Perl
|
||||||
|
# modules such as Image::Size, or call on external programs such as sips, mdls or php.
|
||||||
|
# It is easy to add additional entries to the table. You can use the --method option
|
||||||
|
# to select any of the currently supported methods ('sips', 'mdls', 'php', and
|
||||||
|
# 'image::size'). These are tried, in that order; the first that appears to work
|
||||||
|
# is used for all.
|
||||||
|
|
||||||
|
use v5.14;
|
||||||
|
use strict;
|
||||||
|
use utf8;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use File::stat;
|
||||||
|
use IO::Select;
|
||||||
|
use IPC::Open3;
|
||||||
|
use File::Spec;
|
||||||
|
use MIME::Base64;
|
||||||
|
use File::Basename;
|
||||||
|
use Symbol 'gensym';
|
||||||
|
use Encode qw(decode);
|
||||||
|
use List::Util qw(max);
|
||||||
|
use POSIX qw(strftime floor modf);
|
||||||
|
use Getopt::Long qw(:config no_permute pass_through require_order);
|
||||||
|
|
||||||
|
STDERR->autoflush(1);
|
||||||
|
STDOUT->autoflush(1);
|
||||||
|
binmode STDOUT, ':encoding(UTF-8)';
|
||||||
|
binmode STDERR, ':encoding(UTF-8)';
|
||||||
|
|
||||||
|
my $prog = basename $0;
|
||||||
|
sub usage {
|
||||||
|
my $leader = "usage: $prog";
|
||||||
|
say STDERR
|
||||||
|
"usage: $prog",
|
||||||
|
" [--width #] [--height #] [--[no]preserve_ratio] [--[no]dimensions]",
|
||||||
|
"\n",
|
||||||
|
' ' x length($leader),
|
||||||
|
" [--[no]unknown] [ls options] [file ...]";
|
||||||
|
|
||||||
|
exit shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
# More of the tmux workaround described above.
|
# Some defaults
|
||||||
function print_st() {
|
my $def_image_width = 3; # height (in character cells)
|
||||||
if [ x"$TERM" = "xscreen" ] ; then
|
my $def_image_height = 1; # width (in character cells)
|
||||||
printf "\a\033\\"
|
my $def_preserve_ratio = 'true'; # preserve aspect ratio
|
||||||
else
|
|
||||||
printf "\a"
|
my %imgparams = ( # default image option parameters
|
||||||
fi
|
inline => 1, # image appears inline with text
|
||||||
|
height => $def_image_height, # character cells tall
|
||||||
|
width => $def_image_width, # character cells wide
|
||||||
|
preserveAspectRatio => $def_preserve_ratio, # no stretchmarks please
|
||||||
|
);
|
||||||
|
|
||||||
|
my %failed_types; # cache of file extensions that have failed
|
||||||
|
my %stat_cache; # cache of file/directory lstat() calls
|
||||||
|
my $curtime = time();
|
||||||
|
my $sixmonths = (365 / 2) * 86400;
|
||||||
|
|
||||||
|
my %opts = (
|
||||||
|
height => \$imgparams{'height'},
|
||||||
|
width => \$imgparams{'width'},
|
||||||
|
);
|
||||||
|
get_options(\%opts);
|
||||||
|
|
||||||
|
# find a method to obtain image dimensions
|
||||||
|
my $dims_methods = init_dims_methods();
|
||||||
|
my $dims_method = find_dims_methods($dims_methods);
|
||||||
|
|
||||||
|
# single pixel image for non-renderable files
|
||||||
|
my ($one_pixel_black, $one_pixel_black_len) = get_black_pixel_image();
|
||||||
|
|
||||||
|
my $do_newline;
|
||||||
|
my $dot_filter = $opts{'A'} ? qr/^\.{1,2}$/ : qr/^\./;
|
||||||
|
$dot_filter = undef if $opts{'a'};
|
||||||
|
|
||||||
|
# special: empty @ARGV, or contains only '.'
|
||||||
|
my $do_header = @ARGV > 1 ? 1 : 0;
|
||||||
|
if (@ARGV <= 1) {
|
||||||
|
push @ARGV, '.' if @ARGV == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function list_file() {
|
my (@files, @dirs);
|
||||||
fn=$1
|
for (@ARGV) {
|
||||||
dims=$(php -r 'if (!is_file($argv[1])) exit(1); $a = getimagesize($argv[1]); if ($a==FALSE) exit(1); else { echo $a[0] . "x" .$a[1]; exit(0); }' "$fn")
|
if (! -e _lstat($_)) {
|
||||||
rc=$?
|
say STDERR "$prog: $_: No such file or directory";
|
||||||
if [[ $rc == 0 ]] ; then
|
}
|
||||||
print_osc
|
elsif (-f _lstat($_)) {
|
||||||
printf '1337;File=name='`echo -n "$fn" | base64`";"
|
push @files, $_;
|
||||||
wc -c "$fn" | awk '{printf "size=%d",$1}'
|
}
|
||||||
printf ";inline=1;height=3;width=3;preserveAspectRatio=true"
|
else {
|
||||||
printf ":"
|
push @dirs, $_;
|
||||||
base64 < "$fn"
|
}
|
||||||
print_st
|
}
|
||||||
if [ x"$TERM" == "xscreen" ] ; then
|
@files = ls_sort(@files);
|
||||||
# This works in plain-old tmux but does the wrong thing in iTerm2's tmux
|
@dirs = ls_sort(@dirs);
|
||||||
# integration mode. tmux doesn't know that the cursor moves when the
|
|
||||||
# image code is sent, while iTerm2 does. I had to pick one, since
|
if ($opts{'d'}) {
|
||||||
# integration mode is undetectable, so I picked the failure mode that at
|
push @files, @dirs;
|
||||||
# least produces useful output (there is just too much whitespace in
|
@dirs = ();
|
||||||
# integration mode). This could be fixed by not moving the cursor while
|
}
|
||||||
# in integration mode. A better fix would be for tmux to interpret the
|
do_ls(undef, @files) if @files;
|
||||||
# image sequence, though.
|
|
||||||
#
|
while (@dirs) {
|
||||||
# tl;dr: If you use tmux in integration mode, replace this with the printf
|
my $path = shift @dirs;
|
||||||
# from the else clause.
|
|
||||||
printf '\033[4C\033[Bx'
|
if (! -e $path) {
|
||||||
else
|
say STDERR "$prog: $path: No such file or directory";
|
||||||
printf '\033[A'
|
next;
|
||||||
fi
|
}
|
||||||
echo -n "$dims "
|
my (@f, @d);
|
||||||
ls -ld "$fn"
|
get_dir_content($path, $dot_filter, \@f, \@d) or
|
||||||
else
|
next;
|
||||||
ls -ld "$fn"
|
do_ls($path, @f, @d);
|
||||||
fi
|
if ($opts{'R'}) {
|
||||||
|
push @dirs, grep { ! /\.\.?$/ } @d;
|
||||||
|
}
|
||||||
|
$do_newline++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
# Encodes and outputs an image file to the window
|
||||||
for fn in *
|
# arg 1: path to an image file
|
||||||
do
|
# arg 2: size, in bytes, of the image
|
||||||
list_file "$fn"
|
sub write_image {
|
||||||
done < <(ls -ls)
|
my ($file, $size) = @_;
|
||||||
else
|
my $encoded;
|
||||||
for fn in "$@"
|
|
||||||
do
|
|
||||||
list_file "$fn"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
$imgparams{'name'} = encode_base64($file, ''); # file name is base64 encoded
|
||||||
|
$imgparams{'size'} = $size; # file size in bytes
|
||||||
|
|
||||||
|
if (ref $file eq '') {
|
||||||
|
my $bytes = get_image_bytes($file);
|
||||||
|
$encoded = encode_base64($bytes) if defined $bytes;
|
||||||
|
}
|
||||||
|
if (! $encoded or ref $file eq 'SCALAR') {
|
||||||
|
$encoded = $one_pixel_black;
|
||||||
|
$imgparams{'name'} = encode_base64('one_pixel_black', '');
|
||||||
|
$imgparams{'size'} = $one_pixel_black_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "%s%s%s;File=%s:%s%s",
|
||||||
|
"\033", "]", "1337", # image leadin sequence (OSC + 1337)
|
||||||
|
join(';', map { $_ . '=' . $imgparams{$_} } keys %imgparams), # semicolon separated pairs of param=value pairs
|
||||||
|
$encoded, # base64 encoded image bytes
|
||||||
|
"\007"; # end-of-encoding char (BEL = ^G)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_options {
|
||||||
|
local $SIG{__WARN__} = sub { say "$prog: ", $_[0]; usage(1) };
|
||||||
|
Getopt::Long::Configure(qw/no_ignore_case bundling no_passthrough/);
|
||||||
|
my $result = GetOptions(\%opts,
|
||||||
|
'dimensions!' => sub { $opts{'unknown'}++; $opts{$_[0]} = $_[1] },
|
||||||
|
'height=s',
|
||||||
|
'method=s', # use to force dimensions method
|
||||||
|
"preserve_ratio!" => sub { $imgparams{'preserveAspectRatio'} = $_[1] ? 'true' : 'false' },
|
||||||
|
'unknown!' => sub { $opts{'dimensions'}++; $opts{$_[0]} = $_[1] },
|
||||||
|
'width=s',
|
||||||
|
# supported ls options
|
||||||
|
'D=s',
|
||||||
|
't' => sub { delete $opts{'S'}; $opts{'t'}++ },
|
||||||
|
'S' => sub { delete $opts{'t'}; $opts{'S'}++ },
|
||||||
|
qw/ A F R T a d h i k l n o p r s u y /, 'c|U',
|
||||||
|
);
|
||||||
|
|
||||||
|
$opts{'d'} and delete $opts{'R'};
|
||||||
|
$opts{'D'} and delete $opts{'T'};
|
||||||
|
$opts{'n'} and $opts{'l'}++;
|
||||||
|
$opts{'o'} and $opts{'l'}++;
|
||||||
|
$opts{'s'} and $opts{'show_blocks'}++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_dir_content {
|
||||||
|
my ($path, $filter, $filesref, $dirsref) = @_;
|
||||||
|
my $dh;
|
||||||
|
|
||||||
|
unless (opendir($dh, $path)) {
|
||||||
|
say STDERR "Unable to open directory $path: $!";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (readdir($dh)) {
|
||||||
|
next if defined $filter and $_ =~ /$filter/;
|
||||||
|
my $p = "$path/$_";
|
||||||
|
if (-d _lstat($p)) {
|
||||||
|
push @$dirsref, $p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push @$filesref, $p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir $dh;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub do_ls {
|
||||||
|
my $path = shift;
|
||||||
|
|
||||||
|
my $blocks_total = 0;
|
||||||
|
my (@hfiles, %widths, $st);
|
||||||
|
for my $file (ls_sort(@_)) {
|
||||||
|
#say "FILE: $file";
|
||||||
|
|
||||||
|
my %h;
|
||||||
|
$h{'file'} = $file;
|
||||||
|
$h{'filename'} = defined $path ? (split /\//, $file)[-1] : $file;
|
||||||
|
$h{'st'} = $st = _lstat($file);
|
||||||
|
$h{'ino'} = $st->ino if $opts{'i'};
|
||||||
|
$h{'bytes'} = $st->size;
|
||||||
|
$h{'bytesh'} = format_human($h{'bytes'}) if $opts{'h'};
|
||||||
|
$h{'dims'} = get_dimensions($file) if $opts{'dimensions'} and -f $st && -r $st && $h{'bytes'};
|
||||||
|
$h{'nlink'} = $st->nlink if $opts{'s'} or $opts{'l'};
|
||||||
|
|
||||||
|
if ($opts{'show_blocks'} or $opts{'l'}) {
|
||||||
|
$h{'blocks'} = $st->blocks;
|
||||||
|
if ( ! -d $st and ($opts{'a'} or $h{'filename'} !~ /^\.[^.]+/)) {
|
||||||
|
$blocks_total += $st->blocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opts{'l'}) {
|
||||||
|
$h{'lsmodes'} = Stat::lsMode::format_mode($st->mode);
|
||||||
|
$h{'owner'} = ($opts{'n'} ? $st->uid : getpwuid $st->uid) // $st->uid;
|
||||||
|
$h{'group'} = ($opts{'n'} ? $st->gid : getgrgid $st->gid) // $st->gid if not $opts{'o'};
|
||||||
|
$h{'time'} = format_time($opts{'c'} ? $st->ctime : $st->mtime);
|
||||||
|
}
|
||||||
|
push @hfiles, \%h;
|
||||||
|
|
||||||
|
$widths{'dim_w'} = max(defined $h{'dims'} ? length($h{'dims'}{'width'}) : 0, $widths{'dim_w'} // 0);
|
||||||
|
$widths{'dim_h'} = max(defined $h{'dims'} ? length($h{'dims'}{'height'}) : 0, $widths{'dim_h'} // 0);
|
||||||
|
for my $key (qw/blocks ino bytes bytesh owner group nlink/) {
|
||||||
|
$widths{$key} = max(length($h{$key}), $widths{$key} // 0) if exists $h{$key};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Header output when @ARGV was > 1, or after second dir
|
||||||
|
print "\n" if $path and $do_newline;
|
||||||
|
print "$path:\n" if $path and $do_header++;
|
||||||
|
|
||||||
|
# total blocks inline when -d, as header when -l or -s
|
||||||
|
say "total ", $blocks_total / ($opts{'k'} ? 2 : 1) if $path and ! $opts{'d'} and ($opts{'show_blocks'} or $opts{'l'});
|
||||||
|
|
||||||
|
for my $h (@hfiles) {
|
||||||
|
if (! -f $h->{'st'} or ! $h->{'bytes'} or ($opts{'dimensions'} and ! $h->{'dims'} and ! $opts{'unknown'})) {
|
||||||
|
# pass a ref to indicate the data is already base64 encoded
|
||||||
|
write_image \$one_pixel_black, $one_pixel_black_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write_image $h->{'file'}, $h->{'bytes'};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opts{'dimensions'}) {
|
||||||
|
if ($widths{'dim_w'} or $widths{'dim_h'}) {
|
||||||
|
my $min_w = $widths{'dim_w'} // 1;
|
||||||
|
my $min_h = $widths{'dim_h'} // 1;
|
||||||
|
if ($h->{'dims'}{'width'} or $h->{'dims'}{'height'}) {
|
||||||
|
printf " [%*d x %*d] ", $min_w, $h->{'dims'}{'width'} // 0, $min_h, $h->{'dims'}{'height'} // 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf " %*s %*s ", $min_w, ' ', $min_h, ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf " %*d", $widths{'ino'}, $h->{'ino'} if $opts{'i'};
|
||||||
|
printf " %*d", $widths{'blocks'}, $h->{'blocks'} if $opts{'s'};
|
||||||
|
printf " %s", $h->{'lsmodes'} if exists $h->{'lsmodes'};
|
||||||
|
printf " %*s", $widths{'nlink'}, $h->{'nlink'} if exists $h->{'nlink'};
|
||||||
|
printf " %*s", $widths{'owner'}, $h->{'owner'} if exists $h->{'owner'};
|
||||||
|
printf " %*s", $widths{'group'}, $h->{'group'} if exists $h->{'group'};
|
||||||
|
if ($opts{'l'}) {
|
||||||
|
printf " %*d", $widths{'bytes'}, $h->{'bytes'} if ! $opts{'h'};
|
||||||
|
printf " %4s", $h->{'bytesh'} if $opts{'h'};
|
||||||
|
}
|
||||||
|
printf " %s", $h->{'time'} if exists $h->{'time'};
|
||||||
|
print " ", Encode::decode('UTF-8', defined $path ? (split /\//, $h->{'file'})[-1] : $h->{'file'});
|
||||||
|
printf "%s", get_F_type($h->{'st'}) if $opts{'F'} or $opts{'p'};
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the image's dimensions to supplement the image and ls output.
|
||||||
|
sub get_dimensions {
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
my ($ret, $ext);
|
||||||
|
$file =~ /\.([^.]+)$/ and $ext = $1;
|
||||||
|
|
||||||
|
if ($dims_method and (!$ext or ($ext and ! exists $failed_types{$ext}))) {
|
||||||
|
if (ref $dims_method->{'prog'} eq 'CODE') {
|
||||||
|
$ret = $dims_method->{'format'}->($file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my ($stdout, $stderr, $exit) = runcmd($dims_method->{'prog'}, @{$dims_method->{'args'}}, $file);
|
||||||
|
if ($stdout) {
|
||||||
|
$ret = $dims_method->{'format'}->($stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$failed_types{$ext}++ if ! $ret and $ext;
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub runcmd {
|
||||||
|
my $prog = shift;
|
||||||
|
|
||||||
|
my $pid = open3(my $in, my $out, my $err = gensym, $prog, @_);
|
||||||
|
|
||||||
|
my ($out_buf, $err_buf) = ('', '');
|
||||||
|
my $select = new IO::Select;
|
||||||
|
$select->add($out, $err);
|
||||||
|
while (my @ready = $select->can_read(5)) {
|
||||||
|
foreach my $fh (@ready) {
|
||||||
|
my $data;
|
||||||
|
my $bytes = sysread($fh, $data, 1024);
|
||||||
|
if (! defined( $bytes) && ! $!{ECONNRESET}) {
|
||||||
|
die "error running cmd: $prog: $!";
|
||||||
|
}
|
||||||
|
elsif (! defined $bytes or $bytes == 0) {
|
||||||
|
$select->remove($fh);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($fh == $out) { $out_buf .= $data; }
|
||||||
|
elsif ($fh == $err) { $err_buf .= $data; }
|
||||||
|
else {
|
||||||
|
die 'unexpected filehandle in runcmd';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
waitpid($pid, 0);
|
||||||
|
return ($out_buf, $err_buf, $? >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
# List of methods to obtain image dimensions, tried in prioritized order.
|
||||||
|
# Can be external programs or perl module. Expected to return undef when no
|
||||||
|
# dimensions can be found, or a hash ref with 'width' and 'height' elements.
|
||||||
|
sub init_dims_methods {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
prog => 'sips',
|
||||||
|
args => [ '-g', 'pixelWidth', '-g', 'pixelHeight' ],
|
||||||
|
format => sub {
|
||||||
|
my $out = shift;
|
||||||
|
return ($out =~ /pixelWidth: (\d+)\s+pixelHeight: (\d+)/s) ? { width => $1, height => $2 } : undef;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
prog => 'mdls',
|
||||||
|
args => [ '-name', 'kMDItemPixelWidth', '-name', 'kMDItemPixelHeight' ],
|
||||||
|
format => sub {
|
||||||
|
my $out = shift;
|
||||||
|
my %dim;
|
||||||
|
for my $d (qw /Width Height/) {
|
||||||
|
$dim{$d} = $1 if $out =~ /kMDItemPixel$d\s*=\s*(\d+)$/m;
|
||||||
|
}
|
||||||
|
return ($dim{'Width'} and $dim{'Height'}) ? { width => $dim{'Width'}, height => $dim{'Height'} } : undef;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
prog => 'php',
|
||||||
|
args => [ '-r', q/$a = getimagesize("$argv[1]"); if ($a==FALSE) exit(1); else { echo $a[0] . "x" .$a[1]; exit(0); }/ ],
|
||||||
|
format => sub {
|
||||||
|
my $out = shift;
|
||||||
|
return undef unless $out;
|
||||||
|
my @d = split /x/, $out;
|
||||||
|
return { width => $d[0], height => $d[1] };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
prog => 'exiftool',
|
||||||
|
args => [ '-s', '-ImageSize' ],
|
||||||
|
format => sub {
|
||||||
|
my $out = shift;
|
||||||
|
return ($out =~ /ImageSize\s+:\s+(\d+)x(\d+)/) ? { width => $1, height => $2 } : undef;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
# Use Image::Size last, due to limitations mentioned elsewhere
|
||||||
|
{
|
||||||
|
prog => \&have_Image_Size,
|
||||||
|
format => \&call_Image_Size,
|
||||||
|
name => 'Image::Size',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
# Look for a dims_methods program to determine image dimensions
|
||||||
|
sub find_dims_methods {
|
||||||
|
my $methods = shift;
|
||||||
|
|
||||||
|
if ($opts{'method'}) {
|
||||||
|
@$methods = grep {
|
||||||
|
(exists $_->{'name'} and (lc($_->{'name'}) eq lc($opts{'method'}))) or
|
||||||
|
($_->{'prog'} eq $opts{'method'}) } @$methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (@$methods) {
|
||||||
|
if (ref $_->{'prog'} eq 'CODE' and $_->{'prog'}->()) {
|
||||||
|
return $_;
|
||||||
|
}
|
||||||
|
elsif (my $choice = which($_->{'prog'})) {
|
||||||
|
$_->{'prog'} = $choice;
|
||||||
|
return $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
say STDERR "$prog: no methods found to obtain image dimensions. Tried: ",
|
||||||
|
map { "\n " . (exists $_->{'name'} ? $_->{'name'} : $_->{'prog'}) } @$methods;
|
||||||
|
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Allow Image::Size to be used if available to calculate an image's size. It
|
||||||
|
# does not support dimensions of PDF files, so it will be tried last.
|
||||||
|
sub have_Image_Size {
|
||||||
|
eval "require Image::Size";
|
||||||
|
return Image::Size->can('imgsize');
|
||||||
|
}
|
||||||
|
|
||||||
|
sub call_Image_Size {
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
my ($w, $h, $type) = Image::Size::imgsize($file);
|
||||||
|
if (defined $w and defined $h) {
|
||||||
|
# Bug: Workaround negative BMP size values, discovered with export to BMP via
|
||||||
|
# SnagIt and Pixelmator (classic).
|
||||||
|
if ($type eq 'BMP') {
|
||||||
|
$w = (2**32) - $w if $w > 2**31;
|
||||||
|
$h = (2**32) - $h if $h > 2**31;
|
||||||
|
}
|
||||||
|
return { width => $w, height => $h };
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
# grab the specified image file's contents
|
||||||
|
sub get_image_bytes {
|
||||||
|
my $file = shift;
|
||||||
|
|
||||||
|
$/ = undef;
|
||||||
|
open (my $fh, "<", $file)
|
||||||
|
or return undef;
|
||||||
|
my $filebytes = <$fh>;
|
||||||
|
chomp $filebytes;
|
||||||
|
close $fh;
|
||||||
|
|
||||||
|
return $filebytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ls_sort {
|
||||||
|
return if ! (@_ or scalar @_ > 1);
|
||||||
|
|
||||||
|
if ($opts{'t'}) {
|
||||||
|
# descending
|
||||||
|
@_ = ($opts{'y'} or $ENV{'LS_SAMESORT'}) ?
|
||||||
|
sort { _lstat($b)->mtime <=> _lstat($a)->mtime || $b cmp $a } @_ :
|
||||||
|
sort { _lstat($b)->mtime <=> _lstat($a)->mtime || $a cmp $b } @_;
|
||||||
|
}
|
||||||
|
# macOS seems to sort lexically with -c/-U, but shows ctime timestamps
|
||||||
|
elsif ($opts{'c'}) {
|
||||||
|
@_ = sort { $a cmp $b } @_;
|
||||||
|
}
|
||||||
|
elsif ($opts{'u'}) {
|
||||||
|
@_ = sort { _lstat($a)->atime <=> _lstat($b)->atime } @_;
|
||||||
|
}
|
||||||
|
elsif ($opts{'S'}) {
|
||||||
|
@_ = sort { _lstat($b)->size <=> _lstat($a)->size || $a cmp $b } @_;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@_ = sort @_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $opts{'r'} ? reverse @_ : @_;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_F_type {
|
||||||
|
my $st = shift;
|
||||||
|
|
||||||
|
return '/' if -d $st and ($opts{'p'} or $opts{'F'});
|
||||||
|
return '' unless $opts{'F'};
|
||||||
|
return '@' if -l $st;
|
||||||
|
return '|' if -p $st;
|
||||||
|
return '=' if -S $st;
|
||||||
|
return '*' if -x $st; # must come after other tests
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub format_time {
|
||||||
|
my $time = shift;
|
||||||
|
|
||||||
|
my $fmt;
|
||||||
|
if ($opts{'D'}) {
|
||||||
|
$fmt = $opts{'D'};
|
||||||
|
}
|
||||||
|
elsif ($opts{'T'}) {
|
||||||
|
# mmm dd hh:mm:ss yyyy
|
||||||
|
$fmt = '%b %e %T %Y';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($time + $sixmonths > $curtime and $time < $curtime + $sixmonths) {
|
||||||
|
# mmm dd hh:mm
|
||||||
|
$fmt = '%b %e %R';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# mmm dd yyyy
|
||||||
|
$fmt = '%b %e %Y';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strftime $fmt, localtime($time);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub format_human {
|
||||||
|
my $bytes = shift;
|
||||||
|
|
||||||
|
my @units = ('B', 'K', 'M', 'G', 'T', 'P');
|
||||||
|
my $scale = floor((length($bytes) - 1) / 3);
|
||||||
|
my $float = $bytes / (1024 ** $scale);
|
||||||
|
|
||||||
|
my ($frac, $int) = modf($float);
|
||||||
|
if (length($bytes) < 3 or length($int) >= 2) {
|
||||||
|
sprintf "%d%s", $frac <.5 ? $float : $float + 1, $units[$scale];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sprintf "%.1f%s", $float, $units[$scale];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _lstat {
|
||||||
|
my $file = shift;
|
||||||
|
return $stat_cache{$file} if exists $stat_cache{$file};
|
||||||
|
|
||||||
|
if (my $s = lstat($file)) {
|
||||||
|
return $stat_cache{$file} = $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub which {
|
||||||
|
my ($exec) = @_;
|
||||||
|
|
||||||
|
$exec or
|
||||||
|
return undef;
|
||||||
|
|
||||||
|
if ($exec =~ m#/# && -f $exec && -x _) {
|
||||||
|
return $exec
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $file ( map { File::Spec->catfile($_, $exec) } File::Spec->path) {
|
||||||
|
-d $file and
|
||||||
|
next;
|
||||||
|
-x _ and
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Generate 1 pixel black PNG as placeholding for non-image-able files.
|
||||||
|
sub get_black_pixel_image {
|
||||||
|
# base 64 encoded single black pixel png
|
||||||
|
my $one_pixel_black = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgYGD4DwABBAEAwS2OUAAAAABJRU5ErkJggg==';
|
||||||
|
return ($one_pixel_black, length $one_pixel_black);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Based on Stat::lsMode, Copyright 1998 M-J. Dominus, (mjd-perl-lsmode@plover.com)
|
||||||
|
# You may distribute this module under the same terms as Perl itself.
|
||||||
|
|
||||||
|
package Stat::lsMode;
|
||||||
|
|
||||||
|
sub format_mode {
|
||||||
|
my $mode = shift;
|
||||||
|
|
||||||
|
return undef unless defined $mode;
|
||||||
|
|
||||||
|
my @permchars = qw(--- --x -w- -wx r-- r-x rw- rwx);
|
||||||
|
my @ftypechars = qw(. p c ? d ? b ? - ? l ? s ? ? ?);
|
||||||
|
$ftypechars[0] = '';
|
||||||
|
|
||||||
|
my $setids = ($mode & 07000) >> 9;
|
||||||
|
my @permstrs = @permchars[($mode & 0700) >> 6, ($mode & 0070) >> 3, $mode & 0007];
|
||||||
|
my $ftype = $ftypechars[($mode & 0170000) >> 12];
|
||||||
|
|
||||||
|
if ($setids) {
|
||||||
|
if ($setids & 01) { # sticky
|
||||||
|
$permstrs[2] =~ s/([-x])$/$1 eq 'x' ? 't' : 'T'/e;
|
||||||
|
}
|
||||||
|
if ($setids & 04) { # setuid
|
||||||
|
$permstrs[0] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e;
|
||||||
|
}
|
||||||
|
if ($setids & 02) { # setgid
|
||||||
|
$permstrs[1] =~ s/([-x])$/$1 eq 'x' ? 's' : 'S'/e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
join '', $ftype, @permstrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: expandtab
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -13,7 +13,7 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
@@ -26,6 +26,8 @@ function show_help() {
|
|||||||
echo " Begin bouncing the dock icon if another app is active" 1>& 2
|
echo " Begin bouncing the dock icon if another app is active" 1>& 2
|
||||||
echo " $(basename $0) stop" 1>& 2
|
echo " $(basename $0) stop" 1>& 2
|
||||||
echo " Stop bouncing the dock icon if another app is active" 1>& 2
|
echo " Stop bouncing the dock icon if another app is active" 1>& 2
|
||||||
|
echo " $(basename $0) once" 1>& 2
|
||||||
|
echo " Bounce the dock icon once if another app is active" 1>& 2
|
||||||
echo " $(basename $0) fireworks" 1>& 2
|
echo " $(basename $0) fireworks" 1>& 2
|
||||||
echo " Show an explosion animation at the cursor" 1>& 2
|
echo " Show an explosion animation at the cursor" 1>& 2
|
||||||
}
|
}
|
||||||
@@ -42,6 +44,12 @@ function stop_bounce() {
|
|||||||
print_st
|
print_st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bounce_once() {
|
||||||
|
print_osc
|
||||||
|
printf "1337;RequestAttention=once"
|
||||||
|
print_st
|
||||||
|
}
|
||||||
|
|
||||||
function fireworks() {
|
function fireworks() {
|
||||||
print_osc
|
print_osc
|
||||||
printf "1337;RequestAttention=fireworks"
|
printf "1337;RequestAttention=fireworks"
|
||||||
@@ -61,6 +69,9 @@ then
|
|||||||
elif [[ $1 == stop ]]
|
elif [[ $1 == stop ]]
|
||||||
then
|
then
|
||||||
stop_bounce
|
stop_bounce
|
||||||
|
elif [[ $1 == once ]]
|
||||||
|
then
|
||||||
|
bounce_once
|
||||||
elif [[ $1 == fireworks ]]
|
elif [[ $1 == fireworks ]]
|
||||||
then
|
then
|
||||||
fireworks
|
fireworks
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Make sure stdin and stdout are a tty.
|
# Make sure stdin and stdout are a tty.
|
||||||
if [ ! -t 0 ] ; then
|
if [ ! -t 0 ] ; then
|
||||||
exit 1
|
exit 1
|
||||||
@@ -7,17 +7,6 @@ if [ ! -t 1 ] ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Save the tty's state.
|
|
||||||
saved_stty=$(stty -g)
|
|
||||||
|
|
||||||
# Trap ^C to fix the tty.
|
|
||||||
trap ctrl_c INT
|
|
||||||
|
|
||||||
function ctrl_c() {
|
|
||||||
stty "$saved_stty"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Read some bytes from stdin. Pass the number of bytes to read as the first argument.
|
# Read some bytes from stdin. Pass the number of bytes to read as the first argument.
|
||||||
function read_bytes()
|
function read_bytes()
|
||||||
{
|
{
|
||||||
@@ -47,6 +36,22 @@ function version {
|
|||||||
echo -n "$1" | sed -e 's/.* //'
|
echo -n "$1" | sed -e 's/.* //'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trap clean_up EXIT
|
||||||
|
_STTY=$(stty -g) ## Save current terminal setup
|
||||||
|
|
||||||
|
function clean_up() {
|
||||||
|
stty "$_STTY" ## Restore terminal settings
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prepare to silently read any (>=0) characters with no timeout.
|
||||||
|
stty -echo -icanon raw min 0 time 0
|
||||||
|
|
||||||
|
# Consume all pending input.
|
||||||
|
while read none; do :; done
|
||||||
|
|
||||||
|
# Reset the TTY, so it behaves as expected for the rest of the it2check script.
|
||||||
|
clean_up
|
||||||
|
|
||||||
# Enter raw mode and turn off echo so the terminal and I can chat quietly.
|
# Enter raw mode and turn off echo so the terminal and I can chat quietly.
|
||||||
stty -echo -icanon raw
|
stty -echo -icanon raw
|
||||||
|
|
||||||
@@ -69,7 +74,7 @@ echo -n '[1337n'
|
|||||||
echo -n '[5n'
|
echo -n '[5n'
|
||||||
|
|
||||||
version_string=$(read_dsr)
|
version_string=$(read_dsr)
|
||||||
if [ "${version_string}" != "0" -a "${version_string}" != "3" ]; then
|
if [ -n "${version_string}" -a "${version_string}" != "0" -a "${version_string}" != "3" ]; then
|
||||||
# Already read DSR 1337. Read DSR 5 and throw it away.
|
# Already read DSR 1337. Read DSR 5 and throw it away.
|
||||||
dsr=$(read_dsr)
|
dsr=$(read_dsr)
|
||||||
else
|
else
|
||||||
@@ -77,9 +82,6 @@ else
|
|||||||
version_string=""
|
version_string=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Restore the terminal to cooked mode.
|
|
||||||
stty "$saved_stty"
|
|
||||||
|
|
||||||
# Extract the terminal name and version number from the response.
|
# Extract the terminal name and version number from the response.
|
||||||
version=$(version "${version_string}")
|
version=$(version "${version_string}")
|
||||||
term=$(terminal "${version_string}")
|
term=$(terminal "${version_string}")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
trap clean_up EXIT
|
trap clean_up EXIT
|
||||||
trap clean_up INT
|
trap clean_up INT
|
||||||
@@ -23,7 +23,7 @@ function show_help() {
|
|||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -32,13 +32,52 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send_tmux() {
|
||||||
|
uid=$RANDOM$RANDOM
|
||||||
|
print_osc
|
||||||
|
inosc=1
|
||||||
|
printf '1337;Copy=2;%s' "$uid"
|
||||||
|
print_st
|
||||||
|
inosc=0
|
||||||
|
fold | while read line
|
||||||
|
do
|
||||||
|
print_osc
|
||||||
|
inosc=1
|
||||||
|
printf '1337;Copy=3;%s:%s' "$uid" "$line"
|
||||||
|
print_st
|
||||||
|
inosc=0
|
||||||
|
done
|
||||||
|
|
||||||
|
print_osc
|
||||||
|
inosc=1
|
||||||
|
printf '1337;Copy=4;%s' "$uid"
|
||||||
|
print_st
|
||||||
|
inosc=0
|
||||||
|
}
|
||||||
|
|
||||||
|
send_regular() {
|
||||||
|
print_osc
|
||||||
|
inosc=1
|
||||||
|
printf '1337;Copy=:%s' "$data"
|
||||||
|
print_st
|
||||||
|
inosc=0
|
||||||
|
}
|
||||||
|
|
||||||
|
send() {
|
||||||
|
if [[ $TERM == tmux* ]]; then
|
||||||
|
send_tmux
|
||||||
|
else
|
||||||
|
send_regular
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Look for command line flags.
|
# Look for command line flags.
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -53,12 +92,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [ -r "$1" ] ; then
|
if [ -r "$1" ] ; then
|
||||||
data=$(base64 < "$1")
|
base64 < $1 | send
|
||||||
print_osc
|
|
||||||
inosc=1
|
|
||||||
printf '1337;Copy=:%s' "$data"
|
|
||||||
print_st
|
|
||||||
inosc=0
|
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
error "it2copy: $1: No such file or directory"
|
error "it2copy: $1: No such file or directory"
|
||||||
@@ -69,10 +103,4 @@ while [ $# -gt 0 ]; do
|
|||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
data=$(base64)
|
base64 | send
|
||||||
print_osc
|
|
||||||
inosc=1
|
|
||||||
printf '1337;Copy=:%s' "$data"
|
|
||||||
print_st
|
|
||||||
inosc=0
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,73 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
if [ $# -lt 1 ]; then
|
if [ $# -lt 1 ]; then
|
||||||
echo "Usage: $(basename $0) file ..."
|
echo "Usage: $(basename $0) file ..."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
|
# <sequence> ST, and for all ESCs in <sequence> 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* || $TERM == tmux* ]]; then
|
||||||
|
printf "\033Ptmux;\033\033]"
|
||||||
|
else
|
||||||
|
printf "\033]"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# More of the tmux workaround described above.
|
||||||
|
function print_st() {
|
||||||
|
if [[ $TERM == screen* || $TERM == tmux* ]]; then
|
||||||
|
printf "\a\033\\"
|
||||||
|
else
|
||||||
|
printf "\a"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_version() {
|
||||||
|
if [ -z ${IT2DL_BASE64_VERSION+x} ]; then
|
||||||
|
export IT2DL_BASE64_VERSION=$(base64 --version 2>&1)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64_encode() {
|
||||||
|
load_version
|
||||||
|
if [[ "$IT2DL_BASE64_VERSION" =~ GNU ]]; then
|
||||||
|
# Disable line wrap
|
||||||
|
base64 -w0
|
||||||
|
else
|
||||||
|
base64
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for fn in "$@"
|
for fn in "$@"
|
||||||
do
|
do
|
||||||
if [ -r "$fn" ] ; then
|
if [ -r "$fn" ] ; then
|
||||||
[ -d "$fn" ] && { echo "$fn is a directory"; continue; }
|
[ -d "$fn" ] && { echo "$fn is a directory"; continue; }
|
||||||
printf '\033]1337;File=name='`echo -n "$fn" | base64`";"
|
if [[ $TERM == screen* || $TERM == tmux* ]]; then
|
||||||
wc -c "$fn" | awk '{printf "size=%d",$1}'
|
print_osc
|
||||||
printf ":"
|
printf '1337;MultipartFile=name=%s;' $(echo -n "$fn" | b64_encode)
|
||||||
base64 < "$fn"
|
wc -c "$fn" | awk '{printf "size=%d",$1}'
|
||||||
printf '\a'
|
print_st
|
||||||
|
|
||||||
|
parts=$(b64_encode < "$fn" | fold -w 256)
|
||||||
|
for part in $parts; do
|
||||||
|
print_osc
|
||||||
|
printf '1337;FilePart=%s' "$part"
|
||||||
|
print_st
|
||||||
|
done
|
||||||
|
print_osc
|
||||||
|
printf '1337;FileEnd'
|
||||||
|
print_st
|
||||||
|
else
|
||||||
|
printf '\033]1337;File=name=%s;' $(echo -n "$fn" | b64_encode)
|
||||||
|
wc -c "$fn" | awk '{printf "size=%d",$1}'
|
||||||
|
printf ":"
|
||||||
|
base64 < "$fn"
|
||||||
|
printf '\a'
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo File $fn does not exist or is not readable.
|
echo File $fn does not exist or is not readable.
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,99 +1,133 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
function ctrl_c() {
|
set -o pipefail
|
||||||
stty "$saved_stty"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then printf "\033Ptmux;\033\033]"
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]" >& 2
|
printf "\033]"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\" >& 2
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a" >& 2
|
printf "\a"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_b64_version() {
|
||||||
|
if [[ -z "${BASE64_VERSION+x}" ]]; then
|
||||||
|
BASE64_VERSION=$(base64 --version 2>&1)
|
||||||
|
export BASE64_VERSION
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64_encode() {
|
||||||
|
get_b64_version
|
||||||
|
if [[ $BASE64_VERSION =~ GNU ]]; then
|
||||||
|
# Disable line wrap
|
||||||
|
base64 -w0
|
||||||
|
else
|
||||||
|
base64
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64_decode() {
|
||||||
|
get_b64_version
|
||||||
|
if [[ $BASE64_VERSION =~ fourmilab ]]; then
|
||||||
|
BASE64_ARG=-d
|
||||||
|
elif [[ $BASE64_VERSION =~ GNU ]]; then
|
||||||
|
BASE64_ARG=-di
|
||||||
|
else
|
||||||
|
BASE64_ARG=-D
|
||||||
|
fi
|
||||||
|
base64 $BASE64_ARG
|
||||||
|
}
|
||||||
|
|
||||||
|
function error() {
|
||||||
|
errcho "ERROR: $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function errcho() {
|
||||||
|
echo "$@" >&2
|
||||||
|
}
|
||||||
|
|
||||||
function show_help() {
|
function show_help() {
|
||||||
echo "Usage:" 1>& 2
|
errcho
|
||||||
echo " $(basename $0) name" 1>& 2
|
errcho "Usage: it2getvar variable_name"
|
||||||
|
errcho
|
||||||
|
errcho "Output value of the iTerm2 variable"
|
||||||
|
errcho
|
||||||
|
errcho "See the Variables Reference for information about built-in iTerm2 variables:"
|
||||||
|
errcho " -> https://iterm2.com/documentation-variables.html"
|
||||||
|
errcho
|
||||||
}
|
}
|
||||||
|
|
||||||
# Read some bytes from stdin. Pass the number of bytes to read as the first argument.
|
function check_dependency() {
|
||||||
function read_bytes() {
|
if ! (builtin command -V "$1" >/dev/null 2>&1); then
|
||||||
numbytes=$1
|
error "missing dependency: can't find $1"
|
||||||
dd bs=1 count=$numbytes 2>/dev/null
|
exit 1
|
||||||
}
|
|
||||||
|
|
||||||
# read_until c
|
|
||||||
# Returns bytes read from stdin up to but not including the fist one equal to c
|
|
||||||
function read_until() {
|
|
||||||
result=""
|
|
||||||
while :
|
|
||||||
do
|
|
||||||
b=$(read_bytes 1)
|
|
||||||
if [[ $b == $1 ]]
|
|
||||||
then
|
|
||||||
echo "$result"
|
|
||||||
return
|
|
||||||
fi
|
fi
|
||||||
result="$result$b"
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## Main
|
# get_variable variable_name
|
||||||
if [[ $# != 1 ]]
|
#
|
||||||
then
|
# This function uses POSIX standard synonym for the controlling terminal
|
||||||
show_help
|
# associated with the current process group - /dev/tty. It is useful for programs
|
||||||
exit 1
|
# that wish to be sure of writing or reading data from the terminal
|
||||||
|
# no matter how STDIN/STDOUT/STDERR has been redirected.
|
||||||
|
function get_variable() {
|
||||||
|
trap 'cleanup' EXIT
|
||||||
|
stty -echo < /dev/tty
|
||||||
|
exec 9<> /dev/tty
|
||||||
|
print_osc >&9
|
||||||
|
printf "1337;ReportVariable=%s" "$(echo -n "$1" | b64_encode)" >&9
|
||||||
|
print_st >&9
|
||||||
|
read -r -t 5 -d $'\a' iterm_response <&9
|
||||||
|
exec 9>&-
|
||||||
|
stty echo < /dev/tty
|
||||||
|
[[ "$iterm_response" =~ ReportVariable= ]] || {
|
||||||
|
error "Failed to read response from iTerm2"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
echo "$(b64_decode <<< ${iterm_response#*=})"
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
stty echo < /dev/tty
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show help if no arguments
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
show_help
|
||||||
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! test -t 1
|
check_dependency stty
|
||||||
then
|
check_dependency base64
|
||||||
echo "Standard error not a terminal"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Save the tty's state.
|
# Process command line arguments
|
||||||
saved_stty=$(stty -g)
|
case "$1" in
|
||||||
|
-h|--h|--help)
|
||||||
# Trap ^C to fix the tty.
|
show_help
|
||||||
trap ctrl_c INT
|
exit
|
||||||
|
;;
|
||||||
# Enter raw mode and turn off echo so the terminal and I can chat quietly.
|
-*)
|
||||||
stty -echo -icanon raw
|
error "Unknown option: $1"
|
||||||
|
show_help
|
||||||
print_osc
|
exit 1
|
||||||
printf "1337;ReportVariable=%s" "$(printf "%s" "$1" | base64)" >& 2
|
;;
|
||||||
print_st
|
*)
|
||||||
|
[[ -z "$1" ]] && error "Variable name can't be empty" && exit 1
|
||||||
VERSION=$(base64 --version 2>&1)
|
get_variable "$1"
|
||||||
if [[ "$VERSION" =~ fourmilab ]]; then
|
;;
|
||||||
BASE64ARG=-d
|
esac
|
||||||
elif [[ "$VERSION" =~ GNU ]]; then
|
|
||||||
BASE64ARG=-di
|
|
||||||
else
|
|
||||||
BASE64ARG=-D
|
|
||||||
fi
|
|
||||||
|
|
||||||
ignore=$(read_bytes 1)
|
|
||||||
name=$(read_until )
|
|
||||||
re='^]1337;ReportVariable=(.*)'
|
|
||||||
if [[ $name =~ $re ]]
|
|
||||||
then
|
|
||||||
printf "%s" $(base64 $BASE64ARG <<< ${BASH_REMATCH[1]})
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
open=0
|
open=0
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -14,7 +14,7 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -13,7 +13,7 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
@@ -24,13 +24,15 @@ function show_help() {
|
|||||||
echo "Usage:" 1>& 2
|
echo "Usage:" 1>& 2
|
||||||
echo " $(basename $0) set Fn Label" 1>& 2
|
echo " $(basename $0) set Fn Label" 1>& 2
|
||||||
echo " Where n is a value from 1 to 20" 1>& 2
|
echo " Where n is a value from 1 to 20" 1>& 2
|
||||||
|
echo " $(basename $0) set status Label" 1>& 2
|
||||||
|
echo " Sets the touch bar status button's label" 1>& 2
|
||||||
echo " $(basename $0) push [name]" 1>& 2
|
echo " $(basename $0) push [name]" 1>& 2
|
||||||
echo " Saves the current labels with an optional name. Resets labels to their default value, unless name begins with a "." character." 1>& 2
|
echo " Saves the current labels with an optional name. Resets labels to their default value, unless name begins with a "." character." 1>& 2
|
||||||
echo " $(basename $0) pop [name]" 1>& 2
|
echo " $(basename $0) pop [name]" 1>& 2
|
||||||
echo " If name is given, all key labels up to and including the one with the matching name are popped." 1>& 2
|
echo " If name is given, all key labels up to and including the one with the matching name are popped." 1>& 2
|
||||||
echo "" 1>& 2
|
echo "" 1>& 2
|
||||||
echo "Example:" 1>& 2
|
echo "Example:" 1>& 2
|
||||||
echo "#!/bin/bash" 1>& 2
|
echo "#!/usr/bin/env bash" 1>& 2
|
||||||
echo "# Wrapper script for mc that sets function key labels" 1>& 2
|
echo "# Wrapper script for mc that sets function key labels" 1>& 2
|
||||||
echo "NAME=mc_\$RANDOM" 1>& 2
|
echo "NAME=mc_\$RANDOM" 1>& 2
|
||||||
echo "# Save existing labels" 1>& 2
|
echo "# Save existing labels" 1>& 2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
trap clean_up EXIT
|
trap clean_up EXIT
|
||||||
_STTY=$(stty -g) ## Save current terminal setup
|
_STTY=$(stty -g) ## Save current terminal setup
|
||||||
@@ -52,7 +52,7 @@ function decode() {
|
|||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -61,16 +61,25 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function b64_encode() {
|
||||||
|
if [[ "$IT2DL_BASE64_VERSION" =~ GNU ]]; then
|
||||||
|
# Disable line wrap
|
||||||
|
base64 -w0
|
||||||
|
else
|
||||||
|
base64
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function send_request_for_upload() {
|
function send_request_for_upload() {
|
||||||
print_osc
|
print_osc
|
||||||
printf '1337;RequestUpload=format=tgz' ""
|
printf '1337;RequestUpload=format=tgz;version=%s' "$(tar --version | head -1 | b64_encode)"
|
||||||
print_st
|
print_st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||||
# only accepts ESC backslash for ST.
|
# only accepts ESC backslash for ST.
|
||||||
function print_osc() {
|
function print_osc() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\033Ptmux;\033\033]"
|
printf "\033Ptmux;\033\033]"
|
||||||
else
|
else
|
||||||
printf "\033]"
|
printf "\033]"
|
||||||
@@ -13,7 +13,7 @@ function print_osc() {
|
|||||||
|
|
||||||
# More of the tmux workaround described above.
|
# More of the tmux workaround described above.
|
||||||
function print_st() {
|
function print_st() {
|
||||||
if [[ $TERM == screen* ]] ; then
|
if [[ $TERM == screen* || $TERM == tmux* ]] ; then
|
||||||
printf "\a\033\\"
|
printf "\a\033\\"
|
||||||
else
|
else
|
||||||
printf "\a"
|
printf "\a"
|
||||||
|
|||||||
Reference in New Issue
Block a user