foxshell/fn/-z4h-present-files
2025-07-04 11:48:40 -05:00

148 lines
5.7 KiB
Bash

#!/usr/bin/env zsh
eval "$_z4h_opt"
setopt octalzeroes
local -i list_colors=$1
local -i list_types=$2
local -i tilde_unexpand=$3
[[ $_z4h_mode_colors[ln] != target ]]
local -i ln_target=$?
local -r nil=$'\0'
local -r or=$_z4h_mode_colors[or]
local -r ln=$_z4h_mode_colors[ln]
local -r suf=('|' '|' '' '' '' '' '/' '/' '' '' '' '' '' '' '' '*' '' '' '@' '@' '' '' '=' '=')
local -i10 m i
local buf file style
local -a files modes link link_mode
local -i MATCH
local MBEGIN MEND
while true; do
while [[ $buf != *$'\n'* ]]; do
sysread -s 4096 'buf[$#buf+1]' && continue
(( $? == 5 )) || return
return
done
files=("${(@f)buf}")
buf=$files[-1]
files[-1]=()
if (( ! list_colors && ! list_types && ! tilde_unexpand )) || ! zstat -L -A modes +mode -- $files; then
printf '%1$s\0%1$q\n' $files
continue
fi
if (( ! list_colors && ! tilde_unexpand )); then
printf '%2$s\0%2$q%1$s\n' \
${"${(@)modes/(#m)*/$suf[$((((MATCH & 61440) >> 11) | !(MATCH & 73)))]}":^files}
continue
fi
# This doesn't work the same way as GNU ls. See get_color_indicator in
# https://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c.
#
# TODO: fix it.
# TODO: see if this can be made faster by invoking `find` with `-printf '%Y\0%m\0%P\n'`,
# invoking `zstat -A links +link -- ${files*$'\0'*$'\0'}` and then applying some kind of
# crazy expansion.
#
# Types:
#
# ? unknown
# p fifo
# c chardev
# d directory
# b blockdev
# - normal
# s socket
# w whiteout
# l symlink (good)
# L symlink (loop)
# N symlink (nonexistent)
if (( tilde_unexpand )); then
# This implementation is the same as below except that $file in the second output field
# is replaced with ${(D)file}.
for file m in ${files:^modes}; do
if [[ ${style::=${${_z4h_mode_codes[$((m & 64075))]:-$'\0'}/%$'\0'/$'\0'$_z4h_name_colors[(ke)$file:t]}} \
== $'@\0.' ]]; then
if ! zstat -L -A link +link -- $file; then
printf '%1$s\0\e[%2$sm%3$s\e[0m\n' $file "${or:-$_z4h_name_colors[$file:t]}" ${(D)file}
elif ! zstat -A link_mode +mode -- $file; then
printf '%1$s\0\e[%2$sm%5$s\e[0m -> \e[%4$sm%3$q\e[0m\n' \
$file "${or:-$_z4h_name_colors[$file:t]}" \
$link "${or:-$_z4h_name_colors[$link:t]}" \
${(D)file}
elif (( ln_target )); then
printf '%1$s\0\e[%4$sm%5$s\e[0m -> \e[%4$sm%2$q\e[0m%3$s\n' \
$file $link \
"${(@0)${${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}/%$nil/$nil$_z4h_name_colors[(ke)$link:t]}}" \
${(D)file}
else
printf '%1$s\0\e[%3$sm%6$s\e[0m -> \e[%5$sm%2$q\e[0m%4$s\n' \
$file $link "${ln:-$_z4h_name_colors[$link:t]}" \
"${(@0)${${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}/%$nil/$nil$_z4h_name_colors[(ke)$link:t]}}" \
${(D)file}
fi
else
printf '%1$s\0\e[%3$sm%4$s\e[0m%2$s\n' $file "${(@0)style}" ${(D)file}
fi
done
elif (( $#_z4h_name_colors )); then
# This implementation works whether _z4h_name_colors is empty or not. It's about 30%
# slower than the alternative implementation below, which only works if _z4h_name_colors
# is empty.
for file m in ${files:^modes}; do
if [[ ${style::=${${_z4h_mode_codes[$((m & 64075))]:-$'\0'}/%$'\0'/$'\0'$_z4h_name_colors[(ke)$file:t]}} \
== $'@\0.' ]]; then
if ! zstat -L -A link +link -- $file; then
printf '%1$s\0\e[%2$sm%1$q\e[0m\n' $file "${or:-$_z4h_name_colors[$file:t]}"
elif ! zstat -A link_mode +mode -- $file; then
printf '%1$s\0\e[%2$sm%1$q\e[0m -> \e[%4$sm%3$q\e[0m\n' \
$file "${or:-$_z4h_name_colors[$file:t]}" \
$link "${or:-$_z4h_name_colors[$link:t]}"
elif (( ln_target )); then
printf '%1$s\0\e[%4$sm%1$q\e[0m -> \e[%4$sm%2$q\e[0m%3$s\n' \
$file $link \
"${(@0)${${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}/%$nil/$nil$_z4h_name_colors[(ke)$link:t]}}"
else
printf '%1$s\0\e[%3$sm%1$q\e[0m -> \e[%5$sm%2$q\e[0m%4$s\n' \
$file $link "${ln:-$_z4h_name_colors[$link:t]}" \
"${(@0)${${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}/%$nil/$nil$_z4h_name_colors[(ke)$link:t]}}"
fi
else
printf '%1$s\0\e[%3$sm%1$q\e[0m%2$s\n' $file "${(@0)style}"
fi
done
else
modes=("${(@)modes:/(#m)*/${_z4h_mode_codes[$((MATCH & 64075))]:-$nil}}")
while true; do
i=${modes[(i)@*]}
if (( i == $#modes + 1 )); then
printf '%3$s\0\e[%2$sm%3$q\e[0m%1$s\n' "${(@0)${(@)modes:^files}}"
break
elif (( i != 1 )); then
printf '%3$s\0\e[%2$sm%3$q\e[0m%1$s\n' "${(@0)${(@)modes[1,i-1]:^files}}"
shift $((i-1)) modes files
fi
file=$files[1]
shift modes files
if ! zstat -L -A link +link -- $file; then
printf '%1$s\0\e['$or'm%1$q\e[0m\n' $file
elif ! zstat -A link_mode +mode -- $file; then
printf '%1$s\0\e['$or'm%1$q\e[0m -> \e['$or'm%2$q\e[0m\n' $file $link
elif (( ln_target )); then
printf '%1$s\0\e[%4$sm%1$q\e[0m -> \e[%4$sm%2$q\e[0m%3$s\n' \
$file $link "${(@0)${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}}"
else
printf '%1$s\0\e['$ln'm%1$q\e[0m -> \e[%4$sm%2$q\e[0m%3$s\n' \
$file $link "${(@0)${_z4h_mode_codes[$((link_mode & 64075))]:-$nil}}"
fi
done
fi
done