lf
lf copied to clipboard
Variable for all files in directory *as they are ordered by lf*.
I'd like a way to output to an opener program/remote/etc/variable all the current files in the directory, in the current order they appear in lf.
Here's one of my use cases. As it is, I use the image viewer sxiv which can open multiple images at once as arguments or through stdin. So I want to have lf open an image, for that image to appear in sxiv, but also I'd like sxiv to receive the other images in the directory so I can move through them in sxiv, independently of lf.
Right now I have an external script that takes all the images in the current directory (with ls
or find
), orders them (via awk
) so that the currently selected one is on top, and then sends them to sxiv. This allows me to open an images in a directory, and then move through the other images in sxiv in the order they are arranged by default (i.e. alphabetically), without having to open them one by one in lf.
This works fine in the simple case as is, but suppose someone wants to sort photos by date or size or some other variable lf can sort images by. In this case, if they open the file up in sxiv, sxiv will still get the images from the rifling script in alphabetical order and thus to sort through the images that way would not work as according to plan. Images in lf would be sorted as desired by time, but images in the opener sxiv, would still be sorted alphabetically.
The most extensible fix for this I can think of is, as I said, have a way to output all files in the directory in the order they appear.
Another possibility is communicating with lf to get the current sort variable. Perhaps there's a way to do this now. I'm not sure.
If anyone has any clues as to how to solve this with lf as it is now, please tell me, but such an extension I think would enable new clever ways to open and deal with files.
I do not know the way to print all files in the current dir in order. But the variable fx
used for selected files does keep the order. A possible solution is to select all before opening sxiv and then use that variable like this:
cmd open ${{
case $(file --mime-type "$f" -b) in
image/*) lf -remote "send $id :unselect; invert; open_images" ;;
*/x-raw-disk-image) dmenumount "$f" ;;
*/zip) lf -remote "send $id mount_archive" ;;
text/*) $EDITOR $fx ;;
*) for f in $fx; do setsid $OPENER $f >/dev/null 2>&1 & done ;;
esac
}}
cmd open_images ${{
c="$(grep -Fn "$f" <<< "$fx" | cut -d ':' -f 1)"
[ $c -eq 1 ] && list="$fx" || list="$(tail -n +$c <<<"($fx)")$(head -$((c-1)) <<<"($fx)")"
sxiv -aio 2>/dev/null <<< "$list" |
(lf -remote "send $id unselect"
while read -r file; do
lf -remote "send $id select \"$file\""
lf -remote "send toggle"
done)
}}
When opening images, this is unselecting all and then inverting selection(since I do not know a better way to select all files).
If the first file is focused, we just use fx
Else, it is getting the index of the currently focused file. That line and all after are placed at the beginning of the list and all before are wrapped to the end of the list.
[Update] I wanted to use this for myself but I disliked the selection of all files if I had something selected. Also, I didn't like removing the selection if nothing was marked in sxiv and the selection was not automatic. Another issue was when selecting marked files, the preview was triggered for every iteration but only the last one is needed
cmd open ${{
case $(file --mime-type "$f" -b) in
image/*) lf -remote "send $id open_images" ;;
*) for f in $fx; do setsid $OPENER $f >/dev/null 2>&1 & done ;;
esac
}}
cmd open_images ${{
[ -z "$fs" ] && lf -remote "send $id :invert; open_images all" && exit 0
i="$(grep -Fxn "$f" <<< "$fx" | cut -d ':' -f 1)"
[ $i -eq 1 ] && list="$fx" || list="$(tail -n +$i <<<"$fx")"$'\n'"$(head -$((i-1)) <<<"$fx")"
out="$(devour nsxiv -aiop 2>/dev/null <<< "$list")"
if [ -n "$out" ] || [ -n "$1" ]; then
lf -remote "send $id unselect"
[ -z "$out" ] && exit 0
while read -r file; do
lf -remote "send $id toggle \"$file\""
done <<< "$out"
lf -remote "send $id select \"${out##*$'\n'}\""
fi
}}
You can get the current sort type reading the lf_sortby
environment variable, other environment variables that you may find useful: lf_reverse
and lf_hidden
.
Check: https://github.com/gokcehan/lf/blob/b47cf6d5a525c39db268c2f7b77e2b7497843b17/main.go#L111-L167
You could use the above mentioned variables with some success, but sadly, lf's natural
sort is not always the same as the one in exa
or ls
.
There are probably some other differences that I don't remember, but I extracted lf file sorting function to a separate program for exactly this purpose some time ago.
(Relies on lf_sortby
and lf_reverse
variables to keep sorting in sync with lf)
To use:
go install github.com/MahouShoujoMivutilde/shellbin/cmd/sortlf@latest
(Assuming $(go env GOPATH)/bin
is in PATH
).
And inside lfrc
:
cmd open &{{
exec >/dev/null
case "${f##*.}" in
cbr|cbz|djvu|pdf)
setsid -f evince -- $f >/dev/null
;;
# ...
*)
case $(file -b -L --mime-type -- $f) in
image/*)
images="$(sortlf -- "$PWD" | grep -Ei "\.(png|jpg|jpeg|gif|webp|tif|tiff|bmp|heic|svg|avif|jxl|heif)(_large)*$")"
current="$(echo "$images" | nl | grep -F -- "$(basename $f)" | awk '{print $1}')"
echo "$images" | nsxiv -io -n $current 2>/dev/null | lf-select 2>/dev/null
;;
# ...
esac
;;
esac
}}
(I am pretty sure I stole lf-select
from you, btw).
lf
currently doesn't export this information, although the easiest way to simulate this is to unselect
and then invert
as pointed out by @DusanLesan.
I did manage to find a way to save the current selections to a file and then restore it back after performing the command. Something like below, but I have only tested this very briefly:
set ifs "\n"
cmd openall :{{
$printf '%s\x0' $fs > /tmp/lf_selections
:unselect; invert
${{
<insert_your_command_here> $fs
lf -remote "send $id :unselect; toggle $(xargs -0 printf ' %q' < /tmp/lf_selections)"
}}
}}
Given the complexity involved, I do agree that it would be better to export this information (e.g. environment variable fa
) so that it can be consumed more easily. We can either consider making them available as an environment variable, but @j-xella is strongly advocating to store them in a file instead, see the discussion around https://github.com/gokcehan/lf/issues/1277#issuecomment-1587688404 .