= remembering(1) == NAME remembering - add memory to dmenu, fzf and similar menu tools. == SYNOPSYS *remembering* [_-p PROFILE_] -- _COMMAND_... == EXAMPLES === A dmenu launcher that learns [source,sh] .... $ printf 'firefox\nmpv\nmutt\n' | remembering -p apps -- dmenu .... The first time, the menu comes up alphabetical. Pick `mutt` a few times and it comes up first. === Open a file with fzf, most-used first [source,sh] .... $ ls | remembering -- fzf .... Without _-p_, the profile is derived from the current directory, so every directory gets its own ranking with no setup. == DESCRIPTION *remembering* sits between a list of choices and the menu tool that picks from them. It reads the choices from _stdin_, feeds them to _COMMAND_ sorted by how often each one was picked before, takes what _COMMAND_ prints as the pick, bumps that pick's count in the profile, and prints the pick. The lines on _stdin_ define what is offered: the profile only ranks them. Most-picked lines come first; ties are broken in byte order; never-picked lines keep their byte order at the bottom. The pick does not have to be one of the offered lines --- whatever _COMMAND_ prints is learnt, so menu tools that accept free text (such as `dmenu`) grow new entries on first use. Lines that were offered but never picked are remembered with a count of zero, and profile entries that stop appearing on _stdin_ are kept --- the profile accumulates the universe of choices it has seen. The profile is rewritten atomically (a sibling `.tmp` file plus rename), so a crash never leaves a half-written profile. *remembering* is transparent in pipelines: _COMMAND_'s _stderr_ (where dmenu and fzf draw their interface) passes through, and its exit status is forwarded. A cancelled menu --- a nonzero exit --- aborts the run with the same status and learns nothing. A successful run that picks nothing (empty output) also learns nothing, and exits 0. == OPTIONS *-p* _PROFILE_:: The profile name to gather and store the ranking under (default: the current directory, with every `/` turned into `!`). The attached getopts form (`-pPROFILE`) is accepted too. == IO === STDIN The menu choices, one per line, in any order. === STDOUT The pick, when there is one, followed by a newline. _COMMAND_'s own output is captured, not echoed. === STDERR _COMMAND_'s _stderr_, passed through untouched, and error messages. === INPUT AND OUTPUT FILES The profile, at: [source,sh] .... ${XDG_DATA_HOME:-$HOME/.local/share}/remembering/$PROFILE .... It is a plain text file with one line per known choice: [source,sh] .... 2 profile firefox 0 profile mpv 7 profile mutt .... The count comes first, the literal word `profile` second, and the choice's text --- spaces included --- runs to the end of the line. Lines are kept in byte order, with a newly learnt pick appended at the end. The file is made to be hand-edited: delete a line to forget it, edit a count to re-rank it. == EXIT STATUS 0:: The pick was learnt and printed, or there was nothing to learn (empty pick). 1:: A runtime error, such as an unreadable or unwritable profile. 2:: Usage error: an unknown option, or a missing _COMMAND_. Otherwise, _COMMAND_'s own nonzero exit status, forwarded as-is (or 128 plus the signal number when it was killed by a signal). == SEE ALSO dmenu(1), fzf(1), sort(1) == AUTHORS mailto:eu@euandre.org[EuAndreh] and contributors. == BUGS * Report bugs to the mailto:~euandreh/public-inbox@lists.sr.ht[mailing list]. Use the subject "[remembering] BUG or TASK: ". * Browse bugs https://euandre.org/git/remembering/TODOs.html[online]. * https://euandre.org/git/remembering/[Homepage]. * https://lists.sr.ht/~euandreh/public-inbox?search=%5Bremembering%5D[Comments and discussions].