From a79219d39e93e6267d3d1e1aae132703e5c37a3c Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Thu, 12 Mar 2026 14:57:48 +0100 Subject: [PATCH] add just static binaries --- just | 1 + just-bin/Cargo.lock | 1430 ++++++++ just-bin/Cargo.toml | 108 + just-bin/GRAMMAR.md | 152 + just-bin/LICENSE | 121 + just-bin/README.md | 4882 ++++++++++++++++++++++++++ just-bin/completions/just.bash | 189 + just-bin/completions/just.elvish | 94 + just-bin/completions/just.fish | 87 + just-bin/completions/just.nu | 8 + just-bin/completions/just.powershell | 120 + just-bin/completions/just.zsh | 181 + just-bin/just | 3 + just-bin/just.1 | 294 ++ 14 files changed, 7670 insertions(+) create mode 120000 just create mode 100644 just-bin/Cargo.lock create mode 100644 just-bin/Cargo.toml create mode 100644 just-bin/GRAMMAR.md create mode 100644 just-bin/LICENSE create mode 100644 just-bin/README.md create mode 100644 just-bin/completions/just.bash create mode 100644 just-bin/completions/just.elvish create mode 100644 just-bin/completions/just.fish create mode 100644 just-bin/completions/just.nu create mode 100644 just-bin/completions/just.powershell create mode 100644 just-bin/completions/just.zsh create mode 100755 just-bin/just create mode 100644 just-bin/just.1 diff --git a/just b/just new file mode 120000 index 0000000..97d9fc8 --- /dev/null +++ b/just @@ -0,0 +1 @@ +./just-bin/just \ No newline at end of file diff --git a/just-bin/Cargo.lock b/just-bin/Cargo.lock new file mode 100644 index 0000000..b6ac271 --- /dev/null +++ b/just-bin/Cargo.lock @@ -0,0 +1,1430 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "memmap2", + "rayon-core", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" + +[[package]] +name = "cc" +version = "1.2.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "clap" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8c97f3a6f02b9e24cadc12aaba75201d18754b53ea0a9d99642f806ccdb4c9" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "clap_mangen" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ea63a92086df93893164221ad4f24142086d535b3a0957b9b9bea2dc86301" +dependencies = [ + "clap", + "roff", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctrlc" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +dependencies = [ + "dispatch2", + "nix", + "windows-sys 0.61.2", +] + +[[package]] +name = "derive-where" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "edit-distance" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324d428080b707bac399325341bd61af5ded1b30f33b7c949792ca464733c2d5" + +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "executable-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ebc5a6d89e3c90b84e8f33c8737933dda8f1c106b5415900b38b9d433841478" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" + +[[package]] +name = "generate-book" +version = "0.0.0" +dependencies = [ + "pulldown-cmark", + "pulldown-cmark-to-cmark", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "is_executable" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baabb8b4867b26294d818bf3f651a454b6901431711abb96e296245888d6e8c4" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "just" +version = "1.46.0" +dependencies = [ + "ansi_term", + "blake3", + "camino", + "chrono", + "clap", + "clap_complete", + "clap_mangen", + "ctrlc", + "derive-where", + "dirs", + "dotenvy", + "edit-distance", + "executable-path", + "heck", + "is_executable", + "lexiclean", + "libc", + "nix", + "num_cpus", + "percent-encoding", + "pretty_assertions", + "rand", + "regex", + "rustversion", + "semver", + "serde", + "serde_json", + "sha2", + "shellexpand", + "similar", + "snafu", + "strum", + "target", + "tempfile", + "temptree", + "typed-arena", + "unicode-width", + "uuid", + "which", +] + +[[package]] +name = "lexiclean" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "441225017b106b9f902e97947a6d31e44ebcf274b91bdbfb51e5c477fcd468e5" + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +dependencies = [ + "libc", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags", + "getopts", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "10.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0194e6e1966c23cc5fd988714f85b18d548d773e81965413555d96569931833d" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "roff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shellexpand" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" +dependencies = [ + "dirs", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +dependencies = [ + "bstr", + "unicode-segmentation", +] + +[[package]] +name = "snafu" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" +dependencies = [ + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8f05f774b2db35bdad5a8237a90be1102669f8ea013fea9777b366d34ab145" + +[[package]] +name = "tempfile" +version = "3.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "temptree" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fda94d8251b40088cb769576f436da19ac1d1ae792c97d0afe1cadc890c8630" +dependencies = [ + "tempfile", +] + +[[package]] +name = "terminal_size" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +dependencies = [ + "rustix", + "windows-sys 0.60.2", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "update-contributors" +version = "0.0.0" +dependencies = [ + "regex", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "which" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" +dependencies = [ + "env_home", + "rustix", + "winsafe", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de9211a9f64b825911bdf0240f58b7a8dac217fe260fc61f080a07f61372fbd5" diff --git a/just-bin/Cargo.toml b/just-bin/Cargo.toml new file mode 100644 index 0000000..be46ff4 --- /dev/null +++ b/just-bin/Cargo.toml @@ -0,0 +1,108 @@ +[package] +name = "just" +version = "1.46.0" +authors = ["Casey Rodarmor "] +autotests = false +categories = ["command-line-utilities", "development-tools"] +description = "🤖 Just a command runner" +edition = "2021" +exclude = ["/book", "/icon.png", "/screenshot.png", "/www"] +homepage = "https://github.com/casey/just" +keywords = ["command-line", "task", "runner", "development", "utility"] +license = "CC0-1.0" +readme = "crates-io-readme.md" +repository = "https://github.com/casey/just" +rust-version = "1.82.0" + +[workspace] +members = [".", "crates/*"] + +[dependencies] +ansi_term = "0.12.0" +blake3 = { version = "1.5.0", features = ["rayon", "mmap"] } +camino = "1.0.4" +chrono = "0.4.38" +clap = { version = "4.0.0", features = ["derive", "env", "wrap_help"] } +clap_mangen = "0.2.20" +derive-where = "1.2.7" +dirs = "6.0.0" +dotenvy = "0.15" +edit-distance = "2.0.0" +heck = "0.5.0" +is_executable = "1.0.4" +lexiclean = "0.0.1" +libc = "0.2.0" +num_cpus = "1.15.0" +percent-encoding = "2.3.1" +rand = "0.9.0" +regex = "1.10.4" +rustversion = "1.0.18" +semver = "1.0.20" +serde = { version = "1.0.130", features = ["derive", "rc"] } +serde_json = "1.0.68" +sha2 = "0.10" +shellexpand = "3.1.0" +similar = { version = "2.1.0", features = ["unicode"] } +snafu = "0.8.0" +strum = { version = "0.27.1", features = ["derive"] } +target = "2.0.0" +tempfile = "3.0.0" +typed-arena = "2.0.1" +unicode-width = "0.2.0" +uuid = { version = "1.0.0", features = ["v4"] } + +[target.'cfg(unix)'.dependencies] +nix = { version = "0.30.1", features = ["signal", "user", "fs"] } + +[target.'cfg(windows)'.dependencies] +ctrlc = { version = "3.1.1", features = ["termination"] } + +[dev-dependencies] +clap_complete = "=4.5.48" +executable-path = "1.0.0" +pretty_assertions = "1.0.0" +temptree = "0.2.0" +which = "8.0.0" + +[lints.rust] +mismatched_lifetime_syntaxes = "allow" +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } + +[lints.clippy] +all = { level = "deny", priority = -1 } +arbitrary-source-item-ordering = "deny" +enum_glob_use = "allow" +ignore_without_reason = "allow" +needless_pass_by_value = "allow" +pedantic = { level = "deny", priority = -1 } +similar_names = "allow" +struct_excessive_bools = "allow" +struct_field_names = "allow" +too_many_arguments = "allow" +too_many_lines = "allow" +type_complexity = "allow" +undocumented_unsafe_blocks = "deny" +unnecessary_wraps = "allow" +wildcard_imports = "allow" + +[lib] +doctest = false + +[[bin]] +path = "src/main.rs" +name = "just" +test = false + +# The public documentation is minimal and doesn't change between +# platforms, so we only build them for linux on docs.rs to save +# their build machines some cycles. +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[profile.release] +lto = true +codegen-units = 1 + +[[test]] +name = "integration" +path = "tests/lib.rs" diff --git a/just-bin/GRAMMAR.md b/just-bin/GRAMMAR.md new file mode 100644 index 0000000..e29e999 --- /dev/null +++ b/just-bin/GRAMMAR.md @@ -0,0 +1,152 @@ +justfile grammar +================ + +Justfiles are processed by a mildly context-sensitive tokenizer +and a recursive descent parser. The grammar is LL(k), for an +unknown but hopefully reasonable value of k. + +tokens +------ + +``` +BACKTICK = `[^`]*` +INDENTED_BACKTICK = ```[^(```)]*``` +COMMENT = #([^!].*)?$ +DEDENT = emitted when indentation decreases +EOF = emitted at the end of the file +INDENT = emitted when indentation increases +LINE = emitted before a recipe line +NAME = [a-zA-Z_][a-zA-Z0-9_-]* +NEWLINE = \n|\r\n +RAW_STRING = '[^']*' +INDENTED_RAW_STRING = '''[^(''')]*''' +STRING = "[^"]*" # also processes \n \r \t \" \\ escapes +INDENTED_STRING = """[^(""")]*""" # also processes \n \r \t \" \\ escapes +LINE_PREFIX = @-|-@|@|- +TEXT = recipe text, only matches in a recipe body +``` + +grammar syntax +-------------- + +``` +| alternation +() grouping +_? option (0 or 1 times) +_* repetition (0 or more times) +_+ repetition (1 or more times) +``` + +grammar +------- + +``` +justfile : item* EOF + +item : alias + | assignment + | eol + | export + | import + | module + | recipe + | set + +eol : NEWLINE + | COMMENT NEWLINE + +alias : 'alias' NAME ':=' target eol + +target : NAME ('::' NAME)* + +assignment : NAME ':=' expression eol + +export : 'export' assignment + +set : 'set' setting eol + +setting : 'allow-duplicate-recipes' boolean? + | 'allow-duplicate-variables' boolean? + | 'dotenv-filename' ':=' string + | 'dotenv-load' boolean? + | 'dotenv-path' ':=' string + | 'dotenv-required' boolean? + | 'export' boolean? + | 'fallback' boolean? + | 'ignore-comments' boolean? + | 'positional-arguments' boolean? + | 'script-interpreter' ':=' string_list + | 'quiet' boolean? + | 'shell' ':=' string_list + | 'tempdir' ':=' string + | 'unstable' boolean? + | 'windows-powershell' boolean? + | 'windows-shell' ':=' string_list + | 'working-directory' ':=' string + +boolean : ':=' ('true' | 'false') + +string_list : '[' string (',' string)* ','? ']' + +import : 'import' '?'? string? eol + +module : 'mod' '?'? NAME string? eol + +expression : disjunct || expression + | disjunct + +disjunct : conjunct && disjunct + | conjunct + +conjunct : 'if' condition '{' expression '}' 'else' '{' expression '}' + | 'assert' '(' condition ',' expression ')' + | '/' expression + | value '/' expression + | value '+' expression + | value + +condition : expression '==' expression + | expression '!=' expression + | expression '=~' expression + +value : NAME '(' sequence? ')' + | BACKTICK + | INDENTED_BACKTICK + | NAME + | string + | '(' expression ')' + +string : 'x'? STRING + | 'x'? INDENTED_STRING + | 'x'? RAW_STRING + | 'x'? INDENTED_RAW_STRING + +sequence : expression ',' sequence + | expression ','? + +recipe : attributes* '@'? NAME parameter* variadic? ':' dependencies eol body? + +attributes : '[' attribute (',' attribute)* ']' eol + +attribute : NAME + | NAME ':' string + | NAME '(' string (',' string)* ')' + +parameter : '$'? NAME + | '$'? NAME '=' value + +variadic : '*' parameter + | '+' parameter + +dependencies : dependency* ('&&' dependency+)? + +dependency : target + | '(' target expression* ')' + +body : INDENT line+ DEDENT + +line : LINE LINE_PREFIX? (TEXT | interpolation)+ NEWLINE + | NEWLINE + +interpolation : '{{' expression '}}' +``` diff --git a/just-bin/LICENSE b/just-bin/LICENSE new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/just-bin/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/just-bin/README.md b/just-bin/README.md new file mode 100644 index 0000000..31deca9 --- /dev/null +++ b/just-bin/README.md @@ -0,0 +1,4882 @@ +
Table of Contents↗️
+ +

just

+ +
+ + crates.io version + + + build status + + + downloads + + + chat on discord + + + say thanks + +
+
+ +`just` is a handy way to save and run project-specific commands. + +This readme is also available as a [book](https://just.systems/man/en/). The +book reflects the latest release, whereas the +[readme on GitHub](https://github.com/casey/just/blob/master/README.md) +reflects latest master. + +(中文文档在 [这里](https://github.com/casey/just/blob/master/README.中文.md), +快看过来!) + +Commands, called recipes, are stored in a file called `justfile` with syntax +inspired by `make`: + +![screenshot](https://raw.githubusercontent.com/casey/just/master/screenshot.png) + +You can then run them with `just RECIPE`: + +```console +$ just test-all +cc *.c -o main +./test --all +Yay, all your tests passed! +``` + +`just` has a ton of useful features, and many improvements over `make`: + +- `just` is a command runner, not a build system, so it avoids much of + [`make`'s complexity and idiosyncrasies](#what-are-the-idiosyncrasies-of-make-that-just-avoids). + No need for `.PHONY` recipes! + +- Linux, MacOS, Windows, and other reasonable unices are supported with no + additional dependencies. (Although if your system doesn't have an `sh`, + you'll need to [choose a different shell](#shell).) + +- Errors are specific and informative, and syntax errors are reported along + with their source context. + +- Recipes can accept [command line arguments](#recipe-parameters). + +- Wherever possible, errors are resolved statically. Unknown recipes and + circular dependencies are reported before anything runs. + +- `just` [loads `.env` files](#dotenv-settings), making it easy to populate + environment variables. + +- Recipes can be [listed from the command line](#listing-available-recipes). + +- Command line completion scripts are + [available for most popular shells](#shell-completion-scripts). + +- Recipes can be written in + [arbitrary languages](#shebang-recipes), like Python or NodeJS. + +- `just` can be invoked from any subdirectory, not just the directory that + contains the `justfile`. + +- And [much more](https://just.systems/man/en/)! + +If you need help with `just` please feel free to open an issue or ping me on +[Discord](https://discord.gg/ezYScXR). Feature requests and bug reports are +always welcome! + +Installation +------------ + +### Prerequisites + +`just` should run on any system with a reasonable `sh`, including Linux, MacOS, +and the BSDs. + +#### Windows + +On Windows, `just` works with the `sh` provided by +[Git for Windows](https://git-scm.com), +[GitHub Desktop](https://desktop.github.com), or +[Cygwin](http://www.cygwin.com). After installation, `sh` must be +available in the `PATH` of the shell you want to to invoke `just` from. + +If you'd rather not install `sh`, you can use the `shell` setting to use the +shell of your choice. + +Like PowerShell: + +```just +# use PowerShell instead of sh: +set shell := ["powershell.exe", "-c"] + +hello: + Write-Host "Hello, world!" +``` + +…or `cmd.exe`: + +```just +# use cmd.exe instead of sh: +set shell := ["cmd.exe", "/c"] + +list: + dir +``` + +You can also set the shell using command-line arguments. For example, to use +PowerShell, launch `just` with `--shell powershell.exe --shell-arg -c`. + +(PowerShell is installed by default on Windows 7 SP1 and Windows Server 2008 R2 +S1 and later, and `cmd.exe` is quite fiddly, so PowerShell is recommended for +most Windows users.) + +### Packages + +#### Cross-platform + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Package ManagerPackageCommand
arkadejustarkade get just
asdfjust + asdf plugin add just
+ asdf install just <version> +
Cargojustcargo install just
Condajustconda install -c conda-forge just
Homebrewjustbrew install just
Nixjustnix-env -iA nixpkgs.just
npmrust-justnpm install -g rust-just
pipxrust-justpipx install rust-just
Snapjustsnap install --edge --classic just
+ +#### BSD + + + + + + + + + + + + + + + + + + + + + + + + +
Operating SystemPackage ManagerPackageCommand
FreeBSDpkgjustpkg install just
OpenBSDpkg_*justpkg_add just
+ +#### Linux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Operating SystemPackage ManagerPackageCommand
Alpineapk-toolsjustapk add just
Archpacmanjustpacman -S just
+ Debian 13 and + Ubuntu 24.04 derivativesaptjustapt install just
Debian and Ubuntu derivativesMPRjust + git clone https://mpr.makedeb.org/just
+ cd just
+ makedeb -si +
Debian and Ubuntu derivativesPrebuilt-MPRjust + You must have the Prebuilt-MPR set up on your system in order to run this command.
+ apt install just +
FedoraDNFjustdnf install just
GentooPortageguru/dev-build/just + eselect repository enable guru
+ emerge --sync guru
+ emerge dev-build/just +
NixOSNixjustnix-env -iA nixos.just
openSUSEZypperjustzypper in just
Soluseopkgjusteopkg install just
VoidXBPSjustxbps-install -S just
+ +#### Windows + + + + + + + + + + + + + + + + + + + + + + + + + + +
Package ManagerPackageCommand
Chocolateyjustchoco install just
Scoopjustscoop install just
Windows Package ManagerCasey/Justwinget install --id Casey.Just --exact
+ +#### macOS + + + + + + + + + + + + + + + + +
Package ManagerPackageCommand
MacPortsjustport install just
+ +![just package version table](https://repology.org/badge/vertical-allrepos/just.svg) + +### Pre-Built Binaries + +Pre-built binaries for Linux, MacOS, and Windows can be found on +[the releases page](https://github.com/casey/just/releases). + +You can use the following command on Linux, MacOS, or Windows to download the +latest release, just replace `DEST` with the directory where you'd like to put +`just`: + +```console +curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to DEST +``` + +For example, to install `just` to `~/bin`: + +```console +# create ~/bin +mkdir -p ~/bin + +# download and extract just to ~/bin/just +curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin + +# add `~/bin` to the paths that your shell searches for executables +# this line should be added to your shells initialization file, +# e.g. `~/.bashrc` or `~/.zshrc` +export PATH="$PATH:$HOME/bin" + +# just should now be executable +just --help +``` + +Note that `install.sh` may fail on GitHub Actions, or in other environments +where many machines share IP addresses. `install.sh` calls GitHub APIs in order +to determine the latest version of `just` to install, and those API calls are +rate-limited on a per-IP basis. To make `install.sh` more reliable in such +circumstances, pass a specific tag to install with `--tag`. + +Another way to avoid rate-limiting is to pass a GitHub authentication token to +`install.sh` as an environment variable named `GITHUB_TOKEN`, allowing it to +authenticate its requests. + +[Releases](https://github.com/casey/just/releases) include a `SHA256SUM` file +which can be used to verify the integrity of pre-built binary archives. + +To verify a release, download the pre-built binary archive along with the +`SHA256SUM` file and run: + +```sh +shasum --algorithm 256 --ignore-missing --check SHA256SUMS +``` + +### GitHub Actions + +`just` can be installed on GitHub Actions in a few ways. + +Using package managers pre-installed on GitHub Actions runners on MacOS with +`brew install just`, and on Windows with `choco install just`. + +With [extractions/setup-just](https://github.com/extractions/setup-just): + +```yaml +- uses: extractions/setup-just@v3 + with: + just-version: 1.5.0 # optional semver specification, otherwise latest +``` + +Or with [taiki-e/install-action](https://github.com/taiki-e/install-action): + +```yaml +- uses: taiki-e/install-action@just +``` + +### Release RSS Feed + +An [RSS feed](https://en.wikipedia.org/wiki/RSS) of `just` releases is available [here](https://github.com/casey/just/releases.atom). + +### Node.js Installation + +[just-install](https://npmjs.com/package/just-install) can be used to automate +installation of `just` in Node.js applications. + +`just` is a great, more robust alternative to npm scripts. If you want to +include `just` in the dependencies of a Node.js application, `just-install` +will install a local, platform-specific binary as part of the `npm install` +command. This removes the need for every developer to install `just` +independently using one of the processes mentioned above. After installation, +the `just` command will work in npm scripts or with npx. It's great for teams +who want to make the set up process for their project as easy as possible. + +For more information, see the +[just-install README file](https://github.com/brombal/just-install#readme). + +Backwards Compatibility +----------------------- + +With the release of version 1.0, `just` features a strong commitment to +backwards compatibility and stability. + +Future releases will not introduce backwards incompatible changes that make +existing `justfile`s stop working, or break working invocations of the +command-line interface. + +This does not, however, preclude fixing outright bugs, even if doing so might +break `justfiles` that rely on their behavior. + +There will never be a `just` 2.0. Any desirable backwards-incompatible changes +will be opt-in on a per-`justfile` basis, so users may migrate at their +leisure. + +Features that aren't yet ready for stabilization are marked as unstable and may +be changed or removed at any time. Using unstable features produces an error by +default, which can be suppressed with by passing the `--unstable` flag, +`set unstable`, or setting the environment variable `JUST_UNSTABLE`, to any +value other than `false`, `0`, or the empty string. + +Editor Support +-------------- + +`justfile` syntax is close enough to `make` that you may want to tell your +editor to use `make` syntax highlighting for `just`. + +### Vim and Neovim + +Vim version 9.1.1042 or better and Neovim version 0.11 or better support +Justfile syntax highlighting out of the box, thanks to +[pbnj](https://github.com/pbnj). + +#### `vim-just` + +The [vim-just](https://github.com/NoahTheDuke/vim-just) plugin provides syntax +highlighting for `justfile`s. + +Install it with your favorite package manager, like +[Plug](https://github.com/junegunn/vim-plug): + +```vim +call plug#begin() + +Plug 'NoahTheDuke/vim-just' + +call plug#end() +``` + +Or with Vim's built-in package support: + +```console +mkdir -p ~/.vim/pack/vendor/start +cd ~/.vim/pack/vendor/start +git clone https://github.com/NoahTheDuke/vim-just.git +``` + +#### `tree-sitter-just` + +[tree-sitter-just](https://github.com/IndianBoy42/tree-sitter-just) is an +[Nvim Treesitter](https://github.com/nvim-treesitter/nvim-treesitter) plugin +for Neovim. + +#### Makefile Syntax Highlighting + +Vim's built-in makefile syntax highlighting isn't perfect for `justfile`s, but +it's better than nothing. You can put the following in `~/.vim/filetype.vim`: + +```vimscript +if exists("did_load_filetypes") + finish +endif + +augroup filetypedetect + au BufNewFile,BufRead justfile setf make +augroup END +``` + +Or add the following to an individual `justfile` to enable `make` mode on a +per-file basis: + +```text +# vim: set ft=make : +``` + +### Emacs + +[just-mode](https://github.com/leon-barrett/just-mode.el) provides syntax +highlighting and automatic indentation of `justfile`s. It is available on +[MELPA](https://melpa.org/) as [just-mode](https://melpa.org/#/just-mode). + +[justl](https://github.com/psibi/justl.el) provides commands for executing and +listing recipes. + +You can add the following to an individual `justfile` to enable `make` mode on +a per-file basis: + +```text +# Local Variables: +# mode: makefile +# End: +``` + +### Visual Studio Code + +An extension for VS Code is [available here](https://github.com/nefrob/vscode-just). + +Unmaintained VS Code extensions include +[skellock/vscode-just](https://github.com/skellock/vscode-just) and +[sclu1034/vscode-just](https://github.com/sclu1034/vscode-just). + +### JetBrains IDEs + +A plugin for JetBrains IDEs by [linux_china](https://github.com/linux-china) is +[available here](https://plugins.jetbrains.com/plugin/18658-just). + +### Kakoune + +Kakoune supports `justfile` syntax highlighting out of the box, thanks to +TeddyDD. + +### Helix + +[Helix](https://helix-editor.com/) supports `justfile` syntax highlighting +out-of-the-box since version 23.05. + +### Sublime Text + +The [Just package](https://github.com/nk9/just_sublime) by +[nk9](https://github.com/nk9) with `just` syntax and some other tools is +available on [PackageControl](https://packagecontrol.io/packages/Just). + +### Micro + +[Micro](https://micro-editor.github.io/) supports Justfile syntax highlighting +out of the box, thanks to [tomodachi94](https://github.com/tomodachi94). + +### Zed + +The [zed-just](https://github.com/jackTabsCode/zed-just/) extension by +[jackTabsCode](https://github.com/jackTabsCode) is avilable on the +[Zed extensions page](https://zed.dev/extensions?query=just). + +### Other Editors + +Feel free to send me the commands necessary to get syntax highlighting working +in your editor of choice so that I may include them here. + +### Language Server Protocol + +[just-lsp](https://github.com/terror/just-lsp) provides a [language server +protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol) +implementation, enabling features such as go-to-definition, inline diagnostics, +and code completion. + +### Model Context Protocol + +[just-mcp](http://github.com/promptexecution/just-mcp) provides a +[model context protocol](https://en.wikipedia.org/wiki/Model_Context_Protocol) +adapter to allow LLMs to query the contents of `justfiles` and run recipes. + +Quick Start +----------- + +See the installation section for how to install `just` on your computer. Try +running `just --version` to make sure that it's installed correctly. + +For an overview of the syntax, check out +[this cheatsheet](https://cheatography.com/linux-china/cheat-sheets/justfile/). + +Once `just` is installed and working, create a file named `justfile` in the +root of your project with the following contents: + +```just +recipe-name: + echo 'This is a recipe!' + +# this is a comment +another-recipe: + @echo 'This is another recipe.' +``` + +When you invoke `just` it looks for file `justfile` in the current directory +and upwards, so you can invoke it from any subdirectory of your project. + +The search for a `justfile` is case insensitive, so any case, like `Justfile`, +`JUSTFILE`, or `JuStFiLe`, will work. `just` will also look for files with the +name `.justfile`, in case you'd like to hide a `justfile`. + +Running `just` with no arguments runs the first recipe in the `justfile`: + +```console +$ just +echo 'This is a recipe!' +This is a recipe! +``` + +One or more arguments specify the recipe(s) to run: + +```console +$ just another-recipe +This is another recipe. +``` + +`just` prints each command to standard error before running it, which is why +`echo 'This is a recipe!'` was printed. This is suppressed for lines starting +with `@`, which is why `echo 'This is another recipe.'` was not printed. + +Recipes stop running if a command fails. Here `cargo publish` will only run if +`cargo test` succeeds: + +```just +publish: + cargo test + # tests passed, time to publish! + cargo publish +``` + +Recipes can depend on other recipes. Here the `test` recipe depends on the +`build` recipe, so `build` will run before `test`: + +```just +build: + cc main.c foo.c bar.c -o main + +test: build + ./test + +sloc: + @echo "`wc -l *.c` lines of code" +``` + +```console +$ just test +cc main.c foo.c bar.c -o main +./test +testing… all tests passed! +``` + +Recipes without dependencies will run in the order they're given on the command +line: + +```console +$ just build sloc +cc main.c foo.c bar.c -o main +1337 lines of code +``` + +Dependencies will always run first, even if they are passed after a recipe that +depends on them: + +```console +$ just test build +cc main.c foo.c bar.c -o main +./test +testing… all tests passed! +``` + +Recipes may depend on recipes in submodules: + +```justfile +mod foo + +baz: foo::bar +``` + +Examples +-------- + +A variety of `justfile`s can be found in the +[examples directory](https://github.com/casey/just/tree/master/examples) and on +[GitHub](https://github.com/search?q=path%3A**%2Fjustfile&type=code). + +Features +-------- + +### The Default Recipe + +When `just` is invoked without a recipe, it runs the recipe with the +`[default]` attribute, or the first recipe in the `justfile` if no recipe has +the `[default]` attribute. + +This recipe might be the most frequently run command in the project, like +running the tests: + +```just +test: + cargo test +``` + +You can also use dependencies to run multiple recipes by default: + +```just +default: lint build test + +build: + echo Building… + +test: + echo Testing… + +lint: + echo Linting… +``` + +If no recipe makes sense as the default recipe, you can add a recipe to the +beginning of your `justfile` that lists the available recipes: + +```just +default: + just --list +``` + +### Listing Available Recipes + +Recipes can be listed in alphabetical order with `just --list`: + +```console +$ just --list +Available recipes: + build + test + deploy + lint +``` + +Recipes in [submodules](#modules1190) can be listed with `just --list PATH`, +where `PATH` is a space- or `::`-separated module path: + +``` +$ cat justfile +mod foo +$ cat foo.just +mod bar +$ cat bar.just +baz: +$ just --list foo bar +Available recipes: + baz +$ just --list foo::bar +Available recipes: + baz +``` + +`just --summary` is more concise: + +```console +$ just --summary +build test deploy lint +``` + +Pass `--unsorted` to print recipes in the order they appear in the `justfile`: + +```just +test: + echo 'Testing!' + +build: + echo 'Building!' +``` + +```console +$ just --list --unsorted +Available recipes: + test + build +``` + +```console +$ just --summary --unsorted +test build +``` + +If you'd like `just` to default to listing the recipes in the `justfile`, you +can use this as your default recipe: + +```just +default: + @just --list +``` + +Note that you may need to add `--justfile {{justfile()}}` to the line above. +Without it, if you executed `just -f /some/distant/justfile -d .` or +`just -f ./non-standard-justfile`, the plain `just --list` inside the recipe +would not necessarily use the file you provided. It would try to find a +justfile in your current path, maybe even resulting in a `No justfile found` +error. + +The heading text can be customized with `--list-heading`: + +```console +$ just --list --list-heading $'Cool stuff…\n' +Cool stuff… + test + build +``` + +And the indentation can be customized with `--list-prefix`: + +```console +$ just --list --list-prefix ···· +Available recipes: +····test +····build +``` + +The argument to `--list-heading` replaces both the heading and the newline +following it, so it should contain a newline if non-empty. It works this way so +you can suppress the heading line entirely by passing the empty string: + +```console +$ just --list --list-heading '' + test + build +``` + +### Invoking Multiple Recipes + +Multiple recipes may be invoked on the command line at once: + +```just +build: + make web + +serve: + python3 -m http.server -d out 8000 +``` + +```console +$ just build serve +make web +python3 -m http.server -d out 8000 +``` + +Keep in mind that recipes with parameters will swallow arguments, even if they +match the names of other recipes: + +```just +build project: + make {{project}} + +serve: + python3 -m http.server -d out 8000 +``` + +```console +$ just build serve +make: *** No rule to make target `serve'. Stop. +``` + +The `--one` flag can be used to restrict command-line invocations to a single +recipe: + +```console +$ just --one build serve +error: Expected 1 command-line recipe invocation but found 2. +``` + +### Working Directory + +By default, recipes run with the working directory set to the directory that +contains the `justfile`. + +The `[no-cd]` attribute can be used to make recipes run with the working +directory set to directory in which `just` was invoked. + +```just +@foo: + pwd + +[no-cd] +@bar: + pwd +``` + +```console +$ cd subdir +$ just foo +/ +$ just bar +/subdir +``` + +You can override the working directory for all recipes with +`set working-directory := '…'`: + +```just +set working-directory := 'bar' + +@foo: + pwd +``` + +```console +$ pwd +/home/bob +$ just foo +/home/bob/bar +``` + +You can override the working directory for a specific recipe with the +`working-directory` attribute1.38.0: + +```just +[working-directory: 'bar'] +@foo: + pwd +``` + +```console +$ pwd +/home/bob +$ just foo +/home/bob/bar +``` + +The argument to the `working-directory` setting or `working-directory` +attribute may be absolute or relative. If it is relative it is interpreted +relative to the default working directory. + +### Aliases + +Aliases allow recipes to be invoked on the command line with alternative names: + +```just +alias b := build + +build: + echo 'Building!' +``` + +```console +$ just b +echo 'Building!' +Building! +``` + +The target of an alias may be a recipe in a submodule: + +```justfile +mod foo + +alias baz := foo::bar +``` + +### Settings + +Settings control interpretation and execution. Each setting may be specified at +most once, anywhere in the `justfile`. + +For example: + +```just +set shell := ["zsh", "-cu"] + +foo: + # this line will be run as `zsh -cu 'ls **/*.txt'` + ls **/*.txt +``` + +#### Table of Settings + +| Name | Value | Default | Description | +|------|-------|---------|-------------| +| `allow-duplicate-recipes` | boolean | `false` | Allow recipes appearing later in a `justfile` to override earlier recipes with the same name. | +| `allow-duplicate-variables` | boolean | `false` | Allow variables appearing later in a `justfile` to override earlier variables with the same name. | +| `dotenv-filename` | string | - | Load a `.env` file with a custom name, if present. | +| `dotenv-load` | boolean | `false` | Load a `.env` file, if present. | +| `dotenv-override` | boolean | `false` | Override existing environment variables with values from the `.env` file. | +| `dotenv-path` | string | - | Load a `.env` file from a custom path and error if not present. Overrides `dotenv-filename`. | +| `dotenv-required` | boolean | `false` | Error if a `.env` file isn't found. | +| `export` | boolean | `false` | Export all variables as environment variables. | +| `fallback` | boolean | `false` | Search `justfile` in parent directory if the first recipe on the command line is not found. | +| `ignore-comments` | boolean | `false` | Ignore recipe lines beginning with `#`. | +| `positional-arguments` | boolean | `false` | Pass positional arguments. | +| `quiet` | boolean | `false` | Disable echoing recipe lines before executing. | +| `script-interpreter`1.33.0 | `[COMMAND, ARGS…]` | `['sh', '-eu']` | Set command used to invoke recipes with empty `[script]` attribute. | +| `shell` | `[COMMAND, ARGS…]` | - | Set command used to invoke recipes and evaluate backticks. | +| `tempdir` | string | - | Create temporary directories in `tempdir` instead of the system default temporary directory. | +| `unstable`1.31.0 | boolean | `false` | Enable unstable features. | +| `windows-powershell` | boolean | `false` | Use PowerShell on Windows as default shell. (Deprecated. Use `windows-shell` instead. | +| `windows-shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. | +| `working-directory`1.33.0 | string | - | Set the working directory for recipes and backticks, relative to the default working directory. | + +Boolean settings can be written as: + +```justfile +set NAME +``` + +Which is equivalent to: + +```justfile +set NAME := true +``` + +Non-boolean settings can be set to both strings and +expressions.1.46.0 + +However, because settings affect the behavior of backticks and many functions, +those expressions may not contain backticks or function calls, directly or +transitively via reference. + +#### Allow Duplicate Recipes + +If `allow-duplicate-recipes` is set to `true`, defining multiple recipes with +the same name is not an error and the last definition is used. Defaults to +`false`. + +```just +set allow-duplicate-recipes + +@foo: + echo foo + +@foo: + echo bar +``` + +```console +$ just foo +bar +``` + +#### Allow Duplicate Variables + +If `allow-duplicate-variables` is set to `true`, defining multiple variables +with the same name is not an error and the last definition is used. Defaults to +`false`. + +```just +set allow-duplicate-variables + +a := "foo" +a := "bar" + +@foo: + echo {{a}} +``` + +```console +$ just foo +bar +``` + +#### Dotenv Settings + +If any of `dotenv-load`, `dotenv-filename`, `dotenv-override`, `dotenv-path`, +or `dotenv-required` are set, `just` will try to load environment variables +from a file. + +If `dotenv-path` is set, `just` will look for a file at the given path, which +may be absolute, or relative to the working directory. + +The command-line option `--dotenv-path`, short form `-E`, can be used to set or +override `dotenv-path` at runtime. + +If `dotenv-filename` is set `just` will look for a file at the given path, +relative to the working directory and each of its ancestors. + +If `dotenv-filename` is not set, but `dotenv-load` or `dotenv-required` are +set, just will look for a file named `.env`, relative to the working directory +and each of its ancestors. + +`dotenv-filename` and `dotenv-path` are similar, but `dotenv-path` is only +checked relative to the working directory, whereas `dotenv-filename` is checked +relative to the working directory and each of its ancestors. + +It is not an error if an environment file is not found, unless +`dotenv-required` is set. + +The loaded variables are environment variables, not `just` variables, and so +must be accessed using `$VARIABLE_NAME` in recipes and backticks. + +If `dotenv-override` is set, variables from the environment file will override +existing environment variables. + +For example, if your `.env` file contains: + +```console +# a comment, will be ignored +DATABASE_ADDRESS=localhost:6379 +SERVER_PORT=1337 +``` + +And your `justfile` contains: + +```just +set dotenv-load + +serve: + @echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT…" + ./server --database $DATABASE_ADDRESS --port $SERVER_PORT +``` + +`just serve` will output: + +```console +$ just serve +Starting server with database localhost:6379 on port 1337… +./server --database $DATABASE_ADDRESS --port $SERVER_PORT +``` + +#### Export + +The `export` setting causes all `just` variables to be exported as environment +variables. Defaults to `false`. + +```just +set export + +a := "hello" + +@foo b: + echo $a + echo $b +``` + +```console +$ just foo goodbye +hello +goodbye +``` + +#### Positional Arguments + +If `positional-arguments` is `true`, recipe arguments will be passed as +positional arguments to commands. For linewise recipes, argument `$0` will be +the name of the recipe. + +For example, running this recipe: + +```just +set positional-arguments + +@foo bar: + echo $0 + echo $1 +``` + +Will produce the following output: + +```console +$ just foo hello +foo +hello +``` + +When using an `sh`-compatible shell, such as `bash` or `zsh`, `$@` expands to +the positional arguments given to the recipe, starting from one. When used +within double quotes as `"$@"`, arguments including whitespace will be passed +on as if they were double-quoted. That is, `"$@"` is equivalent to `"$1" "$2"`… +When there are no positional parameters, `"$@"` and `$@` expand to nothing +(i.e., they are removed). + +This example recipe will print arguments one by one on separate lines: + +```just +set positional-arguments + +@test *args='': + bash -c 'while (( "$#" )); do echo - $1; shift; done' -- "$@" +``` + +Running it with _two_ arguments: + +```console +$ just test foo "bar baz" +- foo +- bar baz +``` + +Positional arguments may also be turned on on a per-recipe basis with the +`[positional-arguments]` attribute1.29.0: + +```just +[positional-arguments] +@foo bar: + echo $0 + echo $1 +``` + +Note that PowerShell does not handle positional arguments in the same way as +other shells, so turning on positional arguments will likely break recipes that +use PowerShell. + +If using PowerShell 7.4 or better, the `-CommandWithArgs` flag will make +positional arguments work as expected: + +```just +set shell := ['pwsh.exe', '-CommandWithArgs'] +set positional-arguments + +print-args a b c: + Write-Output @($args[1..($args.Count - 1)]) +``` + +#### Shell + +The `shell` setting controls the command used to invoke recipe lines and +backticks. Shebang recipes are unaffected. The default shell is `sh -cu`. + +```just +# use python3 to execute recipe lines and backticks +set shell := ["python3", "-c"] + +# use print to capture result of evaluation +foos := `print("foo" * 4)` + +foo: + print("Snake snake snake snake.") + print("{{foos}}") +``` + +`just` passes the command to be executed as an argument. Many shells will need +an additional flag, often `-c`, to make them evaluate the first argument. + +##### Windows Shell + +`just` uses `sh` on Windows by default. To use a different shell on Windows, +use `windows-shell`: + +```just +set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] + +hello: + Write-Host "Hello, world!" +``` + +See +[powershell.just](https://github.com/casey/just/blob/master/examples/powershell.just) +for a justfile that uses PowerShell on all platforms. + +##### Windows PowerShell + +*`set windows-powershell` uses the legacy `powershell.exe` binary, and is no +longer recommended. See the `windows-shell` setting above for a more flexible +way to control which shell is used on Windows.* + +`just` uses `sh` on Windows by default. To use `powershell.exe` instead, set +`windows-powershell` to true. + +```just +set windows-powershell := true + +hello: + Write-Host "Hello, world!" +``` + +##### Python 3 + +```just +set shell := ["python3", "-c"] +``` + +##### Bash + +```just +set shell := ["bash", "-uc"] +``` + +##### Z Shell + +```just +set shell := ["zsh", "-uc"] +``` + +##### Fish + +```just +set shell := ["fish", "-c"] +``` + +##### Nushell + +```just +set shell := ["nu", "-c"] +``` + +If you want to change the default table mode to `light`: + +```just +set shell := ['nu', '-m', 'light', '-c'] +``` + +*[Nushell](https://github.com/nushell/nushell) was written in Rust, and **has +cross-platform support for Windows / macOS and Linux**.* + +### Documentation Comments + +Comments immediately preceding a recipe will appear in `just --list`: + +```just +# build stuff +build: + ./bin/build + +# test stuff +test: + ./bin/test +``` + +```console +$ just --list +Available recipes: + build # build stuff + test # test stuff +``` + +The `[doc]` attribute can be used to set or suppress a recipe's doc comment: + +```just +# This comment won't appear +[doc('Build stuff')] +build: + ./bin/build + +# This one won't either +[doc] +test: + ./bin/test +``` + +```console +$ just --list +Available recipes: + build # Build stuff + test +``` + +### Expressions and Substitutions + +Various operators and function calls are supported in expressions, which may be +used in assignments, default recipe arguments, and inside recipe body `{{…}}` +substitutions. + +```just +tmpdir := `mktemp -d` +version := "0.2.7" +tardir := tmpdir / "awesomesauce-" + version +tarball := tardir + ".tar.gz" +config := quote(config_dir() / ".project-config") + +publish: + rm -f {{tarball}} + mkdir {{tardir}} + cp README.md *.c {{ config }} {{tardir}} + tar zcvf {{tarball}} {{tardir}} + scp {{tarball}} me@server.com:release/ + rm -rf {{tarball}} {{tardir}} +``` + +#### Concatenation + +The `+` operator returns the left-hand argument concatenated with the +right-hand argument: + +```just +foobar := 'foo' + 'bar' +``` + +#### Logical Operators + +The logical operators `&&` and `||` can be used to coalesce string +values1.37.0, similar to Python's `and` and `or`. These operators +consider the empty string `''` to be false, and all other strings to be true. + +These operators are currently unstable. + +The `&&` operator returns the empty string if the left-hand argument is the +empty string, otherwise it returns the right-hand argument: + +```justfile +foo := '' && 'goodbye' # '' +bar := 'hello' && 'goodbye' # 'goodbye' +``` + +The `||` operator returns the left-hand argument if it is non-empty, otherwise +it returns the right-hand argument: + +```justfile +foo := '' || 'goodbye' # 'goodbye' +bar := 'hello' || 'goodbye' # 'hello' +``` + +#### Joining Paths + +The `/` operator can be used to join two strings with a slash: + +```just +foo := "a" / "b" +``` + +``` +$ just --evaluate foo +a/b +``` + +Note that a `/` is added even if one is already present: + +```just +foo := "a/" +bar := foo / "b" +``` + +``` +$ just --evaluate bar +a//b +``` + +Absolute paths can also be constructed1.5.0: + +```just +foo := / "b" +``` + +``` +$ just --evaluate foo +/b +``` + +The `/` operator uses the `/` character, even on Windows. Thus, using the `/` +operator should be avoided with paths that use universal naming convention +(UNC), i.e., those that start with `\?`, since forward slashes are not +supported with UNC paths. + +#### Escaping `{{` + +To write a recipe containing `{{`, use `{{{{`: + +```just +braces: + echo 'I {{{{LOVE}} curly braces!' +``` + +(An unmatched `}}` is ignored, so it doesn't need to be escaped.) + +Another option is to put all the text you'd like to escape inside of an +interpolation: + +```just +braces: + echo '{{'I {{LOVE}} curly braces!'}}' +``` + +Yet another option is to use `{{ "{{" }}`: + +```just +braces: + echo 'I {{ "{{" }}LOVE}} curly braces!' +``` + +### Strings + +`'single'`, `"double"`, and `'''triple'''` quoted string literals are +supported. Unlike in recipe bodies, `{{…}}` interpolations are not supported +inside strings. + +Double-quoted strings support escape sequences: + +```just +carriage-return := "\r" +double-quote := "\"" +newline := "\n" +no-newline := "\ +" +slash := "\\" +tab := "\t" +unicode-codepoint := "\u{1F916}" +``` + +```console +$ just --evaluate +"arriage-return := " +double-quote := """ +newline := " +" +no-newline := "" +slash := "\" +tab := " " +unicode-codepoint := "🤖" +``` + +The unicode character escape sequence `\u{…}`1.36.0 accepts up to +six hex digits. + +Strings may contain line breaks: + +```just +single := ' +hello +' + +double := " +goodbye +" +``` + +Single-quoted strings do not recognize escape sequences: + +```just +escapes := '\t\n\r\"\\' +``` + +```console +$ just --evaluate +escapes := "\t\n\r\"\\" +``` + +Indented versions of both single- and double-quoted strings, delimited by +triple single- or double-quotes, are supported. Indented string lines are +stripped of a leading line break, and leading whitespace common to all +non-blank lines: + +```just +# this string will evaluate to `foo\nbar\n` +x := ''' + foo + bar +''' + +# this string will evaluate to `abc\n wuv\nxyz\n` +y := """ + abc + wuv + xyz +""" +``` + +Similar to unindented strings, indented double-quoted strings process escape +sequences, and indented single-quoted strings ignore escape sequences. Escape +sequence processing takes place after unindentation. The unindentation +algorithm does not take escape-sequence produced whitespace or newlines into +account. + +#### Shell-expanded strings + +Strings prefixed with `x` are shell expanded1.27.0: + +```justfile +foobar := x'~/$FOO/${BAR}' +``` + +| Value | Replacement | +|------|-------------| +| `$VAR` | value of environment variable `VAR` | +| `${VAR}` | value of environment variable `VAR` | +| `${VAR:-DEFAULT}` | value of environment variable `VAR`, or `DEFAULT` if `VAR` is not set | +| Leading `~` | path to current user's home directory | +| Leading `~USER` | path to `USER`'s home directory | + +This expansion is performed at compile time, so variables from `.env` files and +exported `just` variables cannot be used. However, this allows shell expanded +strings to be used in places like settings and import paths, which cannot +depend on `just` variables and `.env` files. + +#### Format strings + +Strings prefixed with `f` are format strings1.44.0: + +```justfile +name := "world" +message := f'Hello, {{name}}!' +``` + +Format strings may contain interpolations delimited with `{{…}}` that contain +expressions. Format strings evaluate to the concatenated string fragments and +evaluated expressions. + +Use `{{{{` to include a literal `{{` in a format string: + +```justfile +foo := f'I {{{{LOVE} curly braces!' +``` + +### Ignoring Errors + +Normally, if a command returns a non-zero exit status, execution will stop. To +continue execution after a command, even if it fails, prefix the command with +`-`: + +```just +foo: + -cat foo + echo 'Done!' +``` + +```console +$ just foo +cat foo +cat: foo: No such file or directory +echo 'Done!' +Done! +``` + +### Functions + +`just` provides many built-in functions for use in expressions, including +recipe body `{{…}}` substitutions, assignments, and default parameter values. + +All functions ending in `_directory` can be abbreviated to `_dir`. So +`home_directory()` can also be written as `home_dir()`. In addition, +`invocation_directory_native()` can be abbreviated to +`invocation_dir_native()`. + +#### System Information + +- `arch()` — Instruction set architecture. Possible values are: `"aarch64"`, + `"arm"`, `"asmjs"`, `"hexagon"`, `"mips"`, `"msp430"`, `"powerpc"`, + `"powerpc64"`, `"s390x"`, `"sparc"`, `"wasm32"`, `"x86"`, `"x86_64"`, and + `"xcore"`. +- `num_cpus()`1.15.0 - Number of logical CPUs. +- `os()` — Operating system. Possible values are: `"android"`, `"bitrig"`, + `"dragonfly"`, `"emscripten"`, `"freebsd"`, `"haiku"`, `"ios"`, `"linux"`, + `"macos"`, `"netbsd"`, `"openbsd"`, `"solaris"`, and `"windows"`. +- `os_family()` — Operating system family; possible values are: `"unix"` and + `"windows"`. + +For example: + +```just +system-info: + @echo "This is an {{arch()}} machine". +``` + +```console +$ just system-info +This is an x86_64 machine +``` + +The `os_family()` function can be used to create cross-platform `justfile`s +that work on various operating systems. For an example, see +[cross-platform.just](https://github.com/casey/just/blob/master/examples/cross-platform.just) +file. + +#### External Commands + +- `shell(command, args...)`1.27.0 returns the standard output of shell script + `command` with zero or more positional arguments `args`. The shell used to + interpret `command` is the same shell that is used to evaluate recipe lines, + and can be changed with `set shell := […]`. + + `command` is passed as the first argument, so if the command is `'echo $@'`, + the full command line, with the default shell command `sh -cu` and `args` + `'foo'` and `'bar'` will be: + + ``` + 'sh' '-cu' 'echo $@' 'echo $@' 'foo' 'bar' + ``` + + This is so that `$@` works as expected, and `$1` refers to the first + argument. `$@` does not include the first positional argument, which is + expected to be the name of the program being run. + +```just +# arguments can be variables or expressions +file := '/sys/class/power_supply/BAT0/status' +bat0stat := shell('cat $1', file) + +# commands can be variables or expressions +command := 'wc -l' +output := shell(command + ' "$1"', 'main.c') + +# arguments referenced by the shell command must be used +empty := shell('echo', 'foo') +full := shell('echo $1', 'foo') +error := shell('echo $1') +``` + +```just +# Using python as the shell. Since `python -c` sets `sys.argv[0]` to `'-c'`, +# the first "real" positional argument will be `sys.argv[2]`. +set shell := ["python3", "-c"] +olleh := shell('import sys; print(sys.argv[2][::-1])', 'hello') +``` + +#### Environment Variables + +- `env(key)`1.15.0 — Retrieves the environment variable with name `key`, aborting + if it is not present. + +```just +home_dir := env('HOME') + +test: + echo "{{home_dir}}" +``` + +```console +$ just +/home/user1 +``` + +- `env(key, default)`1.15.0 — Retrieves the environment variable with + name `key`, returning `default` if it is not present. +- `env_var(key)` — Deprecated alias for `env(key)`. +- `env_var_or_default(key, default)` — Deprecated alias for `env(key, default)`. + +A default can be substituted for an empty environment variable value with the +`||` operator, currently unstable: + +```just +set unstable + +foo := env('FOO', '') || 'DEFAULT_VALUE' +``` + +#### Executables + +- `require(name)`1.39.0 — Search directories in the `PATH` + environment variable for the executable `name` and return its full path, or + halt with an error if no executable with `name` exists. + + ```just + bash := require("bash") + + @test: + echo "bash: '{{bash}}'" + ``` + + ```console + $ just + bash: '/bin/bash' + ``` + +- `which(name)`1.39.0 — Search directories in the `PATH` environment + variable for the executable `name` and return its full path, or the empty + string if no executable with `name` exists. Currently unstable. + + + ```just + set unstable + + bosh := which("bosh") + + @test: + echo "bosh: '{{bosh}}'" + ``` + + ```console + $ just + bosh: '' + ``` + +#### Invocation Information + +- `is_dependency()` - Returns the string `true` if the current recipe is being + run as a dependency of another recipe, rather than being run directly, + otherwise returns the string `false`. + +#### Invocation Directory + +- `invocation_directory()` - Retrieves the absolute path to the current + directory when `just` was invoked, before `just` changed it (chdir'd) prior + to executing commands. On Windows, `invocation_directory()` uses `cygpath` to + convert the invocation directory to a Cygwin-compatible `/`-separated path. + Use `invocation_directory_native()` to return the verbatim invocation + directory on all platforms. + +For example, to call `rustfmt` on files just under the "current directory" +(from the user/invoker's perspective), use the following rule: + +```just +rustfmt: + find {{invocation_directory()}} -name \*.rs -exec rustfmt {} \; +``` + +Alternatively, if your command needs to be run from the current directory, you +could use (e.g.): + +```just +build: + cd {{invocation_directory()}}; ./some_script_that_needs_to_be_run_from_here +``` + +- `invocation_directory_native()` - Retrieves the absolute path to the current + directory when `just` was invoked, before `just` changed it (chdir'd) prior + to executing commands. + +#### Justfile and Justfile Directory + +- `justfile()` - Retrieves the path of the current `justfile`. + +- `justfile_directory()` - Retrieves the path of the parent directory of the + current `justfile`. + +For example, to run a command relative to the location of the current +`justfile`: + +```just +script: + {{justfile_directory()}}/scripts/some_script +``` + +#### Source and Source Directory + +- `source_file()`1.27.0 - Retrieves the path of the current source file. + +- `source_directory()`1.27.0 - Retrieves the path of the parent directory of the + current source file. + +`source_file()` and `source_directory()` behave the same as `justfile()` and +`justfile_directory()` in the root `justfile`, but will return the path and +directory, respectively, of the current `import` or `mod` source file when +called from within an import or submodule. + +#### Just Executable + +- `just_executable()` - Absolute path to the `just` executable. + +For example: + +```just +executable: + @echo The executable is at: {{just_executable()}} +``` + +```console +$ just +The executable is at: /bin/just +``` + +#### Just Process ID + +- `just_pid()` - Process ID of the `just` executable. + +For example: + +```just +pid: + @echo The process ID is: {{ just_pid() }} +``` + +```console +$ just +The process ID is: 420 +``` + +#### String Manipulation + +- `append(suffix, s)`1.27.0 Append `suffix` to whitespace-separated + strings in `s`. `append('/src', 'foo bar baz')` → `'foo/src bar/src baz/src'` +- `prepend(prefix, s)`1.27.0 Prepend `prefix` to + whitespace-separated strings in `s`. `prepend('src/', 'foo bar baz')` → + `'src/foo src/bar src/baz'` +- `encode_uri_component(s)`1.27.0 - Percent-encode characters in `s` + except `[A-Za-z0-9_.!~*'()-]`, matching the behavior of the + [JavaScript `encodeURIComponent` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent). +- `quote(s)` - Replace all single quotes with `'\''` and prepend and append + single quotes to `s`. This is sufficient to escape special characters for + many shells, including most Bourne shell descendants. +- `replace(s, from, to)` - Replace all occurrences of `from` in `s` to `to`. +- `replace_regex(s, regex, replacement)` - Replace all occurrences of `regex` + in `s` to `replacement`. Regular expressions are provided by the + [Rust `regex` crate](https://docs.rs/regex/latest/regex/). See the + [syntax documentation](https://docs.rs/regex/latest/regex/#syntax) for usage + examples. Capture groups are supported. The `replacement` string uses + [Replacement string syntax](https://docs.rs/regex/latest/regex/struct.Regex.html#replacement-string-syntax). +- `trim(s)` - Remove leading and trailing whitespace from `s`. +- `trim_end(s)` - Remove trailing whitespace from `s`. +- `trim_end_match(s, substring)` - Remove suffix of `s` matching `substring`. +- `trim_end_matches(s, substring)` - Repeatedly remove suffixes of `s` matching + `substring`. +- `trim_start(s)` - Remove leading whitespace from `s`. +- `trim_start_match(s, substring)` - Remove prefix of `s` matching `substring`. +- `trim_start_matches(s, substring)` - Repeatedly remove prefixes of `s` + matching `substring`. + +#### Case Conversion + +- `capitalize(s)`1.7.0 - Convert first character of `s` to uppercase + and the rest to lowercase. +- `kebabcase(s)`1.7.0 - Convert `s` to `kebab-case`. +- `lowercamelcase(s)`1.7.0 - Convert `s` to `lowerCamelCase`. +- `lowercase(s)` - Convert `s` to lowercase. +- `shoutykebabcase(s)`1.7.0 - Convert `s` to `SHOUTY-KEBAB-CASE`. +- `shoutysnakecase(s)`1.7.0 - Convert `s` to `SHOUTY_SNAKE_CASE`. +- `snakecase(s)`1.7.0 - Convert `s` to `snake_case`. +- `titlecase(s)`1.7.0 - Convert `s` to `Title Case`. +- `uppercamelcase(s)`1.7.0 - Convert `s` to `UpperCamelCase`. +- `uppercase(s)` - Convert `s` to uppercase. + +#### Path Manipulation + +##### Fallible + +- `absolute_path(path)` - Absolute path to relative `path` in the working + directory. `absolute_path("./bar.txt")` in directory `/foo` is + `/foo/bar.txt`. +- `canonicalize(path)`1.24.0 - Canonicalize `path` by resolving symlinks and removing + `.`, `..`, and extra `/`s where possible. +- `extension(path)` - Extension of `path`. `extension("/foo/bar.txt")` is + `txt`. +- `file_name(path)` - File name of `path` with any leading directory components + removed. `file_name("/foo/bar.txt")` is `bar.txt`. +- `file_stem(path)` - File name of `path` without extension. + `file_stem("/foo/bar.txt")` is `bar`. +- `parent_directory(path)` - Parent directory of `path`. + `parent_directory("/foo/bar.txt")` is `/foo`. +- `without_extension(path)` - `path` without extension. + `without_extension("/foo/bar.txt")` is `/foo/bar`. + +These functions can fail, for example if a path does not have an extension, +which will halt execution. + +##### Infallible + +- `clean(path)` - Simplify `path` by removing extra path separators, + intermediate `.` components, and `..` where possible. `clean("foo//bar")` is + `foo/bar`, `clean("foo/..")` is `.`, `clean("foo/./bar")` is `foo/bar`. +- `join(a, b…)` - *This function uses `/` on Unix and `\` on Windows, which can + be lead to unwanted behavior. The `/` operator, e.g., `a / b`, which always + uses `/`, should be considered as a replacement unless `\`s are specifically + desired on Windows.* Join path `a` with path `b`. `join("foo/bar", "baz")` is + `foo/bar/baz`. Accepts two or more arguments. + +#### Filesystem Access + +- `path_exists(path)` - Returns `true` if the path points at an existing entity + and `false` otherwise. Traverses symbolic links, and returns `false` if the + path is inaccessible or points to a broken symlink. +- `read(path)`1.39.0 - Returns the content of file at `path` as + string. + +##### Error Reporting + +- `error(message)` - Abort execution and report error `message` to user. + +#### UUID and Hash Generation + +- `blake3(string)`1.25.0 - Return [BLAKE3] hash of `string` as hexadecimal string. +- `blake3_file(path)`1.25.0 - Return [BLAKE3] hash of file at `path` as hexadecimal + string. +- `sha256(string)` - Return the SHA-256 hash of `string` as hexadecimal string. +- `sha256_file(path)` - Return SHA-256 hash of file at `path` as hexadecimal + string. +- `uuid()` - Generate a random version 4 UUID. + +[BLAKE3]: https://github.com/BLAKE3-team/BLAKE3/ + +#### Random + +- `choose(n, alphabet)`1.27.0 - Generate a string of `n` randomly + selected characters from `alphabet`, which may not contain repeated + characters. For example, `choose('64', HEX)` will generate a random + 64-character lowercase hex string. + +#### Datetime + +- `datetime(format)`1.30.0 - Return local time with `format`. +- `datetime_utc(format)`1.30.0 - Return UTC time with `format`. + +The arguments to `datetime` and `datetime_utc` are `strftime`-style format +strings, see the +[`chrono` library docs](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) +for details. + +#### Semantic Versions + +- `semver_matches(version, requirement)`1.16.0 - Check whether a + [semantic `version`](https://semver.org), e.g., `"0.1.0"` matches a + `requirement`, e.g., `">=0.1.0"`, returning `"true"` if so and `"false"` + otherwise. + +#### Style + +- `style(name)`1.37.0 - Return a named terminal display attribute + escape sequence used by `just`. Unlike terminal display attribute escape + sequence constants, which contain standard colors and styles, `style(name)` + returns an escape sequence used by `just` itself, and can be used to make + recipe output match `just`'s own output. + + Recognized values for `name` are `'command'`, for echoed recipe lines, + `error`, and `warning`. + + For example, to style an error message: + + ```just + scary: + @echo '{{ style("error") }}OH NO{{ NORMAL }}' + ``` + +##### User Directories1.23.0 + +These functions return paths to user-specific directories for things like +configuration, data, caches, executables, and the user's home directory. + +On Unix, these functions follow the +[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). + +On MacOS and Windows, these functions return the system-specified user-specific +directories. For example, `cache_directory()` returns `~/Library/Caches` on +MacOS and `{FOLDERID_LocalAppData}` on Windows. + +See the [`dirs`](https://docs.rs/dirs/latest/dirs/index.html) crate for more +details. + +- `cache_directory()` - The user-specific cache directory. +- `config_directory()` - The user-specific configuration directory. +- `config_local_directory()` - The local user-specific configuration directory. +- `data_directory()` - The user-specific data directory. +- `data_local_directory()` - The local user-specific data directory. +- `executable_directory()` - The user-specific executable directory. +- `home_directory()` - The user's home directory. + +If you would like to use XDG base directories on all platforms you can use the +`env(…)` function with the appropriate environment variable and fallback, +although note that the XDG specification requires ignoring non-absolute paths, +so for full compatibility with spec-compliant applications, you would need to +do: + +```just +xdg_config_dir := if env('XDG_CONFIG_HOME', '') =~ '^/' { + env('XDG_CONFIG_HOME') +} else { + home_directory() / '.config' +} +``` + +### Constants + +A number of constants are predefined: + +| Name | Value | Value on Windows | +|---|---|---| +| `HEX`1.27.0 | `"0123456789abcdef"` | | +| `HEXLOWER`1.27.0 | `"0123456789abcdef"` | | +| `HEXUPPER`1.27.0 | `"0123456789ABCDEF"` | | +| `PATH_SEP`1.41.0 | `"/"` | `"\"` | +| `PATH_VAR_SEP`1.41.0 | `":"` | `";"` | +| `CLEAR`1.37.0 | `"\ec"` | | +| `NORMAL`1.37.0 | `"\e[0m"` | | +| `BOLD`1.37.0 | `"\e[1m"` | | +| `ITALIC`1.37.0 | `"\e[3m"` | | +| `UNDERLINE`1.37.0 | `"\e[4m"` | | +| `INVERT`1.37.0 | `"\e[7m"` | | +| `HIDE`1.37.0 | `"\e[8m"` | | +| `STRIKETHROUGH`1.37.0 | `"\e[9m"` | | +| `BLACK`1.37.0 | `"\e[30m"` | | +| `RED`1.37.0 | `"\e[31m"` | | +| `GREEN`1.37.0 | `"\e[32m"` | | +| `YELLOW`1.37.0 | `"\e[33m"` | | +| `BLUE`1.37.0 | `"\e[34m"` | | +| `MAGENTA`1.37.0 | `"\e[35m"` | | +| `CYAN`1.37.0 | `"\e[36m"` | | +| `WHITE`1.37.0 | `"\e[37m"` | | +| `BG_BLACK`1.37.0 | `"\e[40m"` | | +| `BG_RED`1.37.0 | `"\e[41m"` | | +| `BG_GREEN`1.37.0 | `"\e[42m"` | | +| `BG_YELLOW`1.37.0 | `"\e[43m"` | | +| `BG_BLUE`1.37.0 | `"\e[44m"` | | +| `BG_MAGENTA`1.37.0 | `"\e[45m"` | | +| `BG_CYAN`1.37.0 | `"\e[46m"` | | +| `BG_WHITE`1.37.0 | `"\e[47m"` | | + +```just +@foo: + echo {{HEX}} +``` + +```console +$ just foo +0123456789abcdef +``` + +Constants starting with `\e` are +[ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). + +`CLEAR` clears the screen, similar to the `clear` command. The rest are of the +form `\e[Nm`, where `N` is an integer, and set terminal display attributes. + +Terminal display attribute escape sequences can be combined, for example text +weight `BOLD`, text style `STRIKETHROUGH`, foreground color `CYAN`, and +background color `BG_BLUE`. They should be followed by `NORMAL`, to reset the +terminal back to normal. + +Escape sequences should be quoted, since `[` is treated as a special character +by some shells. + +```just +@foo: + echo '{{BOLD + STRIKETHROUGH + CYAN + BG_BLUE}}Hi!{{NORMAL}}' +``` + +### Attributes + +Recipes, `mod` statements, and aliases may be annotated with attributes that +change their behavior. + +| Name | Type | Description | +|------|------|-------------| +| `[arg(ARG, help="HELP")]`1.46.0 | recipe | Print help string `HELP` for `ARG` in usage messages. | +| `[arg(ARG, long="LONG")]`1.46.0 | recipe | Require values of argument `ARG` to be passed as `--LONG` option. | +| `[arg(ARG, short="S")]`1.46.0 | recipe | Require values of argument `ARG` to be passed as short `-S` option. | +| `[arg(ARG, value="VALUE")]`1.46.0 | recipe | Makes option `ARG` a flag which does not take a value. | +| `[arg(ARG, pattern="PATTERN")]`1.45.0 | recipe | Require values of argument `ARG` to match regular expression `PATTERN`. | +| `[confirm]`1.17.0 | recipe | Require confirmation prior to executing recipe. | +| `[confirm(PROMPT)]`1.23.0 | recipe | Require confirmation prior to executing recipe with a custom prompt. | +| `[default]`1.43.0 | recipe | Use recipe as module's default recipe. | +| `[doc(DOC)]`1.27.0 | module, recipe | Set recipe or module's [documentation comment](#documentation-comments) to `DOC`. | +| `[extension(EXT)]`1.32.0 | recipe | Set shebang recipe script's file extension to `EXT`. `EXT` should include a period if one is desired. | +| `[group(NAME)]`1.27.0 | module, recipe | Put recipe or module in in [group](#groups) `NAME`. | +| `[linux]`1.8.0 | recipe | Enable recipe on Linux. | +| `[macos]`1.8.0 | recipe | Enable recipe on MacOS. | +| `[metadata(METADATA)]`1.42.0 | recipe | Attach `METADATA` to recipe. | +| `[no-cd]`1.9.0 | recipe | Don't change directory before executing recipe. | +| `[no-exit-message]`1.7.0 | recipe | Don't print an error message if recipe fails. | +| `[no-quiet]`1.23.0 | recipe | Override globally quiet recipes and always echo out the recipe. | +| `[openbsd]`1.38.0 | recipe | Enable recipe on OpenBSD. | +| `[parallel]`1.42.0 | recipe | Run this recipe's dependencies in parallel. | +| `[positional-arguments]`1.29.0 | recipe | Turn on [positional arguments](#positional-arguments) for this recipe. | +| `[private]`1.10.0 | alias, recipe | Make recipe, alias, or variable private. See [Private Recipes](#private-recipes). | +| `[script]`1.33.0 | recipe | Execute recipe as script. See [script recipes](#script-recipes) for more details. | +| `[script(COMMAND)]`1.32.0 | recipe | Execute recipe as a script interpreted by `COMMAND`. See [script recipes](#script-recipes) for more details. | +| `[unix]`1.8.0 | recipe | Enable recipe on Unixes. (Includes MacOS). | +| `[windows]`1.8.0 | recipe | Enable recipe on Windows. | +| `[working-directory(PATH)]`1.38.0 | recipe | Set recipe working directory. `PATH` may be relative or absolute. If relative, it is interpreted relative to the default working directory. | + +A recipe can have multiple attributes, either on multiple lines: + +```just +[no-cd] +[private] +foo: + echo "foo" +``` + +Or separated by commas on a single line1.14.0: + +```just +[no-cd, private] +foo: + echo "foo" +``` + +Attributes with a single argument may be written with a colon: + +```just +[group: 'bar'] +foo: +``` + +#### Enabling and Disabling Recipes1.8.0 + +The `[linux]`, `[macos]`, `[unix]`, and `[windows]` attributes are +configuration attributes. By default, recipes are always enabled. A recipe with +one or more configuration attributes will only be enabled when one or more of +those configurations is active. + +This can be used to write `justfile`s that behave differently depending on +which operating system they run on. The `run` recipe in this `justfile` will +compile and run `main.c`, using a different C compiler and using the correct +output binary name for that compiler depending on the operating system: + +```just +[unix] +run: + cc main.c + ./a.out + +[windows] +run: + cl main.c + main.exe +``` + +#### Disabling Changing Directory1.9.0 + +`just` normally executes recipes with the current directory set to the +directory that contains the `justfile`. This can be disabled using the +`[no-cd]` attribute. This can be used to create recipes which use paths +relative to the invocation directory, or which operate on the current +directory. + +For example, this `commit` recipe: + +```just +[no-cd] +commit file: + git add {{file}} + git commit +``` + +Can be used with paths that are relative to the current directory, because +`[no-cd]` prevents `just` from changing the current directory when executing +`commit`. + +#### Requiring Confirmation for Recipes1.17.0 + +`just` normally executes all recipes unless there is an error. The `[confirm]` +attribute allows recipes require confirmation in the terminal prior to running. +This can be overridden by passing `--yes` to `just`, which will automatically +confirm any recipes marked by this attribute. + +Recipes dependent on a recipe that requires confirmation will not be run if the +relied upon recipe is not confirmed, as well as recipes passed after any recipe +that requires confirmation. + +```just +[confirm] +delete-all: + rm -rf * +``` + +#### Custom Confirmation Prompt1.23.0 + +The default confirmation prompt can be overridden with `[confirm(PROMPT)]`: + +```just +[confirm("Are you sure you want to delete everything?")] +delete-everything: + rm -rf * +``` + +### Groups + +Recipes and modules may be annotated with one or more group names: + +```just +[group('lint')] +js-lint: + echo 'Running JS linter…' + +[group('rust recipes')] +[group('lint')] +rust-lint: + echo 'Running Rust linter…' + +[group('lint')] +cpp-lint: + echo 'Running C++ linter…' + +# not in any group +email-everyone: + echo 'Sending mass email…' +``` + +Recipes are listed by group: + +``` +$ just --list +Available recipes: + email-everyone # not in any group + + [lint] + cpp-lint + js-lint + rust-lint + + [rust recipes] + rust-lint +``` + +`just --list --unsorted` prints recipes in their justfile order within each group: + +``` +$ just --list --unsorted +Available recipes: + (no group) + email-everyone # not in any group + + [lint] + js-lint + rust-lint + cpp-lint + + [rust recipes] + rust-lint +``` + +Groups can be listed with `--groups`: + +``` +$ just --groups +Recipe groups: + lint + rust recipes +``` + +Use `just --groups --unsorted` to print groups in their justfile order. + +### Command Evaluation Using Backticks + +Backticks can be used to store the result of commands: + +```just +localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'` + +serve: + ./serve {{localhost}} 8080 +``` + +Indented backticks, delimited by three backticks, are de-indented in the same +manner as indented strings: + +````just +# This backtick evaluates the command `echo foo\necho bar\n`, which produces the value `foo\nbar\n`. +stuff := ``` + echo foo + echo bar + ``` +```` + +See the [Strings](#strings) section for details on unindenting. + +Backticks may not start with `#!`. This syntax is reserved for a future +upgrade. + +The [`shell(…)` function](#external-commands) provides a more general mechanism +to invoke external commands, including the ability to execute the contents of a +variable as a command, and to pass arguments to a command. + +### Conditional Expressions + +`if`/`else` expressions evaluate different branches depending on if two +expressions evaluate to the same value: + +```just +foo := if "2" == "2" { "Good!" } else { "1984" } + +bar: + @echo "{{foo}}" +``` + +```console +$ just bar +Good! +``` + +It is also possible to test for inequality: + +```just +foo := if "hello" != "goodbye" { "xyz" } else { "abc" } + +bar: + @echo {{foo}} +``` + +```console +$ just bar +xyz +``` + +And match against regular expressions: + +```just +foo := if "hello" =~ 'hel+o' { "match" } else { "mismatch" } + +bar: + @echo {{foo}} +``` + +```console +$ just bar +match +``` + +Regular expressions are provided by the +[regex crate](https://github.com/rust-lang/regex), whose syntax is documented on +[docs.rs](https://docs.rs/regex/1.5.4/regex/#syntax). Since regular expressions +commonly use backslash escape sequences, consider using single-quoted string +literals, which will pass slashes to the regex parser unmolested. + +Conditional expressions short-circuit, which means they only evaluate one of +their branches. This can be used to make sure that backtick expressions don't +run when they shouldn't. + +```just +foo := if env_var("RELEASE") == "true" { `get-something-from-release-database` } else { "dummy-value" } +``` + +Conditionals can be used inside of recipes: + +```just +bar foo: + echo {{ if foo == "bar" { "hello" } else { "goodbye" } }} +``` + +Multiple conditionals can be chained: + +```just +foo := if "hello" == "goodbye" { + "xyz" +} else if "a" == "a" { + "abc" +} else { + "123" +} + +bar: + @echo {{foo}} +``` + +```console +$ just bar +abc +``` + +### Stopping execution with error + +Execution can be halted with the `error` function. For example: + +```just +foo := if "hello" == "goodbye" { + "xyz" +} else if "a" == "b" { + "abc" +} else { + error("123") +} +``` + +Which produce the following error when run: + +``` +error: Call to function `error` failed: 123 + | +16 | error("123") +``` + +### Setting Variables from the Command Line + +Variables can be overridden from the command line. + +```just +os := "linux" + +test: build + ./test --test {{os}} + +build: + ./build {{os}} +``` + +```console +$ just +./build linux +./test --test linux +``` + +Any number of arguments of the form `NAME=VALUE` can be passed before recipes: + +```console +$ just os=plan9 +./build plan9 +./test --test plan9 +``` + +Or you can use the `--set` flag: + +```console +$ just --set os bsd +./build bsd +./test --test bsd +``` + +### Getting and Setting Environment Variables + +#### Exporting `just` Variables + +Assignments prefixed with the `export` keyword will be exported to recipes as +environment variables: + +```just +export RUST_BACKTRACE := "1" + +test: + # will print a stack trace if it crashes + cargo test +``` + +Parameters prefixed with a `$` will be exported as environment variables: + +```just +test $RUST_BACKTRACE="1": + # will print a stack trace if it crashes + cargo test +``` + +Exported variables and parameters are not exported to backticks in the same scope. + +```just +export WORLD := "world" +# This backtick will fail with "WORLD: unbound variable" +BAR := `echo hello $WORLD` +``` + +```just +# Running `just a foo` will fail with "A: unbound variable" +a $A $B=`echo $A`: + echo $A $B +``` + +When [export](#export) is set, all `just` variables are exported as environment +variables. + +#### Unexporting Environment Variables1.29.0 + +Environment variables can be unexported with the `unexport keyword`: + +```just +unexport FOO + +@foo: + echo $FOO +``` + +``` +$ export FOO=bar +$ just foo +sh: FOO: unbound variable +``` + +#### Getting Environment Variables from the environment + +Environment variables from the environment are passed automatically to the +recipes. + +```just +print_home_folder: + echo "HOME is: '${HOME}'" +``` + +```console +$ just +HOME is '/home/myuser' +``` + +#### Setting `just` Variables from Environment Variables + +Environment variables can be propagated to `just` variables using the `env()` function. +See +[environment-variables](#environment-variables). + +### Recipe Parameters + +Recipes may have parameters. Here recipe `build` has a parameter called +`target`: + +```just +build target: + @echo 'Building {{target}}…' + cd {{target}} && make +``` + +To pass arguments on the command line, put them after the recipe name: + +```console +$ just build my-awesome-project +Building my-awesome-project… +cd my-awesome-project && make +``` + +To pass arguments to a dependency, put the dependency in parentheses along with +the arguments: + +```just +default: (build "main") + +build target: + @echo 'Building {{target}}…' + cd {{target}} && make +``` + +Variables can also be passed as arguments to dependencies: + +```just +target := "main" + +_build version: + @echo 'Building {{version}}…' + cd {{version}} && make + +build: (_build target) +``` + +A command's arguments can be passed to dependency by putting the dependency in +parentheses along with the arguments: + +```just +build target: + @echo "Building {{target}}…" + +push target: (build target) + @echo 'Pushing {{target}}…' +``` + +Parameters may have default values: + +```just +default := 'all' + +test target tests=default: + @echo 'Testing {{target}}:{{tests}}…' + ./test --tests {{tests}} {{target}} +``` + +Parameters with default values may be omitted: + +```console +$ just test server +Testing server:all… +./test --tests all server +``` + +Or supplied: + +```console +$ just test server unit +Testing server:unit… +./test --tests unit server +``` + +Default values may be arbitrary expressions, but expressions containing the +`+`, `&&`, `||`, or `/` operators must be parenthesized: + +```just +arch := "wasm" + +test triple=(arch + "-unknown-unknown") input=(arch / "input.dat"): + ./test {{triple}} +``` + +The last parameter of a recipe may be variadic, indicated with either a `+` or +a `*` before the argument name: + +```just +backup +FILES: + scp {{FILES}} me@server.com: +``` + +Variadic parameters prefixed with `+` accept _one or more_ arguments and expand +to a string containing those arguments separated by spaces: + +```console +$ just backup FAQ.md GRAMMAR.md +scp FAQ.md GRAMMAR.md me@server.com: +FAQ.md 100% 1831 1.8KB/s 00:00 +GRAMMAR.md 100% 1666 1.6KB/s 00:00 +``` + +Variadic parameters prefixed with `*` accept _zero or more_ arguments and +expand to a string containing those arguments separated by spaces, or an empty +string if no arguments are present: + +```just +commit MESSAGE *FLAGS: + git commit {{FLAGS}} -m "{{MESSAGE}}" +``` + +Variadic parameters can be assigned default values. These are overridden by +arguments passed on the command line: + +```just +test +FLAGS='-q': + cargo test {{FLAGS}} +``` + +`{{…}}` substitutions may need to be quoted if they contain spaces. For +example, if you have the following recipe: + +```just +search QUERY: + lynx https://www.google.com/?q={{QUERY}} +``` + +And you type: + +```console +$ just search "cat toupee" +``` + +`just` will run the command `lynx https://www.google.com/?q=cat toupee`, which +will get parsed by `sh` as `lynx`, `https://www.google.com/?q=cat`, and +`toupee`, and not the intended `lynx` and `https://www.google.com/?q=cat toupee`. + +You can fix this by adding quotes: + +```just +search QUERY: + lynx 'https://www.google.com/?q={{QUERY}}' +``` + +Parameters prefixed with a `$` will be exported as environment variables: + +```just +foo $bar: + echo $bar +``` + +Parameters may be constrained to match regular expression patterns using the +`[arg("name", pattern="pattern")]` attribute1.45.0: + +```just +[arg('n', pattern='\d+')] +double n: + echo $(({{n}} * 2)) +``` + +A leading `^` and trailing `$` are added to the pattern, so it must match the +entire argument value. + +You may constrain the pattern to a number of alternatives using the `|` +operator: + +```just +[arg('flag', pattern='--help|--version')] +info flag: + just {{flag}} +``` + +Regular expressions are provided by the +[Rust `regex` crate](https://docs.rs/regex/latest/regex/). See the +[syntax documentation](https://docs.rs/regex/latest/regex/#syntax) for usage +examples. + +Usage information for a recipe may be printed with the `--usage` +subcommand1.46.0: + +```console +$ just --usage foo +Usage: just foo [OPTIONS] bar + +Arguments: + bar +``` + +Help strings may be added to arguments using the `[arg(ARG, help=HELP)]` attribute: + +```just +[arg("bar", help="hello")] +foo bar: +``` + +```console +$ just --usage foo +Usage: just foo bar + +Arguments: + bar hello +``` + +#### Recipe Flags and Options + +Recipe parameters are positional by default. + +In this `justfile`: + +```just +@foo bar: + echo bar={{bar}} +``` + +The parameter `bar` is positional: + +```console +$ just foo hello +bar=hello +``` + +The `[arg(ARG, long=OPTION)]`1.46.0 attribute can be used to make a +parameter a long option. + +In this `justfile`: + +```just +[arg("bar", long="bar")] +foo bar: +``` + +The parameter `bar` is given with the `--bar` option: + +```console +$ just foo --bar hello +bar=hello +``` + +Options may also be passed with `--name=value` syntax: + +```console +$ just foo --bar=hello +bar=hello +``` + +The value of `long` can be omitted, in which case the option defaults to the +name of the parameter: + +```just +[arg("bar", long)] +foo bar: +``` + +The `[arg(ARG, short=OPTION)]`1.46.0 attribute can be used to make a +parameter a short option. + +In this `justfile`: + +```just +[arg("bar", short="b")] +foo bar: +``` + +The parameter `bar` is given with the `-b` option: + +```console +$ just foo -b hello +bar=hello +``` + +If a parameter has both a long and short option, it may be passed using either. + +Variadic `+` and `?` parameters cannot be options. + +The `[arg(ARG, value=VALUE, …)]`1.46.0 attribute can be used with +`long` or `short` to make a parameter a flag which does not take a value. + +In this `justfile`: + +```just +[arg("bar", long="bar", value="hello")] +foo bar: +``` + +The parameter `bar` is given with the `--bar` option, but does not take a +value, and instead takes the value given in the `[arg]` attribute: + +```console +$ just foo --bar +bar=hello +``` + +This is useful for unconditionally requiring a flag like `--force` on dangerous +commands. + +A flag is optional if its parameter has a default: + +```just +[arg("bar", long="bar", value="hello")] +foo bar="goodbye": +``` + +Causing it to receive the default when not passed in the invocation: + +```console +$ just foo +bar=goodbye +``` + +### Dependencies + +Dependencies run before recipes that depend on them: + +```just +a: b + @echo A + +b: + @echo B +``` + +``` +$ just a +B +A +``` + +In a given invocation of `just`, a recipe with the same arguments will only run +once, regardless of how many times it appears in the command-line invocation, +or how many times it appears as a dependency: + +```just +a: + @echo A + +b: a + @echo B + +c: a + @echo C +``` + +``` +$ just a a a a a +A +$ just b c +A +B +C +``` + +Multiple recipes may depend on a recipe that performs some kind of setup, and +when those recipes run, that setup will only be performed once: + +```just +build: + cc main.c + +test-foo: build + ./a.out --test foo + +test-bar: build + ./a.out --test bar +``` + +``` +$ just test-foo test-bar +cc main.c +./a.out --test foo +./a.out --test bar +``` + +Recipes in a given run are only skipped when they receive the same arguments: + +```just +build: + cc main.c + +test TEST: build + ./a.out --test {{TEST}} +``` + +``` +$ just test foo test bar +cc main.c +./a.out --test foo +./a.out --test bar +``` + +#### Running Recipes at the End of a Recipe + +Normal dependencies of a recipes always run before a recipe starts. That is to +say, the dependee always runs before the depender. These dependencies are +called "prior dependencies". + +A recipe can also have subsequent dependencies, which run immediately after the +recipe and are introduced with an `&&`: + +```just +a: + echo 'A!' + +b: a && c d + echo 'B!' + +c: + echo 'C!' + +d: + echo 'D!' +``` + +…running _b_ prints: + +```console +$ just b +echo 'A!' +A! +echo 'B!' +B! +echo 'C!' +C! +echo 'D!' +D! +``` + +#### Running Recipes in the Middle of a Recipe + +`just` doesn't support running recipes in the middle of another recipe, but you +can call `just` recursively in the middle of a recipe. Given the following +`justfile`: + +```just +a: + echo 'A!' + +b: a + echo 'B start!' + just c + echo 'B end!' + +c: + echo 'C!' +``` + +…running _b_ prints: + +```console +$ just b +echo 'A!' +A! +echo 'B start!' +B start! +echo 'C!' +C! +echo 'B end!' +B end! +``` + +This has limitations, since recipe `c` is run with an entirely new invocation +of `just`: Assignments will be recalculated, dependencies might run twice, and +command line arguments will not be propagated to the child `just` process. + +### Shebang Recipes + +Recipes that start with `#!` are called shebang recipes, and are executed by +saving the recipe body to a file and running it. This lets you write recipes in +different languages: + +```just +polyglot: python js perl sh ruby nu + +python: + #!/usr/bin/env python3 + print('Hello from python!') + +js: + #!/usr/bin/env node + console.log('Greetings from JavaScript!') + +perl: + #!/usr/bin/env perl + print "Larry Wall says Hi!\n"; + +sh: + #!/usr/bin/env sh + hello='Yo' + echo "$hello from a shell script!" + +nu: + #!/usr/bin/env nu + let hello = 'Hola' + echo $"($hello) from a nushell script!" + +ruby: + #!/usr/bin/env ruby + puts "Hello from ruby!" +``` + +```console +$ just polyglot +Hello from python! +Greetings from JavaScript! +Larry Wall says Hi! +Yo from a shell script! +Hola from a nushell script! +Hello from ruby! +``` + +On Unix-like operating systems, including Linux and MacOS, shebang recipes are +executed by saving the recipe body to a file in a temporary directory, marking +the file as executable, and executing it. The OS then parses the shebang line +into a command line and invokes it, including the path to the file. For +example, if a recipe starts with `#!/usr/bin/env bash`, the final command that +the OS runs will be something like `/usr/bin/env bash +/tmp/PATH_TO_SAVED_RECIPE_BODY`. + +Shebang line splitting is operating system dependent. When passing a command +with arguments, you may need to tell `env` to split them explicitly by using +the `-S` flag: + +```just +run: + #!/usr/bin/env -S bash -x + ls +``` + +Windows does not support shebang lines. On Windows, `just` splits the shebang +line into a command and arguments, saves the recipe body to a file, and invokes +the split command and arguments, adding the path to the saved recipe body as +the final argument. For example, on Windows, if a recipe starts with `#! py`, +the final command the OS runs will be something like +`py C:\Temp\PATH_TO_SAVED_RECIPE_BODY`. + +### Script Recipes + +Recipes with a `[script(COMMAND)]`1.32.0 attribute are run as +scripts interpreted by `COMMAND`. This avoids some of the issues with shebang +recipes, such as the use of `cygpath` on Windows, the need to use +`/usr/bin/env`, inconsistencies in shebang line splitting across Unix OSs, and +requiring a temporary directory from which files can be executed. + +Recipes with an empty `[script]` attribute are executed with the value of `set +script-interpreter := […]`1.33.0, defaulting to `sh -eu`, and *not* +the value of `set shell`. + +The body of the recipe is evaluated, written to disk in the temporary +directory, and run by passing its path as an argument to `COMMAND`. + +### Script and Shebang Recipe Temporary Files + +Both script and shebang recipes write the recipe body to a temporary file for +execution. Script recipes execute that file by passing it to a command, while +shebang recipes execute the file directly. Shebang recipe execution will fail +if the filesystem containing the temporary file is mounted with `noexec` or is +otherwise non-executable. + +The directory that `just` writes temporary files to may be configured in a +number of ways, from highest to lowest precedence: + +- Globally with the `--tempdir` command-line option or the `JUST_TEMPDIR` + environment variable1.41.0. + +- On a per-module basis with the `tempdir` setting. + +- Globally on Linux with the `XDG_RUNTIME_DIR` environment variable. + +- Falling back to the directory returned by + [std::env::temp_dir](https://doc.rust-lang.org/std/env/fn.temp_dir.html). + +### Python Recipes with `uv` + +[`uv`](https://github.com/astral-sh/uv) is an excellent cross-platform python +project manager, written in Rust. + +Using the `[script]` attribute and `script-interpreter` setting, `just` can +easily be configured to run Python recipes with `uv`: + +```just +set unstable + +set script-interpreter := ['uv', 'run', '--script'] + +[script] +hello: + print("Hello from Python!") + +[script] +goodbye: + # /// script + # requires-python = ">=3.11" + # dependencies=["sh"] + # /// + import sh + print(sh.echo("Goodbye from Python!"), end='') +``` + +Of course, a shebang also works: + +```just +hello: + #!/usr/bin/env -S uv run --script + print("Hello from Python!") +``` + + +### Safer Bash Shebang Recipes + +If you're writing a `bash` shebang recipe, consider adding `set -euxo +pipefail`: + +```just +foo: + #!/usr/bin/env bash + set -euxo pipefail + hello='Yo' + echo "$hello from Bash!" +``` + +It isn't strictly necessary, but `set -euxo pipefail` turns on a few useful +features that make `bash` shebang recipes behave more like normal, linewise +`just` recipe: + +- `set -e` makes `bash` exit if a command fails. + +- `set -u` makes `bash` exit if a variable is undefined. + +- `set -x` makes `bash` print each script line before it's run. + +- `set -o pipefail` makes `bash` exit if a command in a pipeline fails. This is + `bash`-specific, so isn't turned on in normal linewise `just` recipes. + +Together, these avoid a lot of shell scripting gotchas. + +#### Shebang Recipe Execution on Windows + +On Windows, shebang interpreter paths containing a `/` are translated from +Unix-style paths to Windows-style paths using `cygpath`, a utility that ships +with [Cygwin](http://www.cygwin.com). + +For example, to execute this recipe on Windows: + +```just +echo: + #!/bin/sh + echo "Hello!" +``` + +The interpreter path `/bin/sh` will be translated to a Windows-style path using +`cygpath` before being executed. + +If the interpreter path does not contain a `/` it will be executed without +being translated. This is useful if `cygpath` is not available, or you wish to +pass a Windows-style path to the interpreter. + +### Setting Variables in a Recipe + +Recipe lines are interpreted by the shell, not `just`, so it's not possible to +set `just` variables in the middle of a recipe: + +```justfile +foo: + x := "hello" # This doesn't work! + echo {{x}} +``` + +It is possible to use shell variables, but there's another problem. Every +recipe line is run by a new shell instance, so variables set in one line won't +be set in the next: + +```just +foo: + x=hello && echo $x # This works! + y=bye + echo $y # This doesn't, `y` is undefined here! +``` + +The best way to work around this is to use a shebang recipe. Shebang recipe +bodies are extracted and run as scripts, so a single shell instance will run +the whole thing: + +```just +foo: + #!/usr/bin/env bash + set -euxo pipefail + x=hello + echo $x +``` + +### Sharing Environment Variables Between Recipes + +Each line of each recipe is executed by a fresh shell, so it is not possible to +share environment variables between recipes. + +#### Using Python Virtual Environments + +Some tools, like [Python's venv](https://docs.python.org/3/library/venv.html), +require loading environment variables in order to work, making them challenging +to use with `just`. As a workaround, you can execute the virtual environment +binaries directly: + +```just +venv: + [ -d foo ] || python3 -m venv foo + +run: venv + ./foo/bin/python3 main.py +``` + +### Changing the Working Directory in a Recipe + +Each recipe line is executed by a new shell, so if you change the working +directory on one line, it won't have an effect on later lines: + +```just +foo: + pwd # This `pwd` will print the same directory… + cd bar + pwd # …as this `pwd`! +``` + +There are a couple ways around this. One is to call `cd` on the same line as +the command you want to run: + +```just +foo: + cd bar && pwd +``` + +The other is to use a shebang recipe. Shebang recipe bodies are extracted and +run as scripts, so a single shell instance will run the whole thing, and thus a +`cd` on one line will affect later lines, just like a shell script: + +```just +foo: + #!/usr/bin/env bash + set -euxo pipefail + cd bar + pwd +``` + +### Indentation + +Recipe lines can be indented with spaces or tabs, but not a mix of both. All of +a recipe's lines must have the same type of indentation, but different recipes +in the same `justfile` may use different indentation. + +Each recipe must be indented at least one level from the `recipe-name` but +after that may be further indented. + +Here's a justfile with a recipe indented with spaces, represented as `·`, and +tabs, represented as `→`. + +```justfile +set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"] + +set ignore-comments + +list-space directory: +··#!pwsh +··foreach ($item in $(Get-ChildItem {{directory}} )) { +····echo $item.Name +··} +··echo "" + +# indentation nesting works even when newlines are escaped +list-tab directory: +→ @foreach ($item in $(Get-ChildItem {{directory}} )) { \ +→ → echo $item.Name \ +→ } +→ @echo "" +``` + +```pwsh +PS > just list-space ~ +Desktop +Documents +Downloads + +PS > just list-tab ~ +Desktop +Documents +Downloads +``` + +### Multi-Line Constructs + +Recipes without an initial shebang are evaluated and run line-by-line, which +means that multi-line constructs probably won't do what you want. + +For example, with the following `justfile`: + +```justfile +conditional: + if true; then + echo 'True!' + fi +``` + +The extra leading whitespace before the second line of the `conditional` recipe +will produce a parse error: + +```console +$ just conditional +error: Recipe line has extra leading whitespace + | +3 | echo 'True!' + | ^^^^^^^^^^^^^^^^ +``` + +To work around this, you can write conditionals on one line, escape newlines +with slashes, or add a shebang to your recipe. Some examples of multi-line +constructs are provided for reference. + +#### `if` statements + +```just +conditional: + if true; then echo 'True!'; fi +``` + +```just +conditional: + if true; then \ + echo 'True!'; \ + fi +``` + +```just +conditional: + #!/usr/bin/env sh + if true; then + echo 'True!' + fi +``` + +#### `for` loops + +```just +for: + for file in `ls .`; do echo $file; done +``` + +```just +for: + for file in `ls .`; do \ + echo $file; \ + done +``` + +```just +for: + #!/usr/bin/env sh + for file in `ls .`; do + echo $file + done +``` + +#### `while` loops + +```just +while: + while `server-is-dead`; do ping -c 1 server; done +``` + +```just +while: + while `server-is-dead`; do \ + ping -c 1 server; \ + done +``` + +```just +while: + #!/usr/bin/env sh + while `server-is-dead`; do + ping -c 1 server + done +``` + +#### Outside Recipe Bodies + +Parenthesized expressions can span multiple lines: + +```just +abc := ('a' + + 'b' + + 'c') + +abc2 := ( + 'a' + + 'b' + + 'c' +) + +foo param=('foo' + + 'bar' + ): + echo {{param}} + +bar: (foo + 'Foo' + ) + echo 'Bar!' +``` + +Lines ending with a backslash continue on to the next line as if the lines were +joined by whitespace1.15.0: + +```just +a := 'foo' + \ + 'bar' + +foo param1 \ + param2='foo' \ + *varparam='': dep1 \ + (dep2 'foo') + echo {{param1}} {{param2}} {{varparam}} + +dep1: \ + # this comment is not part of the recipe body + echo 'dep1' + +dep2 \ + param: + echo 'Dependency with parameter {{param}}' +``` + +Backslash line continuations can also be used in interpolations. The line +following the backslash must be indented. + +```just +recipe: + echo '{{ \ + "This interpolation " + \ + "has a lot of text." \ + }}' + echo 'back to recipe body' +``` + +### Command-line Options + +`just` supports a number of useful command-line options for listing, dumping, +and debugging recipes and variables: + +```console +$ just --list +Available recipes: + js + perl + polyglot + python + ruby +$ just --show perl +perl: + #!/usr/bin/env perl + print "Larry Wall says Hi!\n"; +$ just --show polyglot +polyglot: python js perl sh ruby +``` + +#### Setting Command-line Options with Environment Variables + +Some command-line options can be set with environment variables + +For example, unstable features can be enabled either with the `--unstable` +flag: + +```console +$ just --unstable +``` + +Or by setting the `JUST_UNSTABLE` environment variable: + +```console +$ export JUST_UNSTABLE=1 +$ just +``` + +Since environment variables are inherited by child processes, command-line +options set with environment variables are inherited by recursive invocations +of `just`, where as command line options set with arguments are not. + +Consult `just --help` for which options can be set with environment variables. + +### Private Recipes + +Recipes and aliases whose name starts with a `_` are omitted from `just --list`: + +```just +test: _test-helper + ./bin/test + +_test-helper: + ./bin/super-secret-test-helper-stuff +``` + +```console +$ just --list +Available recipes: + test +``` + +And from `just --summary`: + +```console +$ just --summary +test +``` + +The `[private]` attribute1.10.0 may also be used to hide recipes or +aliases without needing to change the name: + +```just +[private] +foo: + +[private] +alias b := bar + +bar: +``` + +```console +$ just --list +Available recipes: + bar +``` + +This is useful for helper recipes which are only meant to be used as +dependencies of other recipes. + +### Quiet Recipes + +A recipe name may be prefixed with `@` to invert the meaning of `@` before each +line: + +```just +@quiet: + echo hello + echo goodbye + @# all done! +``` + +Now only the lines starting with `@` will be echoed: + +```console +$ just quiet +hello +goodbye +# all done! +``` + +All recipes in a Justfile can be made quiet with `set quiet`: + +```just +set quiet + +foo: + echo "This is quiet" + +@foo2: + echo "This is also quiet" +``` + +The `[no-quiet]` attribute overrides this setting: + +```just +set quiet + +foo: + echo "This is quiet" + +[no-quiet] +foo2: + echo "This is not quiet" +``` + +Shebang recipes are quiet by default: + +```just +foo: + #!/usr/bin/env bash + echo 'Foo!' +``` + +```console +$ just foo +Foo! +``` + +Adding `@` to a shebang recipe name makes `just` print the recipe before +executing it: + +```just +@bar: + #!/usr/bin/env bash + echo 'Bar!' +``` + +```console +$ just bar +#!/usr/bin/env bash +echo 'Bar!' +Bar! +``` + +`just` normally prints error messages when a recipe line fails. These error +messages can be suppressed using the `[no-exit-message]`1.7.0 +attribute. You may find this especially useful with a recipe that wraps a tool: + +```just +git *args: + @git {{args}} +``` + +```console +$ just git status +fatal: not a git repository (or any of the parent directories): .git +error: Recipe `git` failed on line 2 with exit code 128 +``` + +Add the attribute to suppress the exit error message when the tool exits with a +non-zero code: + +```just +[no-exit-message] +git *args: + @git {{args}} +``` + +```console +$ just git status +fatal: not a git repository (or any of the parent directories): .git +``` + +### Selecting Recipes to Run With an Interactive Chooser + +The `--choose` subcommand makes `just` invoke a chooser to select which recipes +to run. Choosers should read lines containing recipe names from standard input +and print one or more of those names separated by spaces to standard output. + +Because there is currently no way to run a recipe that requires arguments with +`--choose`, such recipes will not be given to the chooser. Private recipes and +aliases are also skipped. + +The chooser can be overridden with the `--chooser` flag. If `--chooser` is not +given, then `just` first checks if `$JUST_CHOOSER` is set. If it isn't, then +the chooser defaults to `fzf`, a popular fuzzy finder. + +Arguments can be included in the chooser, i.e. `fzf --exact`. + +The chooser is invoked in the same way as recipe lines. For example, if the +chooser is `fzf`, it will be invoked with `sh -cu 'fzf'`, and if the shell, or +the shell arguments are overridden, the chooser invocation will respect those +overrides. + +If you'd like `just` to default to selecting recipes with a chooser, you can +use this as your default recipe: + +```just +default: + @just --choose +``` + +### Invoking `justfile`s in Other Directories + +If the first argument passed to `just` contains a `/`, then the following +occurs: + +1. The argument is split at the last `/`. + +2. The part before the last `/` is treated as a directory. `just` will start + its search for the `justfile` there, instead of in the current directory. + +3. The part after the last slash is treated as a normal argument, or ignored + if it is empty. + +This may seem a little strange, but it's useful if you wish to run a command in +a `justfile` that is in a subdirectory. + +For example, if you are in a directory which contains a subdirectory named +`foo`, which contains a `justfile` with the recipe `build`, which is also the +default recipe, the following are all equivalent: + +```console +$ (cd foo && just build) +$ just foo/build +$ just foo/ +``` + +Additional recipes after the first are sought in the same `justfile`. For +example, the following are both equivalent: + +```console +$ just foo/a b +$ (cd foo && just a b) +``` + +And will both invoke recipes `a` and `b` in `foo/justfile`. + +### Imports + +One `justfile` can include the contents of another using `import` statements. + +If you have the following `justfile`: + +```justfile +import 'foo/bar.just' + +a: b + @echo A +``` + +And the following text in `foo/bar.just`: + +```just +b: + @echo B +``` + +`foo/bar.just` will be included in `justfile` and recipe `b` will be defined: + +```console +$ just b +B +$ just a +B +A +``` + +The `import` path can be absolute or relative to the location of the justfile +containing it. A leading `~/` in the import path is replaced with the current +users home directory. + +Justfiles are insensitive to order, so included files can reference variables +and recipes defined after the `import` statement. + +Imported files can themselves contain `import`s, which are processed +recursively. + +`allow-duplicate-recipes` and `allow-duplicate-variables` allow duplicate +recipes and variables, respectively, to override each other, instead of +producing an error. + +Within a module, later definitions override earlier definitions: + +```just +set allow-duplicate-recipes + +foo: + +foo: + echo 'yes' +``` + +When `import`s are involved, things unfortunately get much more complicated and +hard to explain. + +Shallower definitions always override deeper definitions, so recipes at the top +level will override recipes in imports, and recipes in an import will override +recipes in an import which itself imports those recipes. + +When two duplicate definitions are imported and are at the same depth, the one +from the earlier import will override the one from the later import. + +This is because `just` uses a stack when processing imports, pushing imports +onto the stack in source-order, and always processing the top of the stack +next, so earlier imports are actually handled later by the compiler. + +This is definitely a bug, but since `just` has very strong backwards +compatibility guarantees and we take enormous pains not to break anyone's +`justfile`, we have created issue #2540 to discuss whether or not we can +actually fix it. + +Imports may be made optional by putting a `?` after the `import` keyword: + +```just +import? 'foo/bar.just' +``` + +Importing the same source file multiple times is not an error1.37.0. +This allows importing multiple justfiles, for example `foo.just` and +`bar.just`, which both import a third justfile containing shared recipes, for +example `baz.just`, without the duplicate import of `baz.just` being an error: + +```justfile +# justfile +import 'foo.just' +import 'bar.just' +``` + +```justfile +# foo.just +import 'baz.just' +foo: baz +``` + +```justfile +# bar.just +import 'baz.just' +bar: baz +``` + +```just +# baz +baz: +``` + +### Modules1.19.0 + +A `justfile` can declare modules using `mod` statements. + +`mod` statements were stabilized in `just`1.31.0. In earlier +versions, you'll need to use the `--unstable` flag, `set unstable`, or set the +`JUST_UNSTABLE` environment variable to use them. + +If you have the following `justfile`: + +```justfile +mod bar + +a: + @echo A +``` + +And the following text in `bar.just`: + +```just +b: + @echo B +``` + +`bar.just` will be included in `justfile` as a submodule. Recipes, aliases, and +variables defined in one submodule cannot be used in another, and each module +uses its own settings. + +Recipes in submodules can be invoked as subcommands: + +```console +$ just bar b +B +``` + +Or with path syntax: + +```console +$ just bar::b +B +``` + +If a module is named `foo`, just will search for the module file in `foo.just`, +`foo/mod.just`, `foo/justfile`, and `foo/.justfile`. In the latter two cases, +the module file may have any capitalization. + +Module statements may be of the form: + +```justfile +mod foo 'PATH' +``` + +Which loads the module's source file from `PATH`, instead of from the usual +locations. A leading `~/` in `PATH` is replaced with the current user's home +directory. `PATH` may point to the module source file itself, or to a directory +containing the module source file with the name `mod.just`, `justfile`, or +`.justfile`. In the latter two cases, the module file may have any +capitalization. + +Environment files are only loaded for the root justfile, and loaded environment +variables are available in submodules. Settings in submodules that affect +environment file loading are ignored. + +Recipes in submodules without the `[no-cd]` attribute run with the working +directory set to the directory containing the submodule source file. + +`justfile()` and `justfile_directory()` always return the path to the root +justfile and the directory that contains it, even when called from submodule +recipes. + +Modules may be made optional by putting a `?` after the `mod` keyword: + +```just +mod? foo +``` + +Missing source files for optional modules do not produce an error. + +Optional modules with no source file do not conflict, so you can have multiple +mod statements with the same name, but with different source file paths, as +long as at most one source file exists: + +```just +mod? foo 'bar.just' +mod? foo 'baz.just' +``` + +Modules may be given doc comments which appear in `--list` +output1.30.0: + +```justfile +# foo is a great module! +mod foo +``` + +```console +$ just --list +Available recipes: + foo ... # foo is a great module! +``` + +Modules are still missing a lot of features, for example, the ability to refer +to variables in other modules. See the [module improvement tracking +issue](https://github.com/casey/just/issues/2252) for more information. + +### Hiding `justfile`s + +`just` looks for `justfile`s named `justfile` and `.justfile`, which can be +used to keep a `justfile` hidden. + +### Just Scripts + +By adding a shebang line to the top of a `justfile` and making it executable, +`just` can be used as an interpreter for scripts: + +```console +$ cat > script < formatted-justfile +``` + +The `--dump` command can be used with `--dump-format json` to print a JSON +representation of a `justfile`. + +### Fallback to parent `justfile`s + +If a recipe is not found in a `justfile` and the `fallback` setting is set, +`just` will look for `justfile`s in the parent directory and up, until it +reaches the root directory. `just` will stop after it reaches a `justfile` in +which the `fallback` setting is `false` or unset. + +As an example, suppose the current directory contains this `justfile`: + +```just +set fallback +foo: + echo foo +``` + +And the parent directory contains this `justfile`: + +```just +bar: + echo bar +``` + +```console +$ just bar +Trying ../justfile +echo bar +bar +``` + +### Avoiding Argument Splitting + +Given this `justfile`: + +```just +foo argument: + touch {{argument}} +``` + +The following command will create two files, `some` and `argument.txt`: + +```console +$ just foo "some argument.txt" +``` + +The user's shell will parse `"some argument.txt"` as a single argument, but +when `just` replaces `touch {{argument}}` with `touch some argument.txt`, the +quotes are not preserved, and `touch` will receive two arguments. + +There are a few ways to avoid this: quoting, positional arguments, and exported +arguments. + +#### Quoting + +Quotes can be added around the `{{argument}}` interpolation: + +```just +foo argument: + touch '{{argument}}' +``` + +This preserves `just`'s ability to catch variable name typos before running, +for example if you were to write `{{argument}}`, but will not do what you want +if the value of `argument` contains single quotes. + +#### Positional Arguments + +The `positional-arguments` setting causes all arguments to be passed as +positional arguments, allowing them to be accessed with `$1`, `$2`, …, and +`$@`, which can be then double-quoted to avoid further splitting by the shell: + +```just +set positional-arguments + +foo argument: + touch "$1" +``` + +This defeats `just`'s ability to catch typos, for example if you type `$2` +instead of `$1`, but works for all possible values of `argument`, including +those with double quotes. + +#### Exported Arguments + +All arguments are exported when the `export` setting is set: + +```just +set export + +foo argument: + touch "$argument" +``` + +Or individual arguments may be exported by prefixing them with `$`: + +```just +foo $argument: + touch "$argument" +``` + +This defeats `just`'s ability to catch typos, for example if you type +`$argument`, but works for all possible values of `argument`, including those +with double quotes. + +### Configuring the Shell + +There are a number of ways to configure the shell for linewise recipes, which +are the default when a recipe does not start with a `#!` shebang. Their +precedence, from highest to lowest, is: + +1. The `--shell` and `--shell-arg` command line options. Passing either of + these will cause `just` to ignore any settings in the current justfile. +2. `set windows-shell := [...]` +3. `set windows-powershell` (deprecated) +4. `set shell := [...]` + +Since `set windows-shell` has higher precedence than `set shell`, you can use +`set windows-shell` to pick a shell on Windows, and `set shell` to pick a shell +for all other platforms. + +### Timestamps + +`just` can print timestamps before each recipe commands: + +```just +recipe: + echo one + sleep 2 + echo two +``` + +``` +$ just --timestamp recipe +[07:28:46] echo one +one +[07:28:46] sleep 2 +[07:28:48] echo two +two +``` + +By default, timestamps are formatted as `HH:MM:SS`. The format can be changed +with `--timestamp-format`: + +``` +$ just --timestamp recipe --timestamp-format '%H:%M:%S%.3f %Z' +[07:32:11:.349 UTC] echo one +one +[07:32:11:.350 UTC] sleep 2 +[07:32:13:.352 UTC] echo two +two +``` + +The argument to `--timestamp-format` is a `strftime`-style format string, see +the +[`chrono` library docs](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) +for details. + +### Signal Handling + +[Signals](https://en.wikipedia.org/wiki/Signal_(IPC)) are messsages sent to +running programs to trigger specific behavior. For example, `SIGINT` is sent to +all processes in the terminal forground process group when `CTRL-C` is pressed. + +`just` tries to exit when requested by a signal, but it also tries to avoid +leaving behind running child proccesses, two goals which are somewhat in +conflict. + +If `just` exits leaving behind child processes, the user will have no recourse +but to `ps aux | grep` for the children and manually `kill` them, a tedious +endevour. + +#### Fatal Signals + +`SIGHUP`, `SIGINT`, and `SIGQUIT` are generated when the user closes the +terminal, types `ctrl-c`, or types `ctrl-\`, respectively, and are sent to all +processes in the foreground process group. + +`SIGTERM` is the default signal sent by the `kill` command, and is delivered +only to its intended victim. + +When a child process is not running, `just` will exit immediately on receipt of +any of the above signals. + +When a child process *is* running, `just` will wait until it terminates, to +avoid leaving it behind. + +Additionally, on receipt of `SIGTERM`, `just` will forward `SIGTERM` to any +running children1.41.0, since unlike other fatal signals, `SIGTERM`, +was likely sent to `just` alone. + +Regardless of whether a child process terminates successfully after `just` +receives a fatal signal, `just` halts execution. + +#### `SIGINFO` + +`SIGINFO` is sent to all processes in the foreground process group when the +user types `ctrl-t` on +[BSD](https://en.wikipedia.org/wiki/Berkeley_Software_Distribution)-derived +operating systems, including MacOS, but not Linux. + +`just` responds by printing a list of all child process IDs and +commands1.41.0. + +#### Windows + +On Windows, `just` behaves as if it had received `SIGINT` when the user types +`ctrl-c`. Other signals are unsupported. + +Changelog +--------- + +A changelog for the latest release is available in +[CHANGELOG.md](https://raw.githubusercontent.com/casey/just/master/CHANGELOG.md). +Changelogs for previous releases are available on +[the releases page](https://github.com/casey/just/releases). `just --changelog` +can also be used to make a `just` binary print its changelog. + +Miscellanea +----------- + +### Re-running recipes when files change + +[`watchexec`](https://github.com/mattgreen/watchexec) can re-run any command +when files change. + +To re-run the recipe `foo` when any file changes: + +```console +watchexec just foo +``` + +See `watchexec --help` for more info, including how to specify which files +should be watched for changes. + +### Parallelism + +Dependencies may be run in parallel with the `[parallel]` attribute. + +In this `justfile`, `foo`, `bar`, and `baz` will execute in parallel when +`main` is run: + +```just +[parallel] +main: foo bar baz + +foo: + sleep 1 + +bar: + sleep 1 + +baz: + sleep 1 +``` + +GNU `parallel` may be used to run recipe lines concurrently: + +```just +parallel: + #!/usr/bin/env -S parallel --shebang --ungroup --jobs {{ num_cpus() }} + echo task 1 start; sleep 3; echo task 1 done + echo task 2 start; sleep 3; echo task 2 done + echo task 3 start; sleep 3; echo task 3 done + echo task 4 start; sleep 3; echo task 4 done +``` + +### Shell Alias + +For lightning-fast command running, put `alias j=just` in your shell's +configuration file. + +In `bash`, the aliased command may not keep the shell completion functionality +described in the next section. Add the following line to your `.bashrc` to use +the same completion function as `just` for your aliased command: + +```console +complete -F _just -o bashdefault -o default j +``` + +### Shell Completion Scripts + +Shell completion scripts for Bash, Elvish, Fish, Nushell, PowerShell, and Zsh +are available [release archives](https://github.com/casey/just/releases). + +The `just` binary can also generate the same completion scripts at runtime +using `just --completions SHELL`: + +```console +$ just --completions zsh > just.zsh +``` + +Please refer to your shell's documentation for how to install them. + +*macOS Note:* Recent versions of macOS use zsh as the default shell. If you use +Homebrew to install `just`, it will automatically install the most recent copy +of the zsh completion script in the Homebrew zsh directory, which the built-in +version of zsh doesn't know about by default. It's best to use this copy of the +script if possible, since it will be updated whenever you update `just` via +Homebrew. Also, many other Homebrew packages use the same location for +completion scripts, and the built-in zsh doesn't know about those either. To +take advantage of `just` completion in zsh in this scenario, you can set +`fpath` to the Homebrew location before calling `compinit`. Note also that Oh +My Zsh runs `compinit` by default. So your `.zshrc` file could look like this: + +```zsh +# Init Homebrew, which adds environment variables +eval "$(brew shellenv)" + +fpath=($HOMEBREW_PREFIX/share/zsh/site-functions $fpath) + +# Then choose one of these options: +# 1. If you're using Oh My Zsh, you can initialize it here +# source $ZSH/oh-my-zsh.sh + +# 2. Otherwise, run compinit yourself +# autoload -U compinit +# compinit +``` + +### Man Page + +`just` can print its own man page with `just --man`. Man pages are written in +[`roff`](https://en.wikipedia.org/wiki/Roff_%28software%29), a venerable markup +language and one of the first practical applications of Unix. If you have +[`groff`](https://www.gnu.org/software/groff/) installed you can view the man +page with `just --man | groff -mandoc -Tascii | less`. + +### Grammar + +A non-normative grammar of `justfile`s can be found in +[GRAMMAR.md](https://github.com/casey/just/blob/master/GRAMMAR.md). + +### just.sh + +Before `just` was a fancy Rust program it was a tiny shell script that called +`make`. You can find the old version in +[contrib/just.sh](https://github.com/casey/just/blob/master/contrib/just.sh). + +### Global and User `justfile`s + +If you want some recipes to be available everywhere, you have a few options. + +#### Global Justfile + +`just --global-justfile`, or `just -g` for short, searches the following paths, +in-order, for a justfile: + +- `$XDG_CONFIG_HOME/just/justfile` +- `$HOME/.config/just/justfile` +- `$HOME/justfile` +- `$HOME/.justfile` + +You can put recipes that are used across many projects in a global justfile to +easily invoke them from any directory. + +#### User justfile tips + +You can also adopt some of the following workflows. These tips assume you've +created a `justfile` at `~/.user.justfile`, but you can put this `justfile` +at any convenient path on your system. + +##### Recipe Aliases + +If you want to call the recipes in `~/.user.justfile` by name, and don't mind +creating an alias for every recipe, add the following to your shell's +initialization script: + +```console +for recipe in `just --justfile ~/.user.justfile --summary`; do + alias $recipe="just --justfile ~/.user.justfile --working-directory . $recipe" +done +``` + +Now, if you have a recipe called `foo` in `~/.user.justfile`, you can just type +`foo` at the command line to run it. + +It took me way too long to realize that you could create recipe aliases like +this. Notwithstanding my tardiness, I am very pleased to bring you this major +advance in `justfile` technology. + +##### Forwarding Alias + +If you'd rather not create aliases for every recipe, you can create a single alias: + +```console +alias .j='just --justfile ~/.user.justfile --working-directory .' +``` + +Now, if you have a recipe called `foo` in `~/.user.justfile`, you can just type +`.j foo` at the command line to run it. + +I'm pretty sure that nobody actually uses this feature, but it's there. + +¯\\\_(ツ)\_/¯ + +##### Customization + +You can customize the above aliases with additional options. For example, if +you'd prefer to have the recipes in your `justfile` run in your home directory, +instead of the current directory: + +```console +alias .j='just --justfile ~/.user.justfile --working-directory ~' +``` + +### Node.js `package.json` Script Compatibility + +The following export statement gives `just` recipes access to local Node module +binaries, and makes `just` recipe commands behave more like `script` entries in +Node.js `package.json` files: + +```just +export PATH := "./node_modules/.bin:" + env_var('PATH') +``` + +### Paths on Windows + +On Windows, all functions that return paths, except `invocation_directory()` +will return `\`-separated paths. When not using PowerShell or `cmd.exe` these +paths should be quoted to prevent the `\`s from being interpreted as character +escapes: + +```just +ls: + echo '{{absolute_path(".")}}' +``` + +`cygpath.exe` is an executable included in some distributions of Unix userlands +for Windows, including [Cygwin](https://www.cygwin.com/) and +[Git](https://git-scm.com/downloads) for Windows. + +`just` uses `cygpath.exe` in two places: + +For backwards compatibility, `invocation_directory()`, uses `cygpath.exe` to +convert the invocation directory into a unix-style `/`-separated path. Use +`invocation_directory_native()` to get the native, Windows-style path. On unix, +`invocation_directory()` and `invocation_directory_native()` both return the +same unix-style path. + +`cygpath.exe` is used also used to convert Unix-style shebang lines into +Windows paths. As an alternative, the `[script]` attribute, currently unstable, +can be used, which does not depend on `cygpath.exe`. + +If `cygpath.exe` is available, you can use it to convert between path styles: + +```just +foo_unix := '/hello/world' +foo_windows := shell('cygpath --windows $1', foo_unix) + +bar_windows := 'C:\hello\world' +bar_unix := shell('cygpath --unix $1', bar_windows) +``` + +### Remote Justfiles + +If you wish to include a `mod` or `import` source file in many `justfiles` +without needing to duplicate it, you can use an optional `mod` or `import`, +along with a recipe to fetch the module source: + +```just +import? 'foo.just' + +fetch: + curl https://raw.githubusercontent.com/casey/just/master/justfile > foo.just +``` + +Given the above `justfile`, after running `just fetch`, the recipes in +`foo.just` will be available. + +### Printing Complex Strings + +`echo` can be used to print strings, but because it processes escape sequences, +like `\n`, and different implementations of `echo` recognize different escape +sequences, using `printf` is often a better choice. + +`printf` takes a C-style format string and any number of arguments, which are +interpolated into the format string. + +This can be combined with indented, triple quoted strings to emulate shell +heredocs. + +Substitution complex strings into recipe bodies with `{…}` can also lead to +trouble as it may be split by the shell into multiple arguments depending on +the presence of whitespace and quotes. Exporting complex strings as environment +variables and referring to them with `"$NAME"`, note the double quotes, can +also help. + +Putting all this together, to print a string verbatim to standard output, with +all its various escape sequences and quotes undisturbed: + +```just +export FOO := ''' + a complicated string with + some dis\tur\bi\ng escape sequences + and "quotes" of 'different' kinds +''' + +bar: + printf %s "$FOO" +``` + +### Alternatives and Prior Art + +There is no shortage of command runners! Some more or less similar alternatives +to `just` include: + +- [make](https://en.wikipedia.org/wiki/Make_(software)): The Unix build tool + that inspired `just`. There are a few different modern day descendents of the + original `make`, including + [FreeBSD Make](https://www.freebsd.org/cgi/man.cgi?make(1)) and + [GNU Make](https://www.gnu.org/software/make/). +- [task](https://github.com/go-task/task): A YAML-based command runner written + in Go. +- [maid](https://github.com/egoist/maid): A Markdown-based command runner + written in JavaScript. +- [microsoft/just](https://github.com/microsoft/just): A JavaScript-based + command runner written in JavaScript. +- [cargo-make](https://github.com/sagiegurari/cargo-make): A command runner for + Rust projects. +- [mmake](https://github.com/tj/mmake): A wrapper around `make` with a number + of improvements, including remote includes. +- [robo](https://github.com/tj/robo): A YAML-based command runner written in + Go. +- [mask](https://github.com/jakedeichert/mask): A Markdown-based command runner + written in Rust. +- [makesure](https://github.com/xonixx/makesure): A simple and portable command + runner written in AWK and shell. +- [haku](https://github.com/VladimirMarkelov/haku): A make-like command runner + written in Rust. +- [mise](https://mise.jdx.dev/): A development environment tool manager written + in Rust supporing tasks in TOML files and standalone scripts. + +Contributing +------------ + +`just` welcomes your contributions! `just` is released under the maximally +permissive +[CC0](https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt) public +domain dedication and fallback license, so your changes must also be released +under this license. + +### Getting Started + +`just` is written in Rust. Use +[rustup](https://www.rust-lang.org/tools/install) to install a Rust toolchain. + +`just` is extensively tested. All new features must be covered by unit or +integration tests. Unit tests are under +[src](https://github.com/casey/just/blob/master/src), live alongside the code +being tested, and test code in isolation. Integration tests are in the [tests +directory](https://github.com/casey/just/blob/master/tests) and test the `just` +binary from the outside by invoking `just` on a given `justfile` and set of +command-line arguments, and checking the output. + +You should write whichever type of tests are easiest to write for your feature +while still providing good test coverage. + +Unit tests are useful for testing new Rust functions that are used internally +and as an aid for development. A good example are the unit tests which cover +the +[`unindent()` function](https://github.com/casey/just/blob/master/src/unindent.rs), +used to unindent triple-quoted strings and backticks. `unindent()` has a bunch +of tricky edge cases which are easy to exercise with unit tests that call +`unindent()` directly. + +Integration tests are useful for making sure that the final behavior of the +`just` binary is correct. `unindent()` is also covered by integration tests +which make sure that evaluating a triple-quoted string produces the correct +unindented value. However, there are not integration tests for all possible +cases. These are covered by faster, more concise unit tests that call +`unindent()` directly. + +Integration tests use the `Test` struct, a builder which allows for easily +invoking `just` with a given `justfile`, arguments, and environment variables, +and checking the program's stdout, stderr, and exit code . + +### Contribution Workflow + +1. Make sure the feature is wanted. There should be an open issue about the + feature with a comment from [@casey](https://github.com/casey) saying that + it's a good idea or seems reasonable. If there isn't, open a new issue and + ask for feedback. + + There are lots of good features which can't be merged, either because they + aren't backwards compatible, have an implementation which would + overcomplicate the codebase, or go against `just`'s design philosophy. + +2. Settle on the design of the feature. If the feature has multiple possible + implementations or syntaxes, make sure to nail down the details in the + issue. + +3. Clone `just` and start hacking. The best workflow is to have the code you're + working on in an editor alongside a job that re-runs tests whenever a file + changes. You can run such a job by installing + [cargo-watch](https://github.com/watchexec/cargo-watch) with `cargo install + cargo-watch` and running `just watch test`. + +4. Add a failing test for your feature. Most of the time this will be an + integration test which exercises the feature end-to-end. Look for an + appropriate file to put the test in in + [tests](https://github.com/casey/just/blob/master/tests), or add a new file + in [tests](https://github.com/casey/just/blob/master/tests) and add a `mod` + statement importing that file in + [tests/lib.rs](https://github.com/casey/just/blob/master/tests/lib.rs). + +5. Implement the feature. + +6. Run `just ci` to make sure that all tests, lints, and checks pass. Requires + [mdBook](https://github.com/rust-lang/mdBook) and + [mdbook-linkcheck](https://github.com/Michael-F-Bryan/mdbook-linkcheck). + +7. Open a PR with the new code that is editable by maintainers. PRs often + require rebasing and minor tweaks. If the PR is not editable by maintainers, + each rebase and tweak will require a round trip of code review. Your PR may + be summarily closed if it is not editable by maintainers. + +8. Incorporate feedback. + +9. Enjoy the sweet feeling of your PR getting merged! + +Feel free to open a draft PR at any time for discussion and feedback. + +### Hints + +Here are some hints to get you started with specific kinds of new features, +which you can use in addition to the contribution workflow above. + +#### Adding a New Attribute + +1. Write a new integration test in + [tests/attributes.rs](https://github.com/casey/just/blob/master/tests/attributes.rs). + +2. Add a new variant to the + [`Attribute`](https://github.com/casey/just/blob/master/src/attribute.rs) + enum. + +3. Implement the functionality of the new attribute. + +4. Run `just ci` to make sure that all tests pass. + +### Janus + +[Janus](https://github.com/casey/janus) is a tool for checking whether a change +to `just` breaks or changes the interpretation of existing `justfile`s. It +collects and analyzes public `justfile`s on GitHub. + +Before merging a particularly large or gruesome change, Janus should be run to +make sure that nothing breaks. Don't worry about running Janus yourself, Casey +will happily run it for you on changes that need it. + +### Minimum Supported Rust Version + +The minimum supported Rust version, or MSRV, is current stable Rust. It may +build on older versions of Rust, but this is not guaranteed. + +### New Releases + +New releases of `just` are made frequently so that users quickly get access to +new features. + +Release commit messages use the following template: + +``` +Release x.y.z + +- Bump version: x.y.z → x.y.z +- Update changelog +- Update changelog contributor credits +- Update dependencies +- Update version references in readme +``` + +Frequently Asked Questions +-------------------------- + +### What are the idiosyncrasies of Make that Just avoids? + +`make` has some behaviors which are confusing, complicated, or make it +unsuitable for use as a general command runner. + +One example is that under some circumstances, `make` won't actually run the +commands in a recipe. For example, if you have a file called `test` and the +following makefile: + +```just +test: + ./test +``` + +`make` will refuse to run your tests: + +```console +$ make test +make: `test' is up to date. +``` + +`make` assumes that the `test` recipe produces a file called `test`. Since this +file exists and the recipe has no other dependencies, `make` thinks that it +doesn't have anything to do and exits. + +To be fair, this behavior is desirable when using `make` as a build system, but +not when using it as a command runner. You can disable this behavior for +specific targets using `make`'s built-in +[`.PHONY` target name](https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html), +but the syntax is verbose and can be hard to remember. The explicit list of +phony targets, written separately from the recipe definitions, also introduces +the risk of accidentally defining a new non-phony target. In `just`, all +recipes are treated as if they were phony. + +Other examples of `make`'s idiosyncrasies include the difference between `=` +and `:=` in assignments, the confusing error messages that are produced if you +mess up your makefile, needing `$$` to use environment variables in recipes, +and incompatibilities between different flavors of `make`. + +### What's the relationship between Just and Cargo build scripts? + +[`cargo` build scripts](http://doc.crates.io/build-script.html) have a pretty +specific use, which is to control how `cargo` builds your Rust project. This +might include adding flags to `rustc` invocations, building an external +dependency, or running some kind of codegen step. + +`just`, on the other hand, is for all the other miscellaneous commands you +might run as part of development. Things like running tests in different +configurations, linting your code, pushing build artifacts to a server, +removing temporary files, and the like. + +Also, although `just` is written in Rust, it can be used regardless of the +language or build system your project uses. + +Further Ramblings +----------------- + +I personally find it very useful to write a `justfile` for almost every +project, big or small. + +On a big project with multiple contributors, it's very useful to have a file +with all the commands needed to work on the project close at hand. + +There are probably different commands to test, build, lint, deploy, and the +like, and having them all in one place is useful and cuts down on the time you +have to spend telling people which commands to run and how to type them. + +And, with an easy place to put commands, it's likely that you'll come up with +other useful things which are part of the project's collective wisdom, but +which aren't written down anywhere, like the arcane commands needed for some +part of your revision control workflow, to install all your project's +dependencies, or all the random flags you might need to pass to the build +system. + +Some ideas for recipes: + +- Deploying/publishing the project + +- Building in release mode vs debug mode + +- Running in debug mode or with logging enabled + +- Complex git workflows + +- Updating dependencies + +- Running different sets of tests, for example fast tests vs slow tests, or + running them with verbose output + +- Any complex set of commands that you really should write down somewhere, if + only to be able to remember them + +Even for small, personal projects it's nice to be able to remember commands by +name instead of ^Reverse searching your shell history, and it's a huge boon to +be able to go into an old project written in a random language with a +mysterious build system and know that all the commands you need to do whatever +you need to do are in the `justfile`, and that if you type `just` something +useful (or at least interesting!) will probably happen. + +For ideas for recipes, check out +[this project's `justfile`](https://github.com/casey/just/blob/master/justfile), +or some of the +`justfile`s +[out in the wild](https://github.com/search?q=path%3A**%2Fjustfile&type=code). + +Anyways, I think that's about it for this incredibly long-winded README. + +I hope you enjoy using `just` and find great success and satisfaction in all +your computational endeavors! + +😸 + +[🔼 Back to the top!](#just) diff --git a/just-bin/completions/just.bash b/just-bin/completions/just.bash new file mode 100644 index 0000000..67f058d --- /dev/null +++ b/just-bin/completions/just.bash @@ -0,0 +1,189 @@ +_just() { + local i cur prev words cword opts cmd + COMPREPLY=() + + # Modules use "::" as the separator, which is considered a wordbreak character in bash. + # The _get_comp_words_by_ref function is a hack to allow for exceptions to this rule without + # modifying the global COMP_WORDBREAKS environment variable. + if type _get_comp_words_by_ref &>/dev/null; then + _get_comp_words_by_ref -n : cur prev words cword + else + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + words=$COMP_WORDS + cword=$COMP_CWORD + fi + + cmd="" + opts="" + + for i in ${words[@]} + do + case "${cmd},${i}" in + ",$1") + cmd="just" + ;; + *) + ;; + esac + done + + case "${cmd}" in + just) + opts="-E -n -g -f -q -u -v -d -c -e -l -s -h -V --alias-style --ceiling --check --chooser --clear-shell-args --color --command-color --cygpath --dotenv-filename --dotenv-path --dry-run --dump-format --explain --global-justfile --highlight --justfile --list-heading --list-prefix --list-submodules --no-aliases --no-deps --no-dotenv --no-highlight --one --quiet --allow-missing --set --shell --shell-arg --shell-command --tempdir --timestamp --timestamp-format --unsorted --unstable --verbose --working-directory --yes --changelog --choose --command --completions --dump --edit --evaluate --fmt --groups --init --list --man --request --show --summary --usage --variables --help --version [ARGUMENTS]..." + if [[ ${cur} == -* ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + else + local recipes=$(just --summary 2> /dev/null) + + if echo "${cur}" | \grep -qF '/'; then + local path_prefix=$(echo "${cur}" | sed 's/[/][^/]*$/\//') + local recipes=$(just --summary 2> /dev/null -- "${path_prefix}") + local recipes=$(printf "${path_prefix}%s\t" $recipes) + fi + + if [[ $? -eq 0 ]]; then + COMPREPLY=( $(compgen -W "${recipes}" -- "${cur}") ) + if type __ltrim_colon_completions &>/dev/null; then + __ltrim_colon_completions "$cur" + fi + return 0 + fi + fi + case "${prev}" in + --alias-style) + COMPREPLY=($(compgen -W "left right separate" -- "${cur}")) + return 0 + ;; + --ceiling) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --chooser) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --color) + COMPREPLY=($(compgen -W "always auto never" -- "${cur}")) + return 0 + ;; + --command-color) + COMPREPLY=($(compgen -W "black blue cyan green purple red yellow" -- "${cur}")) + return 0 + ;; + --cygpath) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --dotenv-filename) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --dotenv-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -E) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --dump-format) + COMPREPLY=($(compgen -W "json just" -- "${cur}")) + return 0 + ;; + --justfile) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -f) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --list-heading) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --list-prefix) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --set) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --shell) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --shell-arg) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --tempdir) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --timestamp-format) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --working-directory) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -d) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --command) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --completions) + COMPREPLY=($(compgen -W "bash elvish fish nushell powershell zsh" -- "${cur}")) + return 0 + ;; + --list) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -l) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --request) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --show) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -s) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --usage) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + esac +} + +if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then + complete -F _just -o nosort -o bashdefault -o default just +else + complete -F _just -o bashdefault -o default just +fi diff --git a/just-bin/completions/just.elvish b/just-bin/completions/just.elvish new file mode 100644 index 0000000..5d21051 --- /dev/null +++ b/just-bin/completions/just.elvish @@ -0,0 +1,94 @@ +use builtin; +use str; + +set edit:completion:arg-completer[just] = {|@words| + fn spaces {|n| + builtin:repeat $n ' ' | str:join '' + } + fn cand {|text desc| + edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc + } + var command = 'just' + for word $words[1..-1] { + if (str:has-prefix $word '-') { + break + } + set command = $command';'$word + } + var completions = [ + &'just'= { + cand --alias-style 'Set list command alias display style' + cand --ceiling 'Do not ascend above directory when searching for a justfile.' + cand --chooser 'Override binary invoked by `--choose`' + cand --color 'Print colorful output' + cand --command-color 'Echo recipe lines in ' + cand --cygpath 'Use binary at to convert between unix and Windows paths.' + cand --dotenv-filename 'Search for environment file named instead of `.env`' + cand -E 'Load as environment file instead of searching for one' + cand --dotenv-path 'Load as environment file instead of searching for one' + cand --dump-format 'Dump justfile as ' + cand -f 'Use as justfile' + cand --justfile 'Use as justfile' + cand --list-heading 'Print before list' + cand --list-prefix 'Print before each list item' + cand --set 'Override with ' + cand --shell 'Invoke to run recipes' + cand --shell-arg 'Invoke shell with as an argument' + cand --tempdir 'Save temporary files to .' + cand --timestamp-format 'Timestamp format string' + cand -d 'Use as working directory. --justfile must also be set' + cand --working-directory 'Use as working directory. --justfile must also be set' + cand -c 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set' + cand --command 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set' + cand --completions 'Print shell completion script for ' + cand -l 'List available recipes in or root if omitted' + cand --list 'List available recipes in or root if omitted' + cand --request 'Execute . For internal testing purposes only. May be changed or removed at any time.' + cand -s 'Show recipe at ' + cand --show 'Show recipe at ' + cand --usage 'Print recipe usage information' + cand --check 'Run `--fmt` in ''check'' mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required.' + cand --clear-shell-args 'Clear shell arguments' + cand -n 'Print what just would do without doing it' + cand --dry-run 'Print what just would do without doing it' + cand --explain 'Print recipe doc comment before running it' + cand -g 'Use global justfile' + cand --global-justfile 'Use global justfile' + cand --highlight 'Highlight echoed recipe lines in bold' + cand --list-submodules 'List recipes in submodules' + cand --no-aliases 'Don''t show aliases in list' + cand --no-deps 'Don''t run recipe dependencies' + cand --no-dotenv 'Don''t load `.env` file' + cand --no-highlight 'Don''t highlight echoed recipe lines in bold' + cand --one 'Forbid multiple recipes from being invoked on the command line' + cand -q 'Suppress all output' + cand --quiet 'Suppress all output' + cand --allow-missing 'Ignore missing recipe and module errors' + cand --shell-command 'Invoke with the shell used to run recipe lines and backticks' + cand --timestamp 'Print recipe command timestamps' + cand -u 'Return list and summary entries in source order' + cand --unsorted 'Return list and summary entries in source order' + cand --unstable 'Enable unstable features' + cand -v 'Use verbose output' + cand --verbose 'Use verbose output' + cand --yes 'Automatically confirm all recipes.' + cand --changelog 'Print changelog' + cand --choose 'Select one or more recipes to run using a binary chooser. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`' + cand --dump 'Print justfile' + cand -e 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`' + cand --edit 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`' + cand --evaluate 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.' + cand --fmt 'Format and overwrite justfile' + cand --groups 'List recipe groups' + cand --init 'Initialize new justfile in project root' + cand --man 'Print man page' + cand --summary 'List names of available recipes' + cand --variables 'List names of variables' + cand -h 'Print help' + cand --help 'Print help' + cand -V 'Print version' + cand --version 'Print version' + } + ] + $completions[$command] +} diff --git a/just-bin/completions/just.fish b/just-bin/completions/just.fish new file mode 100644 index 0000000..9c06a1f --- /dev/null +++ b/just-bin/completions/just.fish @@ -0,0 +1,87 @@ +function __fish_just_complete_recipes + if string match -rq '(-f|--justfile)\s*=?(?[^\s]+)' -- (string split -- ' -- ' (commandline -pc))[1] + set -fx JUST_JUSTFILE "$justfile" + end + printf "%s\n" (string split " " (just --summary)) +end + +# don't suggest files right off +complete -c just -n "__fish_is_first_arg" --no-files + +# complete recipes +complete -c just -a '(__fish_just_complete_recipes)' + +# autogenerated completions +complete -c just -l alias-style -d 'Set list command alias display style' -r -f -a "left\t'' +right\t'' +separate\t''" +complete -c just -l ceiling -d 'Do not ascend above directory when searching for a justfile.' -r -F +complete -c just -l chooser -d 'Override binary invoked by `--choose`' -r +complete -c just -l color -d 'Print colorful output' -r -f -a "always\t'' +auto\t'' +never\t''" +complete -c just -l command-color -d 'Echo recipe lines in ' -r -f -a "black\t'' +blue\t'' +cyan\t'' +green\t'' +purple\t'' +red\t'' +yellow\t''" +complete -c just -l cygpath -d 'Use binary at to convert between unix and Windows paths.' -r -F +complete -c just -l dotenv-filename -d 'Search for environment file named instead of `.env`' -r +complete -c just -s E -l dotenv-path -d 'Load as environment file instead of searching for one' -r -F +complete -c just -l dump-format -d 'Dump justfile as ' -r -f -a "json\t'' +just\t''" +complete -c just -s f -l justfile -d 'Use as justfile' -r -F +complete -c just -l list-heading -d 'Print before list' -r +complete -c just -l list-prefix -d 'Print before each list item' -r +complete -c just -l set -d 'Override with ' -r +complete -c just -l shell -d 'Invoke to run recipes' -r +complete -c just -l shell-arg -d 'Invoke shell with as an argument' -r +complete -c just -l tempdir -d 'Save temporary files to .' -r -F +complete -c just -l timestamp-format -d 'Timestamp format string' -r +complete -c just -s d -l working-directory -d 'Use as working directory. --justfile must also be set' -r -F +complete -c just -s c -l command -d 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set' -r +complete -c just -l completions -d 'Print shell completion script for ' -r -f -a "bash\t'' +elvish\t'' +fish\t'' +nushell\t'' +powershell\t'' +zsh\t''" +complete -c just -s l -l list -d 'List available recipes in or root if omitted' -r +complete -c just -l request -d 'Execute . For internal testing purposes only. May be changed or removed at any time.' -r +complete -c just -s s -l show -d 'Show recipe at ' -r +complete -c just -l usage -d 'Print recipe usage information' -r +complete -c just -l check -d 'Run `--fmt` in \'check\' mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required.' +complete -c just -l clear-shell-args -d 'Clear shell arguments' +complete -c just -s n -l dry-run -d 'Print what just would do without doing it' +complete -c just -l explain -d 'Print recipe doc comment before running it' +complete -c just -s g -l global-justfile -d 'Use global justfile' +complete -c just -l highlight -d 'Highlight echoed recipe lines in bold' +complete -c just -l list-submodules -d 'List recipes in submodules' +complete -c just -l no-aliases -d 'Don\'t show aliases in list' +complete -c just -l no-deps -d 'Don\'t run recipe dependencies' +complete -c just -l no-dotenv -d 'Don\'t load `.env` file' +complete -c just -l no-highlight -d 'Don\'t highlight echoed recipe lines in bold' +complete -c just -l one -d 'Forbid multiple recipes from being invoked on the command line' +complete -c just -s q -l quiet -d 'Suppress all output' +complete -c just -l allow-missing -d 'Ignore missing recipe and module errors' +complete -c just -l shell-command -d 'Invoke with the shell used to run recipe lines and backticks' +complete -c just -l timestamp -d 'Print recipe command timestamps' +complete -c just -s u -l unsorted -d 'Return list and summary entries in source order' +complete -c just -l unstable -d 'Enable unstable features' +complete -c just -s v -l verbose -d 'Use verbose output' +complete -c just -l yes -d 'Automatically confirm all recipes.' +complete -c just -l changelog -d 'Print changelog' +complete -c just -l choose -d 'Select one or more recipes to run using a binary chooser. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`' +complete -c just -l dump -d 'Print justfile' +complete -c just -s e -l edit -d 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`' +complete -c just -l evaluate -d 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable\'s value.' +complete -c just -l fmt -d 'Format and overwrite justfile' +complete -c just -l groups -d 'List recipe groups' +complete -c just -l init -d 'Initialize new justfile in project root' +complete -c just -l man -d 'Print man page' +complete -c just -l summary -d 'List names of available recipes' +complete -c just -l variables -d 'List names of variables' +complete -c just -s h -l help -d 'Print help' +complete -c just -s V -l version -d 'Print version' diff --git a/just-bin/completions/just.nu b/just-bin/completions/just.nu new file mode 100644 index 0000000..ab10910 --- /dev/null +++ b/just-bin/completions/just.nu @@ -0,0 +1,8 @@ +def "nu-complete just" [] { + (^just --dump --unstable --dump-format json | from json).recipes | transpose recipe data | flatten | where {|row| $row.private == false } | select recipe doc parameters | rename value description +} + +# Just: A Command Runner +export extern "just" [ + ...recipe: string@"nu-complete just", # Recipe(s) to run, may be with argument(s) +] diff --git a/just-bin/completions/just.powershell b/just-bin/completions/just.powershell new file mode 100644 index 0000000..1b7e12f --- /dev/null +++ b/just-bin/completions/just.powershell @@ -0,0 +1,120 @@ +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + + $commandElements = $commandAst.CommandElements + $command = @( + 'just' + for ($i = 1; $i -lt $commandElements.Count; $i++) { + $element = $commandElements[$i] + if ($element -isnot [StringConstantExpressionAst] -or + $element.StringConstantType -ne [StringConstantType]::BareWord -or + $element.Value.StartsWith('-') -or + $element.Value -eq $wordToComplete) { + break + } + $element.Value + }) -join ';' + + $completions = @(switch ($command) { + 'just' { + [CompletionResult]::new('--alias-style', '--alias-style', [CompletionResultType]::ParameterName, 'Set list command alias display style') + [CompletionResult]::new('--ceiling', '--ceiling', [CompletionResultType]::ParameterName, 'Do not ascend above directory when searching for a justfile.') + [CompletionResult]::new('--chooser', '--chooser', [CompletionResultType]::ParameterName, 'Override binary invoked by `--choose`') + [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'Print colorful output') + [CompletionResult]::new('--command-color', '--command-color', [CompletionResultType]::ParameterName, 'Echo recipe lines in ') + [CompletionResult]::new('--cygpath', '--cygpath', [CompletionResultType]::ParameterName, 'Use binary at to convert between unix and Windows paths.') + [CompletionResult]::new('--dotenv-filename', '--dotenv-filename', [CompletionResultType]::ParameterName, 'Search for environment file named instead of `.env`') + [CompletionResult]::new('-E', '-E ', [CompletionResultType]::ParameterName, 'Load as environment file instead of searching for one') + [CompletionResult]::new('--dotenv-path', '--dotenv-path', [CompletionResultType]::ParameterName, 'Load as environment file instead of searching for one') + [CompletionResult]::new('--dump-format', '--dump-format', [CompletionResultType]::ParameterName, 'Dump justfile as ') + [CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'Use as justfile') + [CompletionResult]::new('--justfile', '--justfile', [CompletionResultType]::ParameterName, 'Use as justfile') + [CompletionResult]::new('--list-heading', '--list-heading', [CompletionResultType]::ParameterName, 'Print before list') + [CompletionResult]::new('--list-prefix', '--list-prefix', [CompletionResultType]::ParameterName, 'Print before each list item') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'Override with ') + [CompletionResult]::new('--shell', '--shell', [CompletionResultType]::ParameterName, 'Invoke to run recipes') + [CompletionResult]::new('--shell-arg', '--shell-arg', [CompletionResultType]::ParameterName, 'Invoke shell with as an argument') + [CompletionResult]::new('--tempdir', '--tempdir', [CompletionResultType]::ParameterName, 'Save temporary files to .') + [CompletionResult]::new('--timestamp-format', '--timestamp-format', [CompletionResultType]::ParameterName, 'Timestamp format string') + [CompletionResult]::new('-d', '-d', [CompletionResultType]::ParameterName, 'Use as working directory. --justfile must also be set') + [CompletionResult]::new('--working-directory', '--working-directory', [CompletionResultType]::ParameterName, 'Use as working directory. --justfile must also be set') + [CompletionResult]::new('-c', '-c', [CompletionResultType]::ParameterName, 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set') + [CompletionResult]::new('--command', '--command', [CompletionResultType]::ParameterName, 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set') + [CompletionResult]::new('--completions', '--completions', [CompletionResultType]::ParameterName, 'Print shell completion script for ') + [CompletionResult]::new('-l', '-l', [CompletionResultType]::ParameterName, 'List available recipes in or root if omitted') + [CompletionResult]::new('--list', '--list', [CompletionResultType]::ParameterName, 'List available recipes in or root if omitted') + [CompletionResult]::new('--request', '--request', [CompletionResultType]::ParameterName, 'Execute . For internal testing purposes only. May be changed or removed at any time.') + [CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'Show recipe at ') + [CompletionResult]::new('--show', '--show', [CompletionResultType]::ParameterName, 'Show recipe at ') + [CompletionResult]::new('--usage', '--usage', [CompletionResultType]::ParameterName, 'Print recipe usage information') + [CompletionResult]::new('--check', '--check', [CompletionResultType]::ParameterName, 'Run `--fmt` in ''check'' mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required.') + [CompletionResult]::new('--clear-shell-args', '--clear-shell-args', [CompletionResultType]::ParameterName, 'Clear shell arguments') + [CompletionResult]::new('-n', '-n', [CompletionResultType]::ParameterName, 'Print what just would do without doing it') + [CompletionResult]::new('--dry-run', '--dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it') + [CompletionResult]::new('--explain', '--explain', [CompletionResultType]::ParameterName, 'Print recipe doc comment before running it') + [CompletionResult]::new('-g', '-g', [CompletionResultType]::ParameterName, 'Use global justfile') + [CompletionResult]::new('--global-justfile', '--global-justfile', [CompletionResultType]::ParameterName, 'Use global justfile') + [CompletionResult]::new('--highlight', '--highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold') + [CompletionResult]::new('--list-submodules', '--list-submodules', [CompletionResultType]::ParameterName, 'List recipes in submodules') + [CompletionResult]::new('--no-aliases', '--no-aliases', [CompletionResultType]::ParameterName, 'Don''t show aliases in list') + [CompletionResult]::new('--no-deps', '--no-deps', [CompletionResultType]::ParameterName, 'Don''t run recipe dependencies') + [CompletionResult]::new('--no-dotenv', '--no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file') + [CompletionResult]::new('--no-highlight', '--no-highlight', [CompletionResultType]::ParameterName, 'Don''t highlight echoed recipe lines in bold') + [CompletionResult]::new('--one', '--one', [CompletionResultType]::ParameterName, 'Forbid multiple recipes from being invoked on the command line') + [CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'Suppress all output') + [CompletionResult]::new('--quiet', '--quiet', [CompletionResultType]::ParameterName, 'Suppress all output') + [CompletionResult]::new('--allow-missing', '--allow-missing', [CompletionResultType]::ParameterName, 'Ignore missing recipe and module errors') + [CompletionResult]::new('--shell-command', '--shell-command', [CompletionResultType]::ParameterName, 'Invoke with the shell used to run recipe lines and backticks') + [CompletionResult]::new('--timestamp', '--timestamp', [CompletionResultType]::ParameterName, 'Print recipe command timestamps') + [CompletionResult]::new('-u', '-u', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order') + [CompletionResult]::new('--unsorted', '--unsorted', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order') + [CompletionResult]::new('--unstable', '--unstable', [CompletionResultType]::ParameterName, 'Enable unstable features') + [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'Use verbose output') + [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'Use verbose output') + [CompletionResult]::new('--yes', '--yes', [CompletionResultType]::ParameterName, 'Automatically confirm all recipes.') + [CompletionResult]::new('--changelog', '--changelog', [CompletionResultType]::ParameterName, 'Print changelog') + [CompletionResult]::new('--choose', '--choose', [CompletionResultType]::ParameterName, 'Select one or more recipes to run using a binary chooser. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`') + [CompletionResult]::new('--dump', '--dump', [CompletionResultType]::ParameterName, 'Print justfile') + [CompletionResult]::new('-e', '-e', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`') + [CompletionResult]::new('--edit', '--edit', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`') + [CompletionResult]::new('--evaluate', '--evaluate', [CompletionResultType]::ParameterName, 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.') + [CompletionResult]::new('--fmt', '--fmt', [CompletionResultType]::ParameterName, 'Format and overwrite justfile') + [CompletionResult]::new('--groups', '--groups', [CompletionResultType]::ParameterName, 'List recipe groups') + [CompletionResult]::new('--init', '--init', [CompletionResultType]::ParameterName, 'Initialize new justfile in project root') + [CompletionResult]::new('--man', '--man', [CompletionResultType]::ParameterName, 'Print man page') + [CompletionResult]::new('--summary', '--summary', [CompletionResultType]::ParameterName, 'List names of available recipes') + [CompletionResult]::new('--variables', '--variables', [CompletionResultType]::ParameterName, 'List names of variables') + [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help') + [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version') + [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version') + break + } + }) + + function Get-JustFileRecipes([string[]]$CommandElements) { + $justFileIndex = $commandElements.IndexOf("--justfile"); + + if ($justFileIndex -ne -1 -and $justFileIndex + 1 -le $commandElements.Length) { + $justFileLocation = $commandElements[$justFileIndex + 1] + } + + $justArgs = @("--summary") + + if (Test-Path $justFileLocation) { + $justArgs += @("--justfile", $justFileLocation) + } + + $recipes = $(just @justArgs) -split ' ' + return $recipes | ForEach-Object { [CompletionResult]::new($_) } + } + + $elementValues = $commandElements | Select-Object -ExpandProperty Value + $recipes = Get-JustFileRecipes -CommandElements $elementValues + $completions += $recipes + $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | + Sort-Object -Property ListItemText +} diff --git a/just-bin/completions/just.zsh b/just-bin/completions/just.zsh new file mode 100644 index 0000000..58c8a7a --- /dev/null +++ b/just-bin/completions/just.zsh @@ -0,0 +1,181 @@ +#compdef just + +autoload -U is-at-least + +_just() { + typeset -A opt_args + typeset -a _arguments_options + local ret=1 + + if is-at-least 5.2; then + _arguments_options=(-s -S -C) + else + _arguments_options=(-s -C) + fi + + local context curcontext="$curcontext" state line + local common=( +'(--no-aliases)--alias-style=[Set list command alias display style]: :(left right separate)' \ +'--ceiling=[Do not ascend above directory when searching for a justfile.]: :_files' \ +'--chooser=[Override binary invoked by \`--choose\`]: :_default' \ +'--color=[Print colorful output]: :(always auto never)' \ +'--command-color=[Echo recipe lines in ]: :(black blue cyan green purple red yellow)' \ +'--cygpath=[Use binary at to convert between unix and Windows paths.]: :_files' \ +'(-E --dotenv-path)--dotenv-filename=[Search for environment file named instead of \`.env\`]: :_default' \ +'-E+[Load as environment file instead of searching for one]: :_files' \ +'--dotenv-path=[Load as environment file instead of searching for one]: :_files' \ +'--dump-format=[Dump justfile as ]:FORMAT:(json just)' \ +'-f+[Use as justfile]: :_files' \ +'--justfile=[Use as justfile]: :_files' \ +'--list-heading=[Print before list]:TEXT:_default' \ +'--list-prefix=[Print before each list item]:TEXT:_default' \ +'*--set=[Override with ]: :(_just_variables)' \ +'--shell=[Invoke to run recipes]: :_default' \ +'*--shell-arg=[Invoke shell with as an argument]: :_default' \ +'--tempdir=[Save temporary files to .]: :_files' \ +'--timestamp-format=[Timestamp format string]: :_default' \ +'-d+[Use as working directory. --justfile must also be set]: :_files' \ +'--working-directory=[Use as working directory. --justfile must also be set]: :_files' \ +'*-c+[Run an arbitrary command with the working directory, \`.env\`, overrides, and exports set]: :_default' \ +'*--command=[Run an arbitrary command with the working directory, \`.env\`, overrides, and exports set]: :_default' \ +'--completions=[Print shell completion script for ]:SHELL:(bash elvish fish nushell powershell zsh)' \ +'()-l+[List available recipes in or root if omitted]' \ +'()--list=[List available recipes in or root if omitted]' \ +'--request=[Execute . For internal testing purposes only. May be changed or removed at any time.]: :_default' \ +'-s+[Show recipe at ]: :(_just_commands)' \ +'--show=[Show recipe at ]: :(_just_commands)' \ +'()--usage=[Print recipe usage information]:PATH:_default' \ +'--check[Run \`--fmt\` in '\''check'\'' mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required.]' \ +'--clear-shell-args[Clear shell arguments]' \ +'(-q --quiet)-n[Print what just would do without doing it]' \ +'(-q --quiet)--dry-run[Print what just would do without doing it]' \ +'--explain[Print recipe doc comment before running it]' \ +'(-f --justfile -d --working-directory)-g[Use global justfile]' \ +'(-f --justfile -d --working-directory)--global-justfile[Use global justfile]' \ +'--highlight[Highlight echoed recipe lines in bold]' \ +'--list-submodules[List recipes in submodules]' \ +'--no-aliases[Don'\''t show aliases in list]' \ +'--no-deps[Don'\''t run recipe dependencies]' \ +'--no-dotenv[Don'\''t load \`.env\` file]' \ +'--no-highlight[Don'\''t highlight echoed recipe lines in bold]' \ +'--one[Forbid multiple recipes from being invoked on the command line]' \ +'(-n --dry-run)-q[Suppress all output]' \ +'(-n --dry-run)--quiet[Suppress all output]' \ +'--allow-missing[Ignore missing recipe and module errors]' \ +'--shell-command[Invoke with the shell used to run recipe lines and backticks]' \ +'--timestamp[Print recipe command timestamps]' \ +'-u[Return list and summary entries in source order]' \ +'--unsorted[Return list and summary entries in source order]' \ +'--unstable[Enable unstable features]' \ +'*-v[Use verbose output]' \ +'*--verbose[Use verbose output]' \ +'--yes[Automatically confirm all recipes.]' \ +'--changelog[Print changelog]' \ +'--choose[Select one or more recipes to run using a binary chooser. If \`--chooser\` is not passed the chooser defaults to the value of \$JUST_CHOOSER, falling back to \`fzf\`]' \ +'--dump[Print justfile]' \ +'-e[Edit justfile with editor given by \$VISUAL or \$EDITOR, falling back to \`vim\`]' \ +'--edit[Edit justfile with editor given by \$VISUAL or \$EDITOR, falling back to \`vim\`]' \ +'--evaluate[Evaluate and print all variables. If a variable name is given as an argument, only print that variable'\''s value.]' \ +'--fmt[Format and overwrite justfile]' \ +'--groups[List recipe groups]' \ +'--init[Initialize new justfile in project root]' \ +'--man[Print man page]' \ +'--summary[List names of available recipes]' \ +'--variables[List names of variables]' \ +'-h[Print help]' \ +'--help[Print help]' \ +'-V[Print version]' \ +'--version[Print version]' \ +) + + _arguments "${_arguments_options[@]}" $common \ + '1: :_just_commands' \ + '*: :->args' \ + && ret=0 + + case $state in + args) + curcontext="${curcontext%:*}-${words[2]}:" + + local lastarg=${words[${#words}]} + local recipe + + local cmds; cmds=( + ${(s: :)$(_call_program commands just --summary)} + ) + + # Find first recipe name + for ((i = 2; i < $#words; i++ )) do + if [[ ${cmds[(I)${words[i]}]} -gt 0 ]]; then + recipe=${words[i]} + break + fi + done + + if [[ $lastarg = */* ]]; then + # Arguments contain slash would be recognised as a file + _arguments -s -S $common '*:: :_files' + elif [[ $lastarg = *=* ]]; then + # Arguments contain equal would be recognised as a variable + _message "value" + elif [[ $recipe ]]; then + # Show usage message + _message "`just --show $recipe`" + # Or complete with other commands + #_arguments -s -S $common '*:: :_just_commands' + else + _arguments -s -S $common '*:: :_just_commands' + fi + ;; + esac + + return ret + +} + +(( $+functions[_just_commands] )) || +_just_commands() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local variables; variables=( + ${(s: :)$(_call_program commands just --variables)} + ) + local commands; commands=( + ${${${(M)"${(f)$(_call_program commands just --list)}":# *}/ ##/}/ ##/:Args: } + ) + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + *) _message 'value' && ret=0 ;; + esac + else + _describe -t variables 'variables' variables -qS "=" && ret=0 + _describe -t commands 'just commands' commands "$@" + fi + +} + +if [ "$funcstack[1]" = "_just" ]; then + (( $+functions[_just_variables] )) || +_just_variables() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local variables; variables=( + ${(s: :)$(_call_program commands just --variables)} + ) + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + *) _message 'value' && ret=0 ;; + esac + else + _describe -t variables 'variables' variables && ret=0 + fi + + return ret +} + +_just "$@" +else + compdef _just just +fi diff --git a/just-bin/just b/just-bin/just new file mode 100755 index 0000000..0c46cc7 --- /dev/null +++ b/just-bin/just @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b616db5c759b43fcf39471f18c9b0104cbc86f89c43d2fc407a7c0d65dd015 +size 4906296 diff --git a/just-bin/just.1 b/just-bin/just.1 new file mode 100644 index 0000000..b88ee2a --- /dev/null +++ b/just-bin/just.1 @@ -0,0 +1,294 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH just 1 "just 1.46.0" +.SH NAME +just \- 🤖 Just a command runner \- https://github.com/casey/just +.SH SYNOPSIS +\fBjust\fR [\fB\-\-alias\-style\fR] [\fB\-\-ceiling\fR] [\fB\-\-check\fR] [\fB\-\-chooser\fR] [\fB\-\-clear\-shell\-args\fR] [\fB\-\-color\fR] [\fB\-\-command\-color\fR] [\fB\-\-cygpath\fR] [\fB\-\-dotenv\-filename\fR] [\fB\-E\fR|\fB\-\-dotenv\-path\fR] [\fB\-n\fR|\fB\-\-dry\-run\fR] [\fB\-\-dump\-format\fR] [\fB\-\-explain\fR] [\fB\-g\fR|\fB\-\-global\-justfile\fR] [\fB\-\-highlight\fR] [\fB\-f\fR|\fB\-\-justfile\fR] [\fB\-\-list\-heading\fR] [\fB\-\-list\-prefix\fR] [\fB\-\-list\-submodules\fR] [\fB\-\-no\-aliases\fR] [\fB\-\-no\-deps\fR] [\fB\-\-no\-dotenv\fR] [\fB\-\-no\-highlight\fR] [\fB\-\-one\fR] [\fB\-q\fR|\fB\-\-quiet\fR] [\fB\-\-allow\-missing\fR] [\fB\-\-set\fR] [\fB\-\-shell\fR] [\fB\-\-shell\-arg\fR] [\fB\-\-shell\-command\fR] [\fB\-\-tempdir\fR] [\fB\-\-timestamp\fR] [\fB\-\-timestamp\-format\fR] [\fB\-u\fR|\fB\-\-unsorted\fR] [\fB\-\-unstable\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-d\fR|\fB\-\-working\-directory\fR] [\fB\-\-yes\fR] [\fB\-\-changelog\fR] [\fB\-\-choose\fR] [\fB\-c\fR|\fB\-\-command\fR] [\fB\-\-completions\fR] [\fB\-\-dump\fR] [\fB\-e\fR|\fB\-\-edit\fR] [\fB\-\-evaluate\fR] [\fB\-\-fmt\fR] [\fB\-\-groups\fR] [\fB\-\-init\fR] [\fB\-l\fR|\fB\-\-list\fR] [\fB\-\-man\fR] [\fB\-s\fR|\fB\-\-show\fR] [\fB\-\-summary\fR] [\fB\-\-usage\fR] [\fB\-\-variables\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIARGUMENTS\fR] +.SH DESCRIPTION +🤖 Just a command runner \- https://github.com/casey/just +.SH OPTIONS +.TP +\fB\-\-alias\-style\fR [default: right] +Set list command alias display style +.br + +.br +[\fIpossible values: \fRleft, right, separate] +.RS +May also be specified with the \fBJUST_ALIAS_STYLE\fR environment variable. +.RE +.TP +\fB\-\-ceiling\fR +Do not ascend above directory when searching for a justfile. +.RS +May also be specified with the \fBJUST_CEILING\fR environment variable. +.RE +.TP +\fB\-\-check\fR +Run `\-\-fmt` in \*(Aqcheck\*(Aq mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required. +.TP +\fB\-\-chooser\fR +Override binary invoked by `\-\-choose` +.RS +May also be specified with the \fBJUST_CHOOSER\fR environment variable. +.RE +.TP +\fB\-\-clear\-shell\-args\fR +Clear shell arguments +.TP +\fB\-\-color\fR [default: auto] +Print colorful output +.br + +.br +[\fIpossible values: \fRalways, auto, never] +.RS +May also be specified with the \fBJUST_COLOR\fR environment variable. +.RE +.TP +\fB\-\-command\-color\fR +Echo recipe lines in +.br + +.br +[\fIpossible values: \fRblack, blue, cyan, green, purple, red, yellow] +.RS +May also be specified with the \fBJUST_COMMAND_COLOR\fR environment variable. +.RE +.TP +\fB\-\-cygpath\fR [default: cygpath] +Use binary at to convert between unix and Windows paths. +.RS +May also be specified with the \fBJUST_CYGPATH\fR environment variable. +.RE +.TP +\fB\-\-dotenv\-filename\fR +Search for environment file named instead of `.env` +.TP +\fB\-E\fR, \fB\-\-dotenv\-path\fR +Load as environment file instead of searching for one +.TP +\fB\-n\fR, \fB\-\-dry\-run\fR +Print what just would do without doing it +.RS +May also be specified with the \fBJUST_DRY_RUN\fR environment variable. +.RE +.TP +\fB\-\-dump\-format\fR \fI\fR [default: just] +Dump justfile as +.br + +.br +[\fIpossible values: \fRjson, just] +.RS +May also be specified with the \fBJUST_DUMP_FORMAT\fR environment variable. +.RE +.TP +\fB\-\-explain\fR +Print recipe doc comment before running it +.RS +May also be specified with the \fBJUST_EXPLAIN\fR environment variable. +.RE +.TP +\fB\-g\fR, \fB\-\-global\-justfile\fR +Use global justfile +.TP +\fB\-\-highlight\fR +Highlight echoed recipe lines in bold +.RS +May also be specified with the \fBJUST_HIGHLIGHT\fR environment variable. +.RE +.TP +\fB\-f\fR, \fB\-\-justfile\fR +Use as justfile +.RS +May also be specified with the \fBJUST_JUSTFILE\fR environment variable. +.RE +.TP +\fB\-\-list\-heading\fR \fI\fR [default: Available recipes: +] +Print before list +.RS +May also be specified with the \fBJUST_LIST_HEADING\fR environment variable. +.RE +.TP +\fB\-\-list\-prefix\fR \fI\fR [default: ] +Print before each list item +.RS +May also be specified with the \fBJUST_LIST_PREFIX\fR environment variable. +.RE +.TP +\fB\-\-list\-submodules\fR +List recipes in submodules +.RS +May also be specified with the \fBJUST_LIST_SUBMODULES\fR environment variable. +.RE +.TP +\fB\-\-no\-aliases\fR +Don\*(Aqt show aliases in list +.RS +May also be specified with the \fBJUST_NO_ALIASES\fR environment variable. +.RE +.TP +\fB\-\-no\-deps\fR +Don\*(Aqt run recipe dependencies +.RS +May also be specified with the \fBJUST_NO_DEPS\fR environment variable. +.RE +.TP +\fB\-\-no\-dotenv\fR +Don\*(Aqt load `.env` file +.RS +May also be specified with the \fBJUST_NO_DOTENV\fR environment variable. +.RE +.TP +\fB\-\-no\-highlight\fR +Don\*(Aqt highlight echoed recipe lines in bold +.RS +May also be specified with the \fBJUST_NO_HIGHLIGHT\fR environment variable. +.RE +.TP +\fB\-\-one\fR +Forbid multiple recipes from being invoked on the command line +.RS +May also be specified with the \fBJUST_ONE\fR environment variable. +.RE +.TP +\fB\-q\fR, \fB\-\-quiet\fR +Suppress all output +.RS +May also be specified with the \fBJUST_QUIET\fR environment variable. +.RE +.TP +\fB\-\-allow\-missing\fR +Ignore missing recipe and module errors +.RS +May also be specified with the \fBJUST_ALLOW_MISSING\fR environment variable. +.RE +.TP +\fB\-\-set\fR \fI\fR\fI \fR\fI\fR +Override with +.TP +\fB\-\-shell\fR +Invoke to run recipes +.TP +\fB\-\-shell\-arg\fR +Invoke shell with as an argument +.TP +\fB\-\-shell\-command\fR +Invoke with the shell used to run recipe lines and backticks +.TP +\fB\-\-tempdir\fR +Save temporary files to . +.RS +May also be specified with the \fBJUST_TEMPDIR\fR environment variable. +.RE +.TP +\fB\-\-timestamp\fR +Print recipe command timestamps +.RS +May also be specified with the \fBJUST_TIMESTAMP\fR environment variable. +.RE +.TP +\fB\-\-timestamp\-format\fR [default: %H:%M:%S] +Timestamp format string +.RS +May also be specified with the \fBJUST_TIMESTAMP_FORMAT\fR environment variable. +.RE +.TP +\fB\-u\fR, \fB\-\-unsorted\fR +Return list and summary entries in source order +.RS +May also be specified with the \fBJUST_UNSORTED\fR environment variable. +.RE +.TP +\fB\-\-unstable\fR +Enable unstable features +.RS +May also be specified with the \fBJUST_UNSTABLE\fR environment variable. +.RE +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Use verbose output +.RS +May also be specified with the \fBJUST_VERBOSE\fR environment variable. +.RE +.TP +\fB\-d\fR, \fB\-\-working\-directory\fR +Use as working directory. \-\-justfile must also be set +.RS +May also be specified with the \fBJUST_WORKING_DIRECTORY\fR environment variable. +.RE +.TP +\fB\-\-yes\fR +Automatically confirm all recipes. +.RS +May also be specified with the \fBJUST_YES\fR environment variable. +.RE +.TP +\fB\-h\fR, \fB\-\-help\fR +Print help +.TP +\fB\-V\fR, \fB\-\-version\fR +Print version +.TP +[\fIARGUMENTS\fR] +Overrides and recipe(s) to run, defaulting to the first recipe in the justfile +.SH COMMANDS +.TP +\fB\-\-changelog\fR +Print changelog +.TP +\fB\-\-choose\fR +Select one or more recipes to run using a binary chooser. If `\-\-chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf` +.TP +\fB\-c\fR, \fB\-\-command\fR +Run an arbitrary command with the working directory, `.env`, overrides, and exports set +.TP +\fB\-\-completions\fR \fI\fR +Print shell completion script for +.br + +.br +[\fIpossible values: \fRbash, elvish, fish, nushell, powershell, zsh] +.TP +\fB\-\-dump\fR +Print justfile +.TP +\fB\-e\fR, \fB\-\-edit\fR +Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim` +.TP +\fB\-\-evaluate\fR +Evaluate and print all variables. If a variable name is given as an argument, only print that variable\*(Aqs value. +.TP +\fB\-\-fmt\fR +Format and overwrite justfile +.TP +\fB\-\-groups\fR +List recipe groups +.TP +\fB\-\-init\fR +Initialize new justfile in project root +.TP +\fB\-l\fR, \fB\-\-list\fR [\fI...\fR] +List available recipes in or root if omitted +.TP +\fB\-\-man\fR +Print man page +.TP +\fB\-s\fR, \fB\-\-show\fR \fI...\fR +Show recipe at +.TP +\fB\-\-summary\fR +List names of available recipes +.TP +\fB\-\-usage\fR \fI...\fR +Print recipe usage information +.TP +\fB\-\-variables\fR +List names of variables +.SH VERSION +v1.46.0 +.SH AUTHORS +Casey Rodarmor