cantino / mcfly

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

Zsh #3

Closed Rxaon closed 4 years ago

Rxaon commented 5 years ago

Awesome!! Any plan on making it available for zsh?

cantino commented 5 years ago

Thanks @Linusero! I don't use zsh, but I think that'd be a pretty simple change. I designed it to be as agnostic as possible. I think you'd just need to port mcfly.bash. Interested in sending a PR?

Rxaon commented 5 years ago

Sure, I will try once I have some time, not so confident about my programming skills though.

cantino commented 5 years ago

Thanks! I'm happy to collaborate and answer questions.

jimeh commented 5 years ago

I created a similar-ish plugin for ZSH (https://github.com/jimeh/zsh-peco-history) for searching history with peco. But I'm curious how mcfly would compare.

So I'd be happy to try and help out with ZSH integration.

@cantino since mcfly doesn't quite seem to work like peco or fzf, would you mind writing up some more detailed documentation about how the mcfly executable itself works, and how you're supposed to interact with it. That would be a great help :)

lervag commented 5 years ago

Seems someone is already working on this now: #8.

cantino commented 5 years ago

peco looks great! Good to know about.

The mcfly executable does a few things, listable with mcfly help. As an integration point, it expects the following:

Given these environment variables, mcfly.bash adds lines to the db with: mcfly add --exit \$__last_exit --append-to-histfile. mcfly uses the exit status provided on the command line and figures out the command based on the last line of $MCFLY_HISTORY. It also appends to $HISTFILE in order to provide backwards compatibility because --append-to-histfile was provided.

When searching, mcfly.bash uses the bind command in mcfly.bash to comment out the current line being typed and to execute mcfly search which brings up the search UI, prefilling it with the last line of $MCFLY_HISTORY, if it contains #mcfly: something.

Please see mcfly.bash for more comments on this flow.

hghwng commented 5 years ago

I'd like to work on the Rust part of the zsh history parser. I have some questions before actually implement it.

  1. Should we rename (and refactor) the bash-related parts, such as bash_history.rs and from_bash_history?

  2. How to detect "zsh mode"? Here're some options:

    1. Detect by $SHELL
    2. Detect by $HISTFILE
    3. Heuristics on file content The "fancy" format is enabled only when EXTENDED_HISTORY is set. Also, it's possible to rename .zhistory. I can't think of a reliable and elegant method.
  3. Where to implement the detection code of "zsh mode"? Depending on the mechanism, sometimes it's better to add a flag to "mcfly add" and let the script do the remaining work. Sometimes everything should be done in the Rust part.

jimeh commented 5 years ago

@cantino Thanks for the detailed explanation :)

So mcfly uses it's own separate internal SQLite database, which is added to each time the prompt command runs, and thats the database that's actually searched through, rather than the contents of any history file on disk right?

And it sounds like mcfly uses the $MCFLY_HISTORY file on disk due to limitations in bash. Please correct me if I'm wrong.

ZSH is a bit more flexible than Bash, and I think you can completely skip having mcfly touching any history files on disk. My peco plugin for example feeds all history into peco via STDIN, which peco then filters, and when you pick an entry inside of peco, all peco itself does is print that to STDOUT, which zsh captures, and puts as the text on your prompt.

Obviously populating the history from scratch on each invocation of ctrl-r would mean the current path is not available. But it should be possible to run a custom command to append to mcfly on each prompt render, without having to worry about mcfly also writing to ZSH's own history file. And any text typed into the prompt when you press ctrl-r is available from ZSH and can be passed to mcfly as a CLI argument, so no need to read it from disk.

Knowing this, I think I'll be able to put together a ZSH plugin for mcfly similar to my zsh-peco-historyf plugin. But a couple of changes might be needed to take full advantage of niceties offered by ZSH:

Also, I have a question:

cantino commented 5 years ago

@hghwng, I think adding a flag to mcfly add is the right approach. Let's not be too smart in our detection in the Rust code. The shell script can tell us.

I think we could use a trait to provide different parsers.

