A port of the wildly popular helper application autojump to Rust.
As this project is technically a fork, the license is the same as autojump,
which is GPL, either version 3 or any later version. See LICENSE
for details.
The package is a drop-in replacement of autojump. Assuming autojump is
already installed, or at least the shell script part of it has been properly
set up, and you have in $PATH ~/.cargo/bin before the system binary
locations, all you have to do is:
cargo install autojump
# tell the shell to forget about previous location of autojump
hash -r(Manually cloning the repository and building is okay, of course.)
Why do a port when the original version works? Primarily for two reasons:
- The author is really tired of
autojumpbreakage inside Python virtualenvs, and - Rust is simply awesome for CLI applications, with its performance and (code) slickness!
Indeed, being written in a compiled language, autojump-rs is very light on
modern hardware. As the program itself is very short-running, the overhead of
setting up and tearing down a whole Python VM could be overwhelming,
especially on less capable hardware. With autojump-rs this latency is
greatly reduced. Typical running time is like this on the author's Core
i7-2670QM laptop, with a directory database of 256 entries:
$ time ./autojump/bin/autojump au
/home/xenon/src/autojump-rs
./autojump/bin/autojump au 0.05s user 0.02s system 96% cpu 0.080 total
$ time ./autojump-rs/target/release/autojump au
/home/xenon/src/autojump-rs
./autojump-rs/target/release/autojump au 0.02s user 0.00s system 94% cpu 0.020 total
The time savings are more pronounced on less powerful hardware, where every cycle shaved off counts. On a Loongson 3A2000 box running at 1.0 GHz the timings are like this, with a database of the same size:
$ time ./autojump/bin/autojump au
/opt/store/src/autojump-rs
./autojump/bin/autojump au 0.15s user 0.02s system 97% cpu 0.178 total
$ time ./autojump-rs/target/release/autojump au
/opt/store/src/autojump-rs
./autojump-rs/target/release/autojump au 0.04s user 0.01s system 96% cpu 0.051 total
And, of course, the program no longer interacts with Python in any way, so the
virtualenv-related crashes are no more. Say goodbye to the dreaded
ImportError's showing every $PS1 in a virtualenv with the system-default
Python!
# bye and you won't be missed!
Traceback (most recent call last):
File "/usr/lib/python-exec/python2.7/autojump", line 43, in <module>
from autojump_data import dictify
ImportError: No module named autojump_data
All of the command line flags and arguments are now implemented, and behave
exactly like the original. Being a drop-in replacement, all other shell
features like tab completion should work too. (Except jc and jco; see
below.)
As for the text database, the on-disk format should be identical. (Actually there is a little difference in the representation of floats, but it doesn't matter.) However, as the author is developing and using this on Linux, other platforms may need a little more love, although all the libraries used are lovingly cross-platform. (Patches are welcome, of course!)
The Windows batch files shipped with the original autojump has Python
hard-coded into them, and obviously that won't work with autojump-rs.
Use the batch files in the windows directory instead; just replacing the
original files and putting autojump.exe along with them should work.
(Thanks @tomv564 for the Windows testing!)
That said, there're some IMO very minor deviations from the original Python implementation. These are:
-
Argument handling and help messages.
Original
autojumpuses Python'sargparseto parse its arguments. There is a Rust port of it, but it's nowhere as popular as thedocopt.rslibrary, as is shown incrates.iostatistics and GitHub activities. So it's necessary to re-arrange the help messages at least, as thedocoptfamily of argument parsers mandate a specific style for them. However this shouldn't be any problem, just that it's different. Again, who looks at the usage screen all the day? XD -
Different algorithm chosen for fuzzy matching.
The Python version uses the
difflib.SequenceMatcheralgorithm for its fuzzy matches. Since it's quite a bit of complexity, I chose to leverage thestrsimlibrary instead. The Jaro-Winkler distance is computed between every filename and the last part of query needles respectively, and results are filtered based on that. -
jcmay jump outside current directory.Exact reason may be different filtering logic involved, but I'm not very sure about this one. The behavior is also observed on original
autojump, but the frequency seems to be lower, and both implementations actually don't check if the target is below current directory. However I only use plainjmostly, so if you're heavily reliant onjcand its friends please open an issue!
Now that platform support is mostly considered okay, next steps would be
more refactoring and bug fixing. The jc behavior differences are observed
on original autojump too, in that you could jump outside $(pwd), but the
actual directory jumped to is different; this needs further investigation.
Hell I even want to write a fasd backend too, but I don't presently have
that much free time. Anyway, contributions and bug reports are welcome!