camdencheek / fre

Command line frecency tracking
MIT License
121 stars 8 forks source link

fre appends $PWD to arguments on --add #7

Closed mwgkgk closed 5 years ago

mwgkgk commented 5 years ago

Problem: fre saves input as absolute path, which conflicts with using it for non-path things like commands.

#!/bin/dash

set -o errexit
set -o nounset

repls() {
    echo "rlwrap sbcl"
    echo "rlwrap dash"
    echo "bash"
    echo "clisp"
    echo "guile"
    echo "iex"
    echo "python"
}

# Default store location is ~/.local/share/fre/
store_name=$(echo "cmd:$0" | md5sum | awk '{print $1}')

fzf_result=$({
    fre --sorted --store_name "$store_name"
    repls
} | awk '!x[$0]++' | fzf -m --reverse --height 15 --tiebreak=index)

if test -n "$fzf_result"; then
    fre --add "$fzf_result" --store_name "$store_name" && echo "$fzf_result"
fi

Here, $fzf_result would be something like rlwrap sbcl, but fre's suggestion on subsequent reruns would include $PWD, like so: /home/username/rlwrap sbcl.

(awk '!x[$0]++' trick is to avoid sort | uniq )

camdencheek commented 5 years ago

I would definitely like this to be usable for more than just directories / files. It seems to me that for the directories/files part to be usable, absolutizing the path is necessary.

Thoughts on a flag that enables or disables absolutizing paths? For example, fre --no-absolutize --add rlwrap sbcl.

Also, I like the awk trick. I literally wrote an entire uniq replacement to do exactly this (plus some other fun features)

mwgkgk commented 5 years ago

One way of doing this would be to not make dirs the default case and add $PWD to store's paths, which would also be named probably something other than paths. Thus the selection itself would be relative. On purge, append it to pwd.

To know which paths are purge'able, it would probably still need a --switch however. Changing the default case to fre --add ~/dir1 --path does not sound super amazing. Need to sort of meditate on this, to come up with a long(er)-term design before more people start using it :) Maybe some other, similar usecases can be found in the wild, to at least have a reference for the flag name: fre --add "orange" --not-a-path. Perhaps --no-absolutize is good enough. (What I don't like about it is exposing the underlying mechanic, which normally would change more often than the api for the users). Also, say, -p and -P for --path and --nopath.

Do we need to know if it's a path for reasons other than purge? If not, the flag could be --nopurge, or something - this sort of conveys a different meaning however, but could work for this usecase combined with splitting the path into relative and pwd. This sort of sounds like a bad idea. Can we theoretically purge things other than non-existent paths? Truncate exists to purge stale entries.

Can we have distinct behaviors for things other than paths? Here I hardcode the fact that it's a cmd, file or a dir into the store name hash, (which is probably overkill as they shouldn't overlap) - but this could be something like --type cmd, with an arbitrary-ish type, whereas the default would be --type path. What are the possible types that could be important for fre to know? Urls? Things on $PATH? Both could have a purge mechanic, which makes me bearish on --nopurge flag upon --add, from above paragraph.

One of the sources on what could be fre'able are the plugins to unite / denite. So, things like colorschemes, file extensions, file lines, jump history, (btw shell history for regular fzf), commits, tags. Ideally there would be some sort of predicate to be passed to purge.

Need some more brain input on this :) Went a little overboard here with the edits, apologize for the notification spam.

camdencheek commented 5 years ago

I really appreciate the input. It sounds like you're imagining a very general implementation of fre, almost more like a mini "frecency database" rather than a commandline navigation tool.

When I initially started developing this, it was definitely only with paths in mind (I just wanted to replace autojump). Maybe files too since most of the commands are the same. However, I like the idea of making it more general so that it could be used for things like command history, colorschemes, etc. It seems more elegant and intuitive to have no use-case-specific behavior embedded in the tool.

With that in mind, I would consider getting rid of --purge entirely and leaving that to the user. They could just run something like like IFS=$'\n'; for file in $(fre --sorted) ; do [ -e "$file" ] && echo "$file"; done | xargs fre --remove {}.

If that were the case, it would also be the responsibility of the user to store the paths in absolute format so they can jump to them from any directory. For example, storing the path ./dir wouldn't do much good because cd ./dir means something different depending on the current directory. This could be done in the shell integrations though. Something like fre --add "$(realpath $path)".

Is there a reason you're hashing the store name? I included splitting out stores by name so people could have separate stores for separate things (I have a directories one and a files one). I'm not sure I see what adding a --type cmd option would add unless you think it would be better to have a single store file which is just partitioned by type.

So, right now, I would lean towards removing purge and absolutize entirely to make it more general. Going that path though, I'd likely want to include some shell script wrappers or suggested commands or something to include application-specific use cases.

Let me know what you think!

mwgkgk commented 5 years ago

Removing --purge sounds sensible! Also indeed it's already time to start building up a wiki of fre(-related) recipes like the purge one :)

Not having a --type makes perfect sense. I split each type of query into different store because otherwise an inappropriate path would be mixed in with find results. As in, I start fd+fzf+fre at different points in the filesystem. Same applies for cmd's. Having the ability to name the store is 100% sufficient for this.

Leaving the necessary realpath'ing to the user is I feel sensible and elegant.

camdencheek commented 5 years ago

8 removes --purge and the relative path expansion, which should take care of this. I'll leave it open for a bit for comments

mwgkgk commented 5 years ago

Confirmed: works as expected! The recipe from the opening post works without changes.

Hope wasn't too much trouble. Enjoyed working with you.