diff options
Diffstat (limited to 'v2/src/content/en/remembering-ann.md')
-rw-r--r-- | v2/src/content/en/remembering-ann.md | 186 |
1 files changed, 0 insertions, 186 deletions
diff --git a/v2/src/content/en/remembering-ann.md b/v2/src/content/en/remembering-ann.md deleted file mode 100644 index 9013ad4..0000000 --- a/v2/src/content/en/remembering-ann.md +++ /dev/null @@ -1,186 +0,0 @@ ---- - -title: ANN: remembering - Add memory to dmenu, fzf and similar tools - -date: 2021-01-26 - -categories: ann - ---- - -Today I pushed v0.1.0 of [remembering][remembering], a tool to enhance the interactive usability of menu-like tools, such as [dmenu][dmenu] and [fzf][fzf]. - -## Previous solution - -I previously used [yeganesh][yeganesh] fill this gap, but as I started to rely less on Emacs, I added fzf as my go-to tool for doing fuzzy searching on the terminal. -But I didn't like that fzf always showed the same order of things, when I would only need 3 or 4 commonly used files. - -For those who don't know: yeganesh is a wrapper around dmenu that will remember your most used programs and put them on the beginning of the list of executables. -This is very convenient for interactive prolonged use, as with time the things you usually want are right at the very beginning. - -But now I had this thing, yeganesh, that solved this problem for dmenu, but didn't for fzf. - -I initially considered patching yeganesh to support it, but I found it more coupled to dmenu than I would desire. -I'd rather have something that knows nothing about dmenu, fzf or anything, but enhances tools like those in a useful way. - -[remembering]: https://euandreh.xyz/remembering/ -[dmenu]: https://tools.suckless.org/dmenu/ -[fzf]: https://github.com/junegunn/fzf -[yeganesh]: http://dmwit.com/yeganesh/ - -## Implementation - -Other than being decoupled from dmenu, another improvement I though that could be made on top of yeganesh is the programming language choice. -Instead of Haskell, I went with POSIX sh. -Sticking to POSIX sh makes it require less build-time dependencies. There aren't any, actually. Packaging is made much easier due to that. - -The good thing is that the program itself is small enough ([119 lines][119-lines] on v0.1.0) that POSIX sh does the job just fine, combined with other POSIX utilities such as [getopts][getopts], [sort][sort] and [awk][awk]. - -[119-lines]: https://euandre.org/git/remembering/tree/remembering?id=v0.1.0 -[getopts]: http://www.opengroup.org/onlinepubs/9699919799/utilities/getopts.html -[sort]: http://www.opengroup.org/onlinepubs/9699919799/utilities/sort.html -[awk]: http://www.opengroup.org/onlinepubs/9699919799/utilities/awk.html - -The behaviour is: given a program that will read from STDIN and write a single entry to STDOUT, `remembering` wraps that program, and rearranges STDIN so that previous choices appear at the beginning. - -Where you would do: - -```shell -$ seq 5 | fzf - - 5 - 4 - 3 - 2 -> 1 - 5/5 -> -``` - -And every time get the same order of numbers, now you can write: - -```shell -$ seq 5 | remembering -p seq-fzf -c fzf - - 5 - 4 - 3 - 2 -> 1 - 5/5 -> -``` - -On the first run, everything is the same. If you picked 4 on the previous example, the following run would be different: - -```shell -$ seq 5 | remembering -p seq-fzf -c fzf - - 5 - 3 - 2 - 1 -> 4 - 5/5 -> -``` - -As time passes, the list would adjust based on the frequency of your choices. - -I aimed for reusability, so that I could wrap diverse commands with `remembering` and it would be able to work. To accomplish that, a "profile" (the `-p something` part) stores data about different runs separately. - -I took the idea of building something small with few dependencies to other places too: -- the manpages are written in troff directly; -- the tests are just more POSIX sh files; -- and a POSIX Makefile to `check` and `install`. - -I was aware of the value of sticking to coding to standards, but I had past experience mostly with programming language standards, such as ECMAScript, Common Lisp, Scheme, or with IndexedDB or DOM APIs. -It felt good to rediscover these nice POSIX tools, which makes me remember of a quote by [Henry Spencer][poor-unix]: - -> Those who do not understand Unix are condemned to reinvent it, poorly. - -[poor-unix]: https://en.wikipedia.org/wiki/Henry_Spencer#cite_note-3 - -## Usage examples - -Here are some functions I wrote myself that you may find useful: - -### Run a command with fzf on `$PWD` - -```shellcheck -f() { - profile="$f-shell-function(pwd | sed -e 's_/_-_g')" - file="$(git ls-files | \ - remembering -p "$profile" \ - -c "fzf --select-1 --exit -0 --query \"$2\" --preview 'cat {}'")" - if [ -n "$file" ]; then - # shellcheck disable=2068 - history -s f $@ - history -s "$1" "$file" - "$1" "$file" -fi -} -``` - -This way I can run `f vi` or `f vi config` at the root of a repository, and the list of files will always appear on the most used order. -Adding `pwd` to the profile allows it to not mix data for different repositories. - -### Copy password to clipboard - -```shell -choice="$(find "$HOME/.password-store" -type f | \ - grep -Ev '(.git|.gpg-id)' | \ - sed -e "s|$HOME/.password-store/||" -e 's/\.gpg$//' | \ - remembering -p password-store \ - -c 'dmenu -l 20 -i')" - - -if [ -n "$choice" ]; then - pass show "$choice" -c -fi -``` - -Adding the above to a file and binding it to a keyboard shortcut, I can access the contents of my [password store][password-store], with the entries ordered by usage. - -[password-store]: https://www.passwordstore.org/ - -### Replacing yeganesh - -Where I previously had: - -```shell -exe=$(yeganesh -x) && exec $exe -``` - -Now I have: - -```shell -exe=$(dmenu_path | remembering -p dmenu-exec -c dmenu) && exec $exe -``` - -This way, the executables appear on order of usage. - -If you don't have `dmenu_path`, you can get just the underlying `stest` tool that looks at the executables available in your `$PATH`. Here's a juicy one-liner to do it: - -```shell -$ wget -O- https://dl.suckless.org/tools/dmenu-5.0.tar.gz | \ - tar Ozxf - dmenu-5.0/arg.h dmenu-5.0/stest.c | \ - sed 's|^#include "arg.h"$|// #include "arg.h"|' | \ - cc -xc - -o stest -``` - -With the `stest` utility you'll be able to list executables in your `$PATH` and pipe them to dmenu or something else yourself: -```shell -$ (IFS=:; ./stest -flx $PATH;) | sort -u | remembering -p another-dmenu-exec -c dmenu | sh -``` - -In fact, the code for `dmenu_path` is almost just like that. - -## Conclusion - -For my personal use, I've [packaged] `remembering` for GNU Guix and Nix. Packaging it to any other distribution should be trivial, or just downloading the tarball and running `[sudo] make install`. - -Patches welcome! - -[packaged]: https://euandre.org/git/package-repository/ -[nix-file]: https://euandre.org/git/dotfiles/tree/nixos/not-on-nixpkgs/remembering.nix?id=0831444f745cf908e940407c3e00a61f6152961f |