cantino commented 5 years ago

@jimeh

So mcfly uses it's own separate internal SQLite database, which is added to each time the prompt command runs, and thats the database that's actually searched through, rather than the contents of any history file on disk right?

Yup!

And it sounds like mcfly uses the $MCFLY_HISTORY file on disk due to limitations in bash. Please correct me if I'm wrong.

Yes, it's how we figure out the fully escaped text of the most recent command, and also how we figure out what you're searching for if you type some characters before hitting ctrl-r. This avoids bad things if you type backticks or other active characters in the line you're searching for.

ZSH is a bit more flexible than Bash, and I think you can completely skip having mcfly touching any history files on disk. My peco plugin for example feeds all history into peco via STDIN, which peco then filters, and when you pick an entry inside of peco, all peco itself does is print that to STDOUT, which zsh captures, and puts as the text on your prompt.

Nice. Maybe we can encapsulate the weird Bash handling into a trait.

...

Allow passing in the initial search query to the search command via the CLI, and maybe add a specific flag for reading it from the $MCLFY_HISTORY file for use by the bash plugin.

You can do this now. Both search and add take a --command option to pass it in. But be careful of escaping shell characters. https://github.com/cantino/mcfly/blob/master/src/settings.rs

What is MCFLY_SESSION_ID, and why is it needed?

This is how we can identify the context of commands in a terminal window so that we're not conflating commands across sessions.

HarshitKaushik commented 5 years ago

@Linusero @cantino @jimeh

Hi, I would like to contribute to this idea. I was trying mcfly and just got to know that it does not work with zsh. Can I contribute in any way to this?

grrowl commented 5 years ago

@HarshitKaushik You can fork my branch (or just copy the mcfly.zsh file from it) and make a new pull request. It seems zsh's history file format is slightly different, I'm not sure what other fixes to the application may be required.

ericbn commented 5 years ago

@cantino, I'm more than happy with contributing with a Zsh script.

I'm confused about the need of the MCFLY_HISTORY file. Is it required to write all commands to it, even if directly passing them as a parameter to mcfly? (see function below)

A simple Zsh function that would be executed after each command can be:

_mcfly_precmd() {
  local exit_status=${?} # Exit status of last command.
  local last_command=${history[$((HISTCMD - 1))]}
  mcfly add --exit ${exit_status} ${last_command}
}
autoload -Uz add-zsh-hook && add-zsh-hook precmd _mcfly_precmd

We can read the last command directly from the history array, so no need to read/write from any file, not even worry about the .zsh_history file, which Zsh takes care of independently. Another good thing about this approach is that is also nicely handles multi-line commands, which would be more complex to read from a file.

So another question I have is how does mcfly handle multi-line commands? Like

% print 'Line 1
Line 2'
cantino commented 5 years ago

@ericbn As long as you can pass the command to mcfly using the --command option and escape it properly, I don't think mcfly needs to read from MCFLY_HISTORY.

ishitatsuyuki commented 5 years ago

@ericbn Has there been any progress? Is there something I can help?

jimeh commented 5 years ago

I've been a bit too busy the past couple of months, but I still intend to take a proper stab at this based on my zsh plugin for peco at some point in the next few weeks.

Mcfly looks very promising, and I'm very keen to try it out properly within my setup :)

xsteve commented 5 years ago

I would really love to see zsh support fro mcfly...

frankenstein91 commented 5 years ago

It sounds very interesting and I like to use the ZSH very much. Is there already an update for the project? Perhaps there are already successes with https://github.com/cantino/mcfly/pull/8?

qazip commented 5 years ago

Oh man, I just installed this and only after did I notice that it doesn't support zsh! I am also looking forward for zsh support!

cantino commented 4 years ago

I have basic Zsh support working now if a few folks could test it out and share their thoughts: https://github.com/cantino/mcfly/pull/81

infokiller commented 4 years ago

Thanks a lot for implementing this @cantino! I tested it and left a few comments about the zsh implementation in the PR.