# msgid "" msgstr "" msgid "title: \"ANN: remembering - Add memory to dmenu, fzf and similar tools\"" msgstr "" msgid "date: 2021-01-26" msgstr "" msgid "layout: post" msgstr "" msgid "lang: en" msgstr "" msgid "ref: ann-remembering-add-memory-to-dmenu-fzf-and-similar-tools" msgstr "" msgid "Previous solution" msgstr "" msgid "" "I previously used [yeganesh](http://dmwit.com/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." msgstr "" msgid "" "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." msgstr "" msgid "" "But now I had this thing, yeganesh, that solved this problem for dmenu, but " "didn't for fzf." msgstr "" msgid "" "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." msgstr "" msgid "Implementation" msgstr "" msgid "" "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." msgstr "" msgid "" "The good thing is that the program itself is small enough ([119 " "lines](https://git.euandreh.xyz/remembering/tree/remembering?id=v0.1.0) on " "v0.1.0) that POSIX sh does the job just fine, combined with other POSIX " "utilities such as " "[getopts](http://www.opengroup.org/onlinepubs/9699919799/utilities/getopts.html)," " [sort](http://www.opengroup.org/onlinepubs/9699919799/utilities/sort.html) " "and " "[awk](http://www.opengroup.org/onlinepubs/9699919799/utilities/awk.html)." msgstr "" msgid "" "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." msgstr "" msgid "Where you would do:" msgstr "" msgid "" "$ seq 5 | fzf\n" "\n" " 5\n" " 4\n" " 3\n" " 2\n" "> 1\n" " 5/5\n" ">\n" msgstr "" msgid "And every time get the same order of numbers, now you can write:" msgstr "" msgid "" "$ seq 5 | remembering -p seq-fzf -c fzf\n" "\n" " 5\n" " 4\n" " 3\n" " 2\n" "> 1\n" " 5/5\n" ">\n" msgstr "" msgid "" "On the first run, everything is the same. If you picked 4 on the previous " "example, the following run would be different:" msgstr "" msgid "" "$ seq 5 | remembering -p seq-fzf -c fzf\n" "\n" " 5\n" " 3\n" " 2\n" " 1\n" "> 4\n" " 5/5\n" ">\n" msgstr "" msgid "" "As time passes, the list would adjust based on the frequency of your " "choices." msgstr "" msgid "" "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." msgstr "" msgid "" "I took the idea of building something small with few dependencies to other " "places too:" msgstr "" msgid "the man pages are written in troff directly;" msgstr "" msgid "the tests are just more POSIX sh files;" msgstr "" msgid "and a POSIX Makefile to `check` and `install`." msgstr "" msgid "" "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](https://en.wikipedia.org/wiki/Henry_Spencer#cite_note-3):" msgstr "" msgid "Those who do not understand Unix are condemned to reinvent it, poorly." msgstr "" msgid "Usage examples" msgstr "" msgid "Here are some functions I wrote myself that you may find useful:" msgstr "" msgid "Run a command with fzf on `$PWD`" msgstr "" msgid "" "f() {\n" " profile=\"$f-shell-function(pwd | sed -e 's_/_-_g')\"\n" " file=\"$(git ls-files | \\\n" " remembering -p \"$profile\" \\\n" " -c \"fzf --select-1 --exit -0 --query \\\"$2\\\" --preview 'cat {}'\")\"\n" " if [ -n \"$file\" ]; then\n" " # shellcheck disable=2068\n" " history -s f $@\n" " history -s \"$1\" \"$file\"\n" " \"$1\" \"$file\"\n" "fi\n" "}\n" msgstr "" msgid "" "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." msgstr "" msgid "Copy password to clipboard" msgstr "" msgid "" "choice=\"$(find \"$HOME/.password-store\" -type f | \\\n" " grep -Ev '(.git|.gpg-id)' | \\\n" " sed -e \"s|$HOME/.password-store/||\" -e 's/\\.gpg$//' | \\\n" " remembering -p password-store \\\n" " -c 'dmenu -l 20 -i')\"\n" "\n" "\n" "if [ -n \"$choice\" ]; then\n" " pass show \"$choice\" -c\n" "fi\n" msgstr "" msgid "" "Adding the above to a file and binding it to a keyboard shortcut, I can " "access the contents of my [password store](https://www.passwordstore.org/), " "with the entries ordered by usage." msgstr "" msgid "Replacing yeganesh" msgstr "" msgid "Where I previously had:" msgstr "" msgid "exe=$(yeganesh -x) && exec $exe\n" msgstr "" msgid "Now I have:" msgstr "" msgid "exe=$(dmenu_path | remembering -p dmenu-exec -c dmenu) && exec $exe\n" msgstr "" msgid "This way, the executables appear on order of usage." msgstr "" msgid "" "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:" msgstr "" msgid "" "$ wget -O- https://dl.suckless.org/tools/dmenu-5.0.tar.gz | \\\n" " tar Ozxf - dmenu-5.0/arg.h dmenu-5.0/stest.c | \\\n" " sed 's|^#include \"arg.h\"$|// #include \"arg.h\"|' | \\\n" " cc -xc - -o stest\n" msgstr "" msgid "" "With the `stest` utility you'll be able to list executables in your `$PATH` " "and pipe them to dmenu or something else yourself:" msgstr "" msgid "" "$ (IFS=:; ./stest -flx $PATH;) | sort -u | remembering -p another-dmenu-exec" " -c dmenu | sh\n" msgstr "" msgid "In fact, the code for `dmenu_path` is almost just like that." msgstr "" msgid "Conclusion" msgstr "" msgid "" "For my personal use, I've packaged `remembering` for [GNU " "Guix](https://git.euandreh.xyz/euandreh-guix-channel/about/) and " "[Nix](https://git.euandreh.xyz/dotfiles/tree/nixos/not-on-" "nixpkgs/remembering.nix?id=0831444f745cf908e940407c3e00a61f6152961f). " "Packaging it to any other distribution should be trivial, or just " "downloading the tarball and running `[sudo] make install`." msgstr "" msgid "Patches welcome!" msgstr "" msgid "" "Today I pushed v0.1.0 of [remembering](https://remembering.euandreh.xyz), a " "tool to enhance the interactive usability of menu-like tools, such as " "[dmenu](https://tools.suckless.org/dmenu/) and " "[fzf](https://github.com/junegunn/fzf)." msgstr "" #~ msgid "" #~ "Today I pushed v0.1.0 of " #~ "[remembering](https://git.euandreh.xyz/remembering/about/), a tool to " #~ "enhance the interactive usability of menu-like tools, such as " #~ "[dmenu](https://tools.suckless.org/dmenu/) and " #~ "[fzf](https://github.com/junegunn/fzf)." #~ msgstr "" #~ msgid "" #~ "Today I pushed v0.1.0 of [remembering](https://remembering.euandreh.xyz), a " #~ "tool to enhance the interactive usability of menu-like tools, such as " #~ "[dmenu](https://tools.suckless.org/dmenu/) and " #~ "[fzf](https://github.com/junegunn/fzf)." #~ msgstr ""