mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2024-12-29 12:32:40 +00:00
commit
128413e45f
145
Cargo.lock
generated
145
Cargo.lock
generated
@ -8,6 +8,11 @@ dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
@ -33,26 +38,6 @@ name = "autocfg"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.11.0"
|
||||
@ -87,11 +72,6 @@ name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
@ -146,26 +126,6 @@ dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
@ -185,6 +145,14 @@ dependencies = [
|
||||
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.8"
|
||||
@ -203,6 +171,30 @@ name = "libc"
|
||||
version = "0.2.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.9"
|
||||
@ -245,11 +237,6 @@ dependencies = [
|
||||
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.104"
|
||||
@ -273,6 +260,28 @@ name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.16"
|
||||
@ -284,14 +293,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
name = "syn-mid"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -302,6 +310,11 @@ dependencies = [
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
@ -317,6 +330,11 @@ name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
@ -343,58 +361,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "zoxide"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
|
||||
"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8"
|
||||
"checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35"
|
||||
"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
|
||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
"checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b"
|
||||
"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
|
||||
"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
||||
"checksum proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
|
||||
"checksum proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
|
||||
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
|
||||
"checksum structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
|
||||
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
|
||||
"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
|
||||
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "zoxide"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
authors = ["Ajeet D'Souza <98ajeet@gmail.com>"]
|
||||
description = "A cd command that learns your habits"
|
||||
repository = "https://github.com/ajeetdsouza/zoxide/"
|
||||
@ -13,12 +13,13 @@ license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.26"
|
||||
bincode = "1.2.1"
|
||||
clap = "2.33.0"
|
||||
dirs = "2.0.2"
|
||||
failure = "0.1.7"
|
||||
fs2 = "0.4.3"
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
structopt = "0.3.11"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
44
README.md
44
README.md
@ -1,6 +1,7 @@
|
||||
# zoxide
|
||||
|
||||
[![crates.io](https://img.shields.io/crates/v/zoxide)](https://crates.io/crates/zoxide)
|
||||
![.github/workflows/release.yml](https://github.com/ajeetdsouza/zoxide/workflows/.github/workflows/release.yml/badge.svg)
|
||||
|
||||
A cd command that learns your habits
|
||||
|
||||
@ -12,6 +13,7 @@ A cd command that learns your habits
|
||||
- [Installing `zoxide`](#installing-zoxide)
|
||||
- [Adding `zoxide` to your shell](#adding-zoxide-to-your-shell)
|
||||
- [zsh](#zsh)
|
||||
- [bash](#bash)
|
||||
- [fish](#fish)
|
||||
- [Configuration](#configuration)
|
||||
- [Environment variables](#environment-variables)
|
||||
@ -58,52 +60,30 @@ If you want the interactive fuzzy selection feature, you will also need to insta
|
||||
|
||||
### Step 2: Adding `zoxide` to your shell
|
||||
|
||||
By default, `zoxide` defines the `z`, `zi`, `za`, `zq`, and `zr` aliases. If you'd like to go with just the barebones `z`, pass the `--no-define-aliases` flag to `zoxide init`.
|
||||
|
||||
#### zsh
|
||||
|
||||
Using [antibody](https://github.com/getantibody/antibody):
|
||||
Add the following line to your `~/.zshrc`:
|
||||
|
||||
```sh
|
||||
antibody bundle ajeetdsouza/zoxide
|
||||
eval "$(zoxide init zsh)"
|
||||
```
|
||||
|
||||
Using [zinit](https://github.com/zdharma/zinit):
|
||||
#### bash
|
||||
|
||||
Add the following line to your `~/.bashrc`:
|
||||
|
||||
```sh
|
||||
zinit light ajeetdsouza/zoxide
|
||||
eval "$(zoxide init bash)"
|
||||
```
|
||||
|
||||
Using [antigen](https://github.com/zsh-users/antigen):
|
||||
|
||||
```sh
|
||||
antigen bundle ajeetdsouza/zoxide
|
||||
```
|
||||
|
||||
Using [zgen](https://github.com/tarjoilija/zgen):
|
||||
|
||||
```sh
|
||||
zgen load ajeetdsouza/zoxide
|
||||
```
|
||||
|
||||
Using [zplug](https://github.com/zplug/zplug):
|
||||
|
||||
```sh
|
||||
zplug "ajeetdsouza/zoxide"
|
||||
```
|
||||
|
||||
If you'd rather not use a package manager, add the contents of [zoxide.plugin.zsh](zoxide.plugin.zsh) to your `.zshrc`.
|
||||
|
||||
#### fish
|
||||
|
||||
Using [fisher](https://github.com/jorgebucaran/fisher):
|
||||
Add the following line to your `~/.config/fish/config.fish`:
|
||||
|
||||
```sh
|
||||
fisher add ajeetdsouza/zoxide
|
||||
```
|
||||
|
||||
Using [oh-my-fish](https://github.com/oh-my-fish/oh-my-fish):
|
||||
|
||||
```sh
|
||||
omf install https://github.com/ajeetdsouza/zoxide
|
||||
zoxide init fish | source
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
@ -1,22 +0,0 @@
|
||||
function z
|
||||
set -l argc (count $argv)
|
||||
if test $argc -gt 0
|
||||
if test $argc -eq 1 -a "$argv[1]" = "-"
|
||||
cd -
|
||||
commandline -f repaint
|
||||
else
|
||||
set _Z_RESULT (zoxide query $argv)
|
||||
switch "$_Z_RESULT"
|
||||
case 'query: *'
|
||||
cd (string sub -s 8 -- "$_Z_RESULT")
|
||||
commandline -f repaint
|
||||
case '*'
|
||||
echo -n "$_Z_RESULT"
|
||||
end
|
||||
end
|
||||
else
|
||||
cd ~
|
||||
commandline -f repaint
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1 @@
|
||||
function zoxide-add --on-event fish_prompt
|
||||
zoxide add
|
||||
end
|
||||
|
||||
abbr -a zi "z -i"
|
||||
abbr -a za "zoxide add"
|
||||
abbr -a zq "zoxide query"
|
||||
abbr -a zr "zoxide remove"
|
||||
zoxide init fish | source
|
||||
|
@ -1,36 +0,0 @@
|
||||
use crate::error::AppError;
|
||||
use crate::types::Rank;
|
||||
use failure::{bail, ResultExt};
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
|
||||
pub const ZO_DATA: &str = "_ZO_DATA";
|
||||
pub const ZO_MAXAGE: &str = "_ZO_MAXAGE";
|
||||
|
||||
pub fn get_zo_data() -> Result<OsString, failure::Error> {
|
||||
let path = match env::var_os(ZO_DATA) {
|
||||
Some(path) => path,
|
||||
None => {
|
||||
let mut path = dirs::home_dir().ok_or_else(|| AppError::GetHomeDirError)?;
|
||||
path.push(".zo");
|
||||
path.into_os_string()
|
||||
}
|
||||
};
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
pub fn get_zo_maxage() -> Result<Rank, failure::Error> {
|
||||
if let Some(maxage_osstr) = env::var_os(ZO_MAXAGE) {
|
||||
match maxage_osstr.to_str() {
|
||||
Some(maxage_str) => {
|
||||
let maxage = maxage_str
|
||||
.parse::<Rank>()
|
||||
.with_context(|_| AppError::EnvError(ZO_MAXAGE.to_owned()))?;
|
||||
Ok(maxage)
|
||||
}
|
||||
None => bail!(AppError::EnvError(ZO_MAXAGE.to_owned())),
|
||||
}
|
||||
} else {
|
||||
Ok(5000.0)
|
||||
}
|
||||
}
|
136
src/db.rs
136
src/db.rs
@ -1,67 +1,85 @@
|
||||
use crate::config::get_zo_maxage;
|
||||
use crate::dir::Dir;
|
||||
use crate::error::AppError;
|
||||
use crate::types::{Rank, Timestamp};
|
||||
use failure::ResultExt;
|
||||
use crate::util::get_zo_maxage;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use fs2::FileExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use std::io::{self, BufReader, BufWriter};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct DB {
|
||||
pub dirs: Vec<Dir>,
|
||||
path: PathBuf,
|
||||
path_tmp: PathBuf,
|
||||
|
||||
#[serde(skip)]
|
||||
pub modified: bool,
|
||||
file_tmp: File,
|
||||
|
||||
dirs: Vec<Dir>,
|
||||
modified: bool,
|
||||
}
|
||||
|
||||
impl DB {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<DB, failure::Error> {
|
||||
match File::open(path) {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<DB> {
|
||||
let path = path.as_ref().to_path_buf();
|
||||
|
||||
let mut path_tmp = path.clone();
|
||||
path_tmp.set_file_name(".zo.tmp");
|
||||
|
||||
let file_tmp = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&path_tmp)
|
||||
.with_context(|| anyhow!("could not open temporary database"))?;
|
||||
|
||||
file_tmp
|
||||
.lock_exclusive()
|
||||
.with_context(|| anyhow!("could not lock temporary database"))?;
|
||||
|
||||
let dirs = match File::open(&path) {
|
||||
Ok(file) => {
|
||||
file.lock_shared()
|
||||
.with_context(|_| AppError::FileLockError)?;
|
||||
let rd = BufReader::new(file);
|
||||
let db = DB::read_from(rd).with_context(|_| AppError::DBReadError)?;
|
||||
Ok(db)
|
||||
let rd = BufReader::new(&file);
|
||||
bincode::deserialize_from(rd)
|
||||
.with_context(|| anyhow!("could not deserialize database"))?
|
||||
}
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::NotFound => Ok(DB::default()),
|
||||
_ => Err(err).with_context(|_| AppError::FileOpenError)?,
|
||||
io::ErrorKind::NotFound => Vec::<Dir>::new(),
|
||||
_ => return Err(err).with_context(|| anyhow!("could not open database")),
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Ok(DB {
|
||||
path,
|
||||
path_tmp,
|
||||
file_tmp,
|
||||
dirs,
|
||||
modified: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn save<P: AsRef<Path>>(&mut self, path: P) -> Result<(), failure::Error> {
|
||||
pub fn save(&mut self) -> Result<()> {
|
||||
if self.modified {
|
||||
let file = File::create(path).with_context(|_| AppError::FileOpenError)?;
|
||||
file.lock_exclusive()
|
||||
.with_context(|_| AppError::FileLockError)?;
|
||||
let wr = BufWriter::new(file);
|
||||
self.write_into(wr)
|
||||
.with_context(|_| AppError::DBWriteError)?;
|
||||
self.file_tmp
|
||||
.set_len(0)
|
||||
.with_context(|| "could not truncate temporary database")?;
|
||||
|
||||
let wr = BufWriter::new(&self.file_tmp);
|
||||
bincode::serialize_into(wr, &self.dirs)
|
||||
.with_context(|| anyhow!("could not serialize database"))?;
|
||||
fs::rename(&self.path_tmp, &self.path)
|
||||
.with_context(|| anyhow!("could not move temporary database"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_from<R: Read>(rd: R) -> Result<DB, bincode::Error> {
|
||||
bincode::deserialize_from(rd)
|
||||
}
|
||||
|
||||
pub fn write_into<W: Write>(&self, wr: W) -> Result<(), bincode::Error> {
|
||||
bincode::serialize_into(wr, &self)
|
||||
}
|
||||
|
||||
pub fn add<P: AsRef<Path>>(&mut self, path: P, now: Timestamp) -> Result<(), failure::Error> {
|
||||
pub fn add<P: AsRef<Path>>(&mut self, path: P, now: Timestamp) -> Result<()> {
|
||||
let path_abs = path
|
||||
.as_ref()
|
||||
.canonicalize()
|
||||
.with_context(|_| AppError::PathAccessError)?;
|
||||
let path_str = path_abs.to_str().ok_or_else(|| AppError::UnicodeError)?;
|
||||
.with_context(|| anyhow!("could not access directory: {}", path.as_ref().display()))?;
|
||||
|
||||
let path_str = path_abs
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid unicode in path: {}", path_abs.display()))?;
|
||||
|
||||
match self.dirs.iter_mut().find(|dir| dir.path == path_str) {
|
||||
None => self.dirs.push(Dir {
|
||||
@ -92,8 +110,6 @@ impl DB {
|
||||
}
|
||||
|
||||
pub fn query(&mut self, keywords: &[String], now: Timestamp) -> Option<Dir> {
|
||||
// TODO: expand "~" in queries
|
||||
|
||||
loop {
|
||||
let (idx, dir) = self
|
||||
.dirs
|
||||
@ -111,12 +127,29 @@ impl DB {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<(), failure::Error> {
|
||||
let path_abs = path
|
||||
.as_ref()
|
||||
.canonicalize()
|
||||
.with_context(|_| AppError::PathAccessError)?;
|
||||
let path_str = path_abs.to_str().ok_or_else(|| AppError::UnicodeError)?;
|
||||
pub fn query_all(&mut self, mut keywords: Vec<String>) -> Vec<Dir> {
|
||||
self.remove_invalid();
|
||||
|
||||
for keyword in &mut keywords {
|
||||
keyword.make_ascii_lowercase();
|
||||
}
|
||||
|
||||
self.dirs
|
||||
.iter()
|
||||
.filter(|dir| dir.is_match(&keywords))
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||
let path_abs = match path.as_ref().canonicalize() {
|
||||
Ok(path_abs) => path_abs,
|
||||
Err(_) => path.as_ref().to_path_buf(),
|
||||
};
|
||||
|
||||
let path_str = path_abs
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid unicode in path"))?;
|
||||
|
||||
if let Some(idx) = self.dirs.iter().position(|dir| dir.path == path_str) {
|
||||
self.dirs.remove(idx);
|
||||
@ -126,11 +159,10 @@ impl DB {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_invalid(&mut self) {
|
||||
let dirs_len = self.dirs.len();
|
||||
self.dirs.retain(|dir| dir.is_dir());
|
||||
|
||||
if self.dirs.len() != dirs_len {
|
||||
fn remove_invalid(&mut self) {
|
||||
let orig_len = self.dirs.len();
|
||||
self.dirs.retain(Dir::is_dir);
|
||||
if orig_len != self.dirs.len() {
|
||||
self.modified = true;
|
||||
}
|
||||
}
|
||||
|
18
src/dir.rs
18
src/dir.rs
@ -2,7 +2,7 @@ use crate::types::{Rank, Timestamp};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Dir {
|
||||
pub path: String,
|
||||
pub rank: Rank,
|
||||
@ -17,16 +17,14 @@ impl Dir {
|
||||
pub fn is_match(&self, query: &[String]) -> bool {
|
||||
let path = self.path.to_ascii_lowercase();
|
||||
|
||||
if let Some(dir_name) = Path::new(&path).file_name() {
|
||||
if let Some(query_last) = query.last() {
|
||||
if let Some(query_dir_name) = Path::new(query_last).file_name() {
|
||||
// `unwrap()` here should be safe because the values are already encoded as UTF-8
|
||||
let dir_name_str = dir_name.to_str().unwrap().to_ascii_lowercase();
|
||||
let query_dir_name_str = query_dir_name.to_str().unwrap().to_ascii_lowercase();
|
||||
if let Some(query_name) = query.last().and_then(|word| Path::new(word).file_name()) {
|
||||
if let Some(path_name) = Path::new(&path).file_name() {
|
||||
// `unwrap()` here should be safe because the values are already encoded as UTF-8
|
||||
let query_name = query_name.to_str().unwrap();
|
||||
let path_name = path_name.to_str().unwrap();
|
||||
|
||||
if !dir_name_str.contains(&query_dir_name_str) {
|
||||
return false;
|
||||
}
|
||||
if !path_name.contains(&query_name) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
src/error.rs
35
src/error.rs
@ -1,35 +0,0 @@
|
||||
use failure::Fail;
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum AppError {
|
||||
#[fail(display = "found invalid UTF-8 code sequence")]
|
||||
UnicodeError,
|
||||
|
||||
#[fail(display = "system clock is set to invalid time")]
|
||||
SystemTimeError,
|
||||
|
||||
#[fail(display = "unable to open database file")]
|
||||
FileOpenError,
|
||||
#[fail(display = "unable to lock database file")]
|
||||
FileLockError,
|
||||
|
||||
#[fail(display = "could not read from database")]
|
||||
DBReadError,
|
||||
#[fail(display = "could not write to database")]
|
||||
DBWriteError,
|
||||
|
||||
#[fail(display = "could not launch fzf")]
|
||||
FzfLaunchError,
|
||||
#[fail(display = "could not communicate with fzf")]
|
||||
FzfIoError,
|
||||
|
||||
#[fail(display = "could not retrieve home directory")]
|
||||
GetHomeDirError,
|
||||
#[fail(display = "could not retrieve current directory")]
|
||||
GetCurrentDirError,
|
||||
#[fail(display = "could not access path")]
|
||||
PathAccessError,
|
||||
|
||||
#[fail(display = "could not decode ${} in env", 0)]
|
||||
EnvError(String),
|
||||
}
|
306
src/main.rs
306
src/main.rs
@ -1,20 +1,53 @@
|
||||
mod config;
|
||||
mod db;
|
||||
mod dir;
|
||||
mod error;
|
||||
mod types;
|
||||
mod util;
|
||||
|
||||
use crate::config::get_zo_data;
|
||||
use crate::db::DB;
|
||||
use crate::error::AppError;
|
||||
use crate::types::Timestamp;
|
||||
use crate::util::{fzf_helper, get_current_time};
|
||||
use clap::{app_from_crate, crate_authors, crate_description, crate_name, crate_version};
|
||||
use clap::{App, Arg, SubCommand};
|
||||
use failure::ResultExt;
|
||||
use crate::util::{fzf_helper, get_current_time, get_db};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use clap::arg_enum;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use structopt::StructOpt;
|
||||
|
||||
// TODO: use structopt to parse env variables: <https://github.com/TeXitoi/structopt/blob/master/examples/env.rs>
|
||||
|
||||
arg_enum! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
enum Shell {
|
||||
bash,
|
||||
fish,
|
||||
zsh,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(about = "A cd command that learns your habits")]
|
||||
enum Zoxide {
|
||||
#[structopt(about = "Add a new directory or increment its rank")]
|
||||
Add { path: Option<String> },
|
||||
|
||||
#[structopt(about = "Prints shell configuration")]
|
||||
Init {
|
||||
#[structopt(possible_values = &Shell::variants(), case_insensitive = true)]
|
||||
shell: Shell,
|
||||
#[structopt(long, help = "Prevents zoxide from defining any aliases other than 'z'")]
|
||||
no_define_aliases: bool,
|
||||
},
|
||||
|
||||
#[structopt(about = "Search for a directory")]
|
||||
Query {
|
||||
keywords: Vec<String>,
|
||||
#[structopt(short, long, help = "Opens an interactive selection menu using fzf")]
|
||||
interactive: bool,
|
||||
},
|
||||
|
||||
#[structopt(about = "Remove a directory")]
|
||||
Remove { path: String },
|
||||
}
|
||||
|
||||
fn zoxide_query(db: &mut DB, mut keywords: Vec<String>, now: Timestamp) -> Option<String> {
|
||||
if let [path] = keywords.as_slice() {
|
||||
@ -36,105 +69,182 @@ fn zoxide_query(db: &mut DB, mut keywords: Vec<String>, now: Timestamp) -> Optio
|
||||
|
||||
fn zoxide_query_interactive(
|
||||
db: &mut DB,
|
||||
mut keywords: Vec<String>,
|
||||
keywords: Vec<String>,
|
||||
now: Timestamp,
|
||||
) -> Result<Option<String>, failure::Error> {
|
||||
db.remove_invalid();
|
||||
|
||||
for keyword in &mut keywords {
|
||||
keyword.make_ascii_lowercase();
|
||||
}
|
||||
|
||||
let dirs = db
|
||||
.dirs
|
||||
.iter()
|
||||
.filter(|dir| dir.is_match(&keywords))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
) -> Result<Option<String>> {
|
||||
let dirs = db.query_all(keywords);
|
||||
fzf_helper(now, dirs)
|
||||
}
|
||||
|
||||
fn zoxide_app() -> App<'static, 'static> {
|
||||
app_from_crate!()
|
||||
.subcommand(
|
||||
SubCommand::with_name("add")
|
||||
.about("Add a new directory or increment its rank")
|
||||
.author(crate_authors!())
|
||||
.version(crate_version!())
|
||||
.arg(Arg::with_name("PATH")),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("query")
|
||||
.about("Search for a directory")
|
||||
.author(crate_authors!())
|
||||
.version(crate_version!())
|
||||
.arg(
|
||||
Arg::with_name("interactive")
|
||||
.short("i")
|
||||
.long("interactive")
|
||||
.takes_value(false)
|
||||
.help("Opens an interactive selection menu using fzf"),
|
||||
)
|
||||
.arg(Arg::with_name("KEYWORD").min_values(0)),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("remove")
|
||||
.about("Remove a directory")
|
||||
.author(crate_authors!())
|
||||
.version(crate_version!())
|
||||
.arg(Arg::with_name("PATH").required(true)),
|
||||
)
|
||||
}
|
||||
pub fn main() -> Result<()> {
|
||||
let opt = Zoxide::from_args();
|
||||
match opt {
|
||||
Zoxide::Add { path: path_opt } => {
|
||||
let mut db = get_db()?;
|
||||
let now = get_current_time()?;
|
||||
|
||||
fn zoxide() -> Result<(), failure::Error> {
|
||||
let matches = zoxide_app().get_matches();
|
||||
match path_opt {
|
||||
Some(path) => db.add(path, now),
|
||||
None => {
|
||||
let current_dir = env::current_dir()
|
||||
.with_context(|| anyhow!("unable to fetch current directory"))?;
|
||||
db.add(current_dir, now)
|
||||
}
|
||||
}?;
|
||||
|
||||
let db_path = get_zo_data()?;
|
||||
let mut db = DB::open(&db_path)?;
|
||||
|
||||
if let Some(matches) = matches.subcommand_matches("query") {
|
||||
let now = get_current_time()?;
|
||||
|
||||
let keywords = matches
|
||||
.values_of_os("KEYWORD")
|
||||
.unwrap_or_default()
|
||||
.map(|keyword| match keyword.to_str() {
|
||||
Some(keyword) => Ok(keyword.to_owned()),
|
||||
None => Err(AppError::UnicodeError),
|
||||
})
|
||||
.collect::<Result<Vec<String>, _>>()?;
|
||||
|
||||
let path_opt = if matches.is_present("interactive") {
|
||||
zoxide_query_interactive(&mut db, keywords, now)
|
||||
} else {
|
||||
Ok(zoxide_query(&mut db, keywords, now))
|
||||
}?;
|
||||
|
||||
if let Some(path) = path_opt {
|
||||
println!("query: {}", path.trim());
|
||||
db.save()?;
|
||||
}
|
||||
} else if let Some(matches) = matches.subcommand_matches("add") {
|
||||
let now = get_current_time()?;
|
||||
match matches.value_of_os("PATH") {
|
||||
Some(path) => db.add(path, now)?,
|
||||
None => {
|
||||
let path = env::current_dir().with_context(|_| AppError::GetCurrentDirError)?;
|
||||
db.add(path, now)?;
|
||||
Zoxide::Init {
|
||||
shell,
|
||||
no_define_aliases,
|
||||
} => {
|
||||
match shell {
|
||||
Shell::bash => {
|
||||
println!("{}", INIT_BASH);
|
||||
if !no_define_aliases {
|
||||
println!("{}", INIT_BASH_ALIAS);
|
||||
}
|
||||
}
|
||||
Shell::fish => {
|
||||
println!("{}", INIT_FISH);
|
||||
if !no_define_aliases {
|
||||
println!("{}", INIT_FISH_ALIAS);
|
||||
}
|
||||
}
|
||||
Shell::zsh => {
|
||||
println!("{}", INIT_ZSH);
|
||||
if !no_define_aliases {
|
||||
println!("{}", INIT_ZSH_ALIAS);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Zoxide::Query {
|
||||
keywords,
|
||||
interactive,
|
||||
} => {
|
||||
let mut db = get_db()?;
|
||||
let now = get_current_time()?;
|
||||
|
||||
let path_opt = if interactive {
|
||||
zoxide_query_interactive(&mut db, keywords, now)?
|
||||
} else {
|
||||
zoxide_query(&mut db, keywords, now)
|
||||
};
|
||||
|
||||
if let Some(path) = path_opt {
|
||||
println!("query: {}", path.trim());
|
||||
}
|
||||
};
|
||||
} else if let Some(matches) = matches.subcommand_matches("remove") {
|
||||
// unwrap is safe here because PATH has been set as a required field
|
||||
let path = matches.value_of_os("PATH").unwrap();
|
||||
db.remove(path)?;
|
||||
}
|
||||
}
|
||||
Zoxide::Remove { path } => {
|
||||
let mut db = get_db()?;
|
||||
db.remove(path)?;
|
||||
db.save()?;
|
||||
}
|
||||
};
|
||||
|
||||
db.save(db_path)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(err) = zoxide() {
|
||||
eprintln!("zoxide: {}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
const INIT_BASH: &str = r#"
|
||||
_zoxide_precmd() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
case "$PROMPT_COMMAND" in
|
||||
*_zoxide_precmd*) ;;
|
||||
*) PROMPT_COMMAND="_zoxide_precmd${PROMPT_COMMAND:+;$PROMPT_COMMAND}" ;;
|
||||
esac
|
||||
|
||||
z() {
|
||||
if [ "$#" -eq 0 ]; then
|
||||
cd "$HOME"
|
||||
elif [ "$#" -eq 1 ] && [ "$1" = "-" ]; then
|
||||
cd "-"
|
||||
else
|
||||
_Z_RESULT=$(zoxide query "$@")
|
||||
case "$_Z_RESULT" in
|
||||
"query: "*)
|
||||
cd "${_Z_RESULT:7}"
|
||||
;;
|
||||
*)
|
||||
echo -n "$_Z_RESULT"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
"#;
|
||||
|
||||
const INIT_BASH_ALIAS: &str = r#"
|
||||
alias zi="z -i"
|
||||
|
||||
alias za="zoxide add"
|
||||
alias zq="zoxide query"
|
||||
alias zr="zoxide remove"
|
||||
"#;
|
||||
|
||||
const INIT_FISH: &str = r#"
|
||||
function _zoxide_precmd --on-event fish_prompt
|
||||
zoxide add
|
||||
end
|
||||
|
||||
function z
|
||||
set -l argc (count $argv)
|
||||
if test $argc -eq 0
|
||||
cd "$HOME" && commandline -f repaint
|
||||
else if test $argc -eq 1 -a "$argv[1]" = "-"
|
||||
cd "-" && commandline -f repaint
|
||||
else
|
||||
set _Z_RESULT (zoxide query $argv)
|
||||
switch "$_Z_RESULT"
|
||||
case 'query: *'
|
||||
cd (string sub -s 8 -- "$_Z_RESULT") && commandline -f repaint
|
||||
case '*'
|
||||
echo -n "$_Z_RESULT"
|
||||
end
|
||||
end
|
||||
end
|
||||
"#;
|
||||
|
||||
const INIT_FISH_ALIAS: &str = r#"
|
||||
abbr -a zi "z -i"
|
||||
abbr -a za "zoxide add"
|
||||
abbr -a zq "zoxide query"
|
||||
abbr -a zr "zoxide remove"
|
||||
"#;
|
||||
|
||||
const INIT_ZSH: &str = r#"
|
||||
_zoxide_precmd() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
[[ -n "${precmd_functions[(r)_zoxide_precmd]}" ]] || {
|
||||
precmd_functions+=(_zoxide_precmd)
|
||||
}
|
||||
|
||||
z() {
|
||||
if [ "$#" -eq 0 ]; then
|
||||
cd "$HOME"
|
||||
elif [ "$#" -eq 1 ] && [ "$1" = "-" ]; then
|
||||
cd "-"
|
||||
else
|
||||
_Z_RESULT=$(zoxide query "$@")
|
||||
case "$_Z_RESULT" in
|
||||
"query: "*)
|
||||
cd "${_Z_RESULT:7}"
|
||||
;;
|
||||
*)
|
||||
echo -n "$_Z_RESULT"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
"#;
|
||||
|
||||
const INIT_ZSH_ALIAS: &str = r#"
|
||||
alias zi="z -i"
|
||||
|
||||
alias za="zoxide add"
|
||||
alias zq="zoxide query"
|
||||
alias zr="zoxide remove"
|
||||
"#;
|
||||
|
62
src/util.rs
62
src/util.rs
@ -1,29 +1,67 @@
|
||||
use crate::db::DB;
|
||||
use crate::dir::Dir;
|
||||
use crate::error::AppError;
|
||||
use crate::types::Timestamp;
|
||||
use failure::ResultExt;
|
||||
use crate::types::{Rank, Timestamp};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::env;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::time::SystemTime;
|
||||
|
||||
pub fn get_current_time() -> Result<Timestamp, failure::Error> {
|
||||
pub fn get_zo_data() -> Result<PathBuf> {
|
||||
const ZO_DATA: &str = "_ZO_DATA";
|
||||
|
||||
Ok(match env::var_os(ZO_DATA) {
|
||||
Some(path) => PathBuf::from(path),
|
||||
None => {
|
||||
let mut path =
|
||||
dirs::home_dir().ok_or_else(|| anyhow!("could not locate home directory"))?;
|
||||
path.push(".zo");
|
||||
path
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_zo_maxage() -> Result<Rank> {
|
||||
const ZO_MAXAGE: &str = "_ZO_MAXAGE";
|
||||
|
||||
let maxage = match env::var_os(ZO_MAXAGE) {
|
||||
Some(maxage_var) => maxage_var
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("invalid Unicode in ${}", ZO_MAXAGE))?
|
||||
.parse::<i64>()
|
||||
.with_context(|| anyhow!("could not parse ${} as integer", ZO_MAXAGE))?
|
||||
as Rank,
|
||||
None => 1000.0,
|
||||
};
|
||||
Ok(maxage)
|
||||
}
|
||||
|
||||
pub fn get_db() -> Result<DB> {
|
||||
let path = get_zo_data()?;
|
||||
DB::open(path)
|
||||
}
|
||||
|
||||
pub fn get_current_time() -> Result<Timestamp> {
|
||||
let current_time = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.with_context(|_| AppError::SystemTimeError)?
|
||||
.with_context(|| "system clock set to invalid time")?
|
||||
.as_secs();
|
||||
|
||||
Ok(current_time as Timestamp)
|
||||
}
|
||||
|
||||
pub fn fzf_helper(now: Timestamp, mut dirs: Vec<Dir>) -> Result<Option<String>, failure::Error> {
|
||||
pub fn fzf_helper(now: Timestamp, mut dirs: Vec<Dir>) -> Result<Option<String>> {
|
||||
let fzf = Command::new("fzf")
|
||||
.arg("-n2..")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.with_context(|_| AppError::FzfLaunchError)?;
|
||||
.with_context(|| anyhow!("could not launch fzf"))?;
|
||||
|
||||
let mut fzf_stdin = fzf.stdin.ok_or_else(|| AppError::FzfIoError)?;
|
||||
let mut fzf_stdin = fzf
|
||||
.stdin
|
||||
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
|
||||
|
||||
for dir in dirs.iter_mut() {
|
||||
dir.rank = dir.get_frecency(now);
|
||||
@ -42,15 +80,17 @@ pub fn fzf_helper(now: Timestamp, mut dirs: Vec<Dir>) -> Result<Option<String>,
|
||||
};
|
||||
|
||||
writeln!(fzf_stdin, "{:>4} {}", frecency, dir.path)
|
||||
.with_context(|_| AppError::FzfIoError)?;
|
||||
.with_context(|| anyhow!("could not write into fzf stdin"))?;
|
||||
}
|
||||
|
||||
let mut fzf_stdout = fzf.stdout.ok_or_else(|| AppError::FzfIoError)?;
|
||||
let mut fzf_stdout = fzf
|
||||
.stdout
|
||||
.ok_or_else(|| anyhow!("could not connect to fzf stdout"))?;
|
||||
|
||||
let mut output = String::new();
|
||||
fzf_stdout
|
||||
.read_to_string(&mut output)
|
||||
.with_context(|_| AppError::FzfIoError)?;
|
||||
.with_context(|| anyhow!("could not read from fzf stdout"))?;
|
||||
|
||||
Ok(output.get(12..).map(str::to_owned))
|
||||
}
|
||||
|
@ -1,29 +1 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
_zoxide_precmd() {
|
||||
zoxide add
|
||||
}
|
||||
|
||||
[[ -n "${precmd_functions[(r)_zoxide_precmd]}" ]] || {
|
||||
precmd_functions+=(_zoxide_precmd)
|
||||
}
|
||||
|
||||
z() {
|
||||
if [ $# -ne 0 ]; then
|
||||
_Z_RESULT=$(zoxide query "$@")
|
||||
case $_Z_RESULT in
|
||||
"query: "*)
|
||||
cd "${_Z_RESULT:7}"
|
||||
;;
|
||||
*)
|
||||
echo "${_Z_RESULT}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
alias zi="z -i"
|
||||
|
||||
alias za="zoxide add"
|
||||
alias zq="zoxide query"
|
||||
alias zr="zoxide remove"
|
||||
eval "$(zoxide init zsh)"
|
||||
|
Loading…
Reference in New Issue
Block a user