This post is about combination of skim, ripgrep and fd that generalizes common ways of using terminal. Let me show you some examples.
Notes keeping system
Being bitten a few times by device or vendor lock offs, I formulated for myself this rules:
- Life without keeping notes educate own memory worse than it could
- Life after notes loss is possible and can be even better than before
- Notes keeping system should follow KISS and be portable
Thus, my current system consists mostly of FS trees and plain markdown files. Directory name represents major interest category, names of the files are often thought as a cloud of tags. Since it's so simple, the real overall structure of notes keeping place are volatile, and depends on how often new strings appears there and how often renaming occures.
Below you can see bash function m (short for "memory") runs sk changing to the root dir of all notes. Then you'll see list of files narrowed by shell query. Right side is a split preview window rendering content that can be scrolled to better get what is looked for. Since no files matched with xargs, I switched with tab to "grep mode" and prepend query with ' (single quote) to discard default fuzziness of skim. There preview window points attention to the concrete line with matched word. Afterall, file opened with nvim.
Personal web archive
Slight variation of previous idea. Gif starts from picking up URL to archive page locally. wa is another bash function. It wraps wget to download page fully when called with argumens, or runs same machinery as above to navigate all web archive store. It also shows, that preview can display images as ASCII blocks with help of viu (this is tmux restriction) or, additionally, open them, in my case, with Quick Look.
Code navigation
In addition to two modes—files and grep—switching between each other with tab, vim extends them with outline mode (pipe in current buffer to the ctags and massage its output back with awk), and buffers mode (show loaded files and allow to close'em). This is not something new to those already using fzf or skim as a daily driver. Maybe just good integration with skim previewer and seamless mode switching without the need to close skim window and hitting another binding keys for next function.
Setup tips
Keep as most options as you can in environment variable
Even though varables values would look extremely cryptic, this lets hold important defaults in a single place. I've found that I can't use the only options for all the use cases, but always trying hard to put sane defaults here.
export SKIM_DEFAULT_COMMAND="fd --type file --follow --hidden --exclude .git --color=always || find ."
export SKIM_DEFAULT_OPTIONS="
--ansi \
--reverse \
--color=16 \
--delimiter=: \
--preview-window='right:65%:hidden:+{2}-/2' \
--preview='
case \`file -bL --mime-type {1}\` in
text/html) w3m {1} ;;
text/troff) man {1} ;;
text/*) bat --style=numbers --color=always --highlight-line {2}:+0 {1} ;;
image/*) viu {1} ;;
application/pdf) pdftotext -layout -nopgbrk {1} - ;;
*) hexyl --bytes=4KiB --color=always --border=none {1} ;;
esac
'
--bind='\
ctrl-d:half-page-down,\
ctrl-u:half-page-up,\
?:toggle-preview,\
alt-/:execute-silent(ql {}),\
alt-space:execute-silent(ql {})+down,\
alt-j:preview-down,\
alt-k:preview-up,\
alt-h:preview-left,\
alt-l:preview-right,\
alt-d:preview-page-down,\
alt-u:preview-page-up,'\
"
Here you can see key bindings modifications --bind= that mimic those in vim. --preview expects string that will be passed to $SHELL -c, so value is basically a map of MIME type to the helper tool.
Wrap sk with shell function
This make possible emulate mode switching from fd to rg and back again. It is also use euristics or conventions when selected item has been picked up.
sk() {
# stdin is not a tty means data has been piped into skim
if [ ! -t 0 ]; then
command sk "$@"
return $?
fi
local qry key sel mod res
__fd() {
command sk \
--prompt="Fls> " \
--header=" " \
--no-multi \
--cmd='fd --color=always --type file --follow' \
--expect=enter,alt-enter,ctrl-m,alt-m,ctrl-c,esc,tab \
--print-query \
--query="$1"
}
__rg() {
command sk \
--prompt="Rgp> " \
--header=" " \
--no-multi \
--cmd='rg --color=always --ignore-case --line-number "{}"' \
--delimiter=: \
--nth="3.." \
--expect=enter,alt-enter,ctrl-m,alt-m,ctrl-c,esc,tab \
--print-query \
--query="$1"
}
mod="__fd"
qry="$@"
while true; do
res=$(eval '$mod' '$qry')
qry=$(echo "$res" | sed -n 1p)
key=$(echo "$res" | sed -n 2p)
sel=$(echo "$res" | sed -n 3p)
[ "$key" != "tab" ] && break
if [ "$mod" = "__rg" ]; then
mod="__fd"
else
mod="__rg"
fi
done
case "$key" in
ctrl-m | enter)
if [ -z "$sel" ]; then
$EDITOR "${qry#\'}"
elif [ "$mod" = "__fd" ]; then
$EDITOR "$sel"
else
$EDITOR $(echo "$sel" | cut -f1,2 -d':' | sed 's/:/ \+/g')
fi
;;
alt-m | alt-enter)
echo "${sel:-$qry}"
;;
ctrl-c | esc | *)
return 0
;;
esac
}
Use that wrapped function as a basis for other workflows
Here is my m:
m() {
trap "cd `pwd`" EXIT
cd $HOME/mem
sk "$@"
}
And wa:
wa() {
trap "cd `pwd`" EXIT
cd $HOME/warc
if [ -z "$1" ]; then
EDITOR="open" sk "$@"
return $?
fi
wget \
--page-requisites \
--convert-links \
--adjust-extension \
--compression=auto \
--reject-regex='/search|/rss' \
--no-if-modified-since \
--no-check-certificate \
--user-agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)' \
"$@"
}
If you're vim user, write some extra commands
Mad looking? Definitely true. This is an example of outline mode.
command! -nargs=? Otln
\ call skim#run({
\ 'source': "ctags -f - --sort=foldcase --file-scope=no --all-kinds=* --fields=Kn " . expand('%:p') .
\ ' | grep -F "/;\""'.
\ " | awk -F $'\t' ".
\ "'".
\ ' BEGIN { OFS=FS }'.
\ ' {'.
\ ' gsub(/implementation/, "impl", $4);'.
\ ' gsub(/\/\^[ ]*/, "", $3);'.
\ ' gsub(/[; {]*\$\/;"$/, "", $3);'.
\ ' gsub(/line:/, "", $5);'.
\ ' printf "%d\t%12s %-31s\t%s\n", $5, $4, $1, $3;'.
\ " }'".
\ " | sort -bk2,2",
\ 'sink*': function('s:OpenUp', ['Otln']),
\ 'options': ['--header= ', '--layout=reverse',
\ '--no-sort',
\ '--query=' . <q-args>,
\ '--expect=tab',
\ '--print-query',
\ '--delimiter=\t', '--nth=3',
\ '--color=16', '--inline-info', '--prompt=Otln> ',
\ '--cycle',
\ '--preview-window=right:65%:hidden:+{1}-/2',
\ '--preview=bat --style=numbers --color=always --highlight-line={1} ' . expand('%:p')] })
More can be found at dotfiles repo.
