Skip to content

Instantly share code, notes, and snippets.

@tkapias
Last active October 1, 2023 14:54
Show Gist options
  • Save tkapias/8d23d8667432ff36b6b54b77111e591c to your computer and use it in GitHub Desktop.
Save tkapias/8d23d8667432ff36b6b54b77111e591c to your computer and use it in GitHub Desktop.
List-Fuzzy: function for Bash 5+. List/filter/sort a location in sk/sk-tmux with lsd 1+ and xsel
# List-Fuzzy: lsd pipe to sk/sk-tmux then output to tty and clipboards
lf() {
Help() {
cat <<- HEREDOC
list-fuzzy: List/filter/sort a location in sk/sk-tmux
- inline|vertical output to 'stdout + clipboard'
- use only current or the first submitted path
Syntax: lf [-haefgnosv] [<path>]
options:
-h Print this Help.
-a Display hidden files (ex.: . & ..)
-g Display git status (can slowdown lsd)
-v Output vertical list (Default: inline)
-e Sort by ext (Default: by name)
-n Sort by newest (Default: by name)
-s Sort by size (Default: by name)
-f Files first (Default: dirs first)
-o Keep sort order when filtering
<path> Optional (Default: .)
HEREDOC
}
local array=( sk lsd xsel gpaste-client )
for cmd in "${array[@]}"; do
if [[ -z $(command -v $cmd) ]]; then
echo "function requirements:"
echo -e " - lsd >=1.0\n - sk >0.10\n - xsel\n - bash >5\n - gpaste-client"
echo "Error: $cmd could not be found"
return 0
fi
done
if ! pidof -q gpaste-daemon; then
echo "function requirements:"
echo -e "\n - Error: gpaste-daemon s not running"
return 0
fi
local _by="name"
local _filter="visible"
local _formatSel='| xargs -r -d "\n"'
local _git=''
local _gitCol=''
local _group="--group-dirs=first"
local OPTIND=0
while getopts ":haefgnosv" option; do
case $option in
h) Help; return 0 ;;
a) local _all="-A"
local _filter="all" ;;
e) local _sort="--sort=extension"
local _by="extention" ;;
f) local _group="--group-dirs=last" ;;
g) local _git='git,'
local _gitCol='$9=' ;;
n) local _sort="--sort=time"
local _by="newest" ;;
o) local _noSort="--no-sort" ;;
s) local _sort="--sort=size"
local _by="size" ;;
v) local _formatSel="";;
\?) echo -e "Unknown option: -$OPTARG \n" >&2; Help; return 1;;
: ) echo -e "Missing argument for -$OPTARG \n" >&2; Help; return 1;;
* ) echo -e "Unimplemented option: -$option \n" >&2; Help; return 1;;
esac
done
shift $((OPTIND-1))
if command -v tmux 1> /dev/null; then
local _fuzzyCmd="sk-tmux -d 80%"
else
local _fuzzyCmd="sk"
fi
_location="$(realpath -sq "${1-$PWD}" 2>&1)"
read -r -d '' _cleanSel <<- HEREDOC
for line in {+}; do echo "\$line"; done \
| sed -E -e 's/\s⇒\s.+//g' \
| awk -v loc="${_location}/" '{\$1=\$2=\$3=\$4=\$5=\$6=\$7=\$8=$_gitCol""; \$0=\$0; \$1=\$1; print "\"" loc \$0 "\""}' \
$_formatSel
HEREDOC
lsd --ignore-config -l1 --size=short --header --blocks=permission,links,size,user,group,date,${_git}name $_all $_sort --icon=always --icon-theme=fancy --color=always $_group --date='+%F %T' "$_location" 2>/dev/null \
| ${_fuzzyCmd} --exit-0 --color=dark,bg+:237 $_noSort --no-mouse --cycle --keep-right --sync --multi --reverse --ansi --tabstop 2 --header-lines=1 \
--prompt "A list of $_filter elements sorted by $_by in \"$_location\" > " \
--preview-window down:8:wrap \
--preview "echo -e \"\\\e[1;37mKEYS:\\\e[0m \\\e[1;33m󰱑\\\e[1;36mtab \\\e[1;33m󰗼\\\e[1;36menter/esc \\\e[1;33m󰜺\\\e[1;36mctrl-c \\\e[1;33m\\\e[1;36mctrl-a \\\e[1;33m\\\e[1;36mctrl-d \\\e[1;33m/\\\e[1;36mctrl-t \\\e[1;33m󱂩\\\e[1;36mctrl-p\\\n\\\e[1;37mPREVIEW \\\e[0;37mfor tty/clipboard/primary:\\\n\"; $_cleanSel | head -c -1" \
--bind "ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle-all,ctrl-p:toggle-preview" \
--bind "enter:execute-silent[ $_cleanSel | head -c -1 \
| xsel -ip && xsel -op | xsel -ib && xsel -ob | xargs -r -0 echo ]+execute-silent[ xsel -cp && xsel -cb ]+abort"
}
@tkapias
Copy link
Author

tkapias commented Sep 9, 2023

lf is a useful function I wrote for my bashrc to navigate a directory and easily select specific files for operating on them safely

The selected files are quoted, shown on the tty and copied to both clipboards. The output list can be either inline or in a vertical format.

  • Skim (sk or sk-tmux) is used as a fuzzy-finder since it is quicker than fzf and I experienced problems with execute-silent parsing in fzf.
  • For the ls input command, lsd is used because it is fast, attractive, and has numerous features from v1.0.0.
  • The program utilises xsel for clipboard output as xclip fails to close the stdout and makes tmux unresponsive.

@tkapias
Copy link
Author

tkapias commented Sep 9, 2023

Example in urxvt/tmux

lf

@tkapias
Copy link
Author

tkapias commented Sep 10, 2023

I updated the function to depend on a clipboard manager:

  • gpaste in this case because it keep last entries active.
  • Reasons: xsel/xclip both function by running in the background and waiting to be called for pasting or clearing, the proccess try to stay even if you close the tty.
  • It was hanging the closing of my tmux session and I could not open a new one with the same unit name without killing it manually.

Now it clears xsel after using it because gpaste keep the selection, and I clear gpaste history with a key binding manually when I want.

@tkapias
Copy link
Author

tkapias commented Sep 10, 2023

Note: GPaste does not require Gnome, it can be built light :

meson setup -Dbash-completion=true -Dgnome-shell=false -Dsystemd=true -Dgnome-shell=false -Dx-keybinder=false -Dcontrol-center-keybindings-dir=false -Dx-keybinder=true ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment