cantino / mcfly

Fly through your shell history. Great Scott!
MIT License
6.87k stars 177 forks source link

fish: how easy/hard would it be to add support for fish shell #89

Closed mfrw closed 4 years ago

mfrw commented 4 years ago

Hi, i am wondering would it possible to make it work with fish shell. I am planning to take a stab at it, if the author does not have any issue :)

zicklag commented 4 years ago

If it makes any difference, I'd probably use this if it supported fish. :) :+1:

cantino commented 4 years ago

I don't personally use fish but I'd gladly accept pull requests! Hopefully you can look at the bash and zsh integrations as a starting point, and I'm happy to answer questions.

mfrw commented 4 years ago

I don't personally use fish but I'd gladly accept pull requests! Hopefully you can look at the bash and zsh integrations as a starting point, and I'm happy to answer questions.

Thank you very much :) Will go through the bash/zsh impls

tjkirch commented 4 years ago

I gave it a shot and have fish support working through a mcfly.fish file you source. It doesn't allow you to import/remove commands from history yet, because the Rust code doesn't understand the fish history format, so I'll work on that next.

(Should #10 be closed since this issue has a little more recent traction?)

zicklag commented 4 years ago

Sweet I'll test it out once the PR is up!

cantino commented 4 years ago

Awesome! Yes, I'll close #10.

tjkirch commented 4 years ago

Quick update. I have fish history import working now as well, and everything's fine in fish 2.7 and 3.1. History deletion is trickier, but I have an idea.

A little background is necessary. fish has a structured history file (almost, but not quite, YAML) with entries that store command, time, and any relevant paths. 256K of these entries can be stored before the oldest start being purged; commands are automatically deduplicated. This rotation/deduplication happens automatically every handful of commands. (If you run ~10-20 distinct commands, you should see it by then.)

In short, it's a little more dynamic than bash/zsh, and it makes me uncomfortable reading, editing, and replacing the file. You could lose history if fish did an update in the middle of mcfly's update. I had initially implemented the naive method and saw surprising results during that cleanup. (And the format is just more complex, so I was worried anyway.)

What you really want to do is have fish handle history deletion itself. And we're already sending commands out to fish - in that respect, it's like mcfly.zsh, which saves mcfly search output to a temp file and interprets the results as commands.

So, my idea is to extend those output commands a bit. Currently, the first line of output is a "mode", either run or display, that says whether to run the selected command or just continue to edit it. The second line is the updated command line, if any. I'd like to extend this by prefixing them with mode and commandline, respectively, and adding a new type of command, delete, where the rest of the line represents an exact command that should be removed from history. (Specific line numbers would no longer matter; we have context from the prefix instead.)

mcfly.zsh would be easy to update with such a scheme - just to understand the prefixes, I don't think it has any fancy history deletion methods, just edits to HISTFILE or fc -R/W.

My worry is that I don't have a full understanding of how mcfly.bash works, so I'm not sure if this would interfere with it. How are changed commandlines showing up in bash? How does bash know to run something when you hit enter in McFly? I don't see anything happening after the invocation of mcfly search in the bind, and I don't think bash is interpreting the display/run output, or at least I couldn't find anything talking about that... I'll find out quick enough tomorrow when I test, if no one jumps in about that.

tjkirch commented 4 years ago

Oh, silly me, mcfly.bash doesn't use the -o feature of search :) So, I'm still not sure what that bash bind is doing to update/run commands, but I'm confident the -o output could be updated and work well for zsh and fish, accomplishing the goal above.

tjkirch commented 4 years ago

I believe it's the "fake typer" that forces bash to run a selected command: https://github.com/cantino/mcfly/blob/422557e1ba48c33c5753262bd294bf3e92a40476/src/main.rs#L61-L63 And I believe what updates the commandline itself is just the output of the mcfly search, since it's not being written to a file in that case. Simpler than I thought, modulo the fake typer :)

I just wanted to be confident that I wouldn't affect other shells. I'm almost done for fish.

cantino commented 4 years ago

You're both correct. I couldn't get the fake typer approach to work with zsh and added the -o option. It should be safe to extend it.

tjkirch commented 4 years ago

Pull request for fish support is at #95.