Closed Rxaon closed 4 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?
Sure, I will try once I have some time, not so confident about my programming skills though.
Thanks! I'm happy to collaborate and answer questions.
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 :)
Seems someone is already working on this now: #8.
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:
$HISTFILE
to point to the shell's default history file to be imported (when there's no history in mcfly's sqlite3 DB), cleaned if you use the F2 command in the UI, and appended to if you provide the --append-to-histfile
option when running mcfly add
.$MCFLY_HISTORY
, the shell history file to read from when adding or searching. This is set to a temporary file by mcfly.bash
. mcfly
uses this file both to save commands to the DB (by taking the last line as the most recent command) and to figure out what you're searching for if you hit ctrl-r
after having typed a bit (again by taking the last line after stripping off the leading #mcfly:
.)$PWD
the current directoryGiven 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.
I'd like to work on the Rust part of the zsh history parser. I have some questions before actually implement it.
Should we rename (and refactor) the bash-related parts, such as bash_history.rs
and from_bash_history
?
How to detect "zsh mode"? Here're some options:
$SHELL
$HISTFILE
EXTENDED_HISTORY
is set. Also, it's possible to rename .zhistory
. I can't think of a reliable and elegant method.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.
@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:
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.MCFLY_HISTORY
an optional environment variable, as I believe it's not needed for ZSH as we can capture and pass in the initial search query as a CLI argument.HISTFILE
an optional environment variable, and maybe rename it to BASH_HISTFILE
, so a separate ZSH_HISTFILE
env var can be used for importing ZSH history. And only import history if the relevant env var is set.Also, I have a question:
MCFLY_SESSION_ID
, and why is it needed?@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.
@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.
@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?
@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.
@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'
@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
.
@ericbn Has there been any progress? Is there something I can help?
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 :)
I would really love to see zsh support fro mcfly...
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?
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!
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
Thanks a lot for implementing this @cantino! I tested it and left a few comments about the zsh implementation in the PR.
Awesome!! Any plan on making it available for zsh?