From 173a6665b1c778c3356170bb1cbdb9ab8b8b9146 Mon Sep 17 00:00:00 2001 From: Timo Borer Date: Mon, 22 Dec 2025 14:43:44 +0100 Subject: [PATCH 1/5] feat: Add shell completions --- crane/Cargo.toml | 8 +++-- crane/src/cmd/commands.rs | 12 +++++++ crane/src/cmd/completion.rs | 9 ++++++ crane/src/cmd/list.rs | 12 +++++++ crane/src/cmd/mod.rs | 2 ++ crane/src/main.rs | 1 + crane/src/shell.rs | 64 +++++++++++++++++++++++++++++++++++++ 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 crane/src/cmd/completion.rs create mode 100644 crane/src/shell.rs diff --git a/crane/Cargo.toml b/crane/Cargo.toml index 47822ac..e2791a0 100644 --- a/crane/Cargo.toml +++ b/crane/Cargo.toml @@ -13,11 +13,15 @@ keywords = ["cli", "tool", "utility"] serde = { version = "1.0", features = ["derive"] } toml = "0.9.6" clap = { version = "4.5.47", features = ["derive"] } +clap-verbosity = "2.1.0" fuzzy-matcher = "0.3.7" anyhow = "1.0.99" -clap-verbosity = "2.1.0" env_logger = "0.11.8" log = "0.4.28" -crane_bricks = { path = "../crane_bricks/", version = "0.1.0"} +crane_bricks = { path = "../crane_bricks/", version = "0.1.0" } colog = "1.4.0" colored = "3.0.0" + +[profile.release] +codegen-units = 1 +lto = true diff --git a/crane/src/cmd/commands.rs b/crane/src/cmd/commands.rs index 26902b8..7a7eef5 100644 --- a/crane/src/cmd/commands.rs +++ b/crane/src/cmd/commands.rs @@ -3,6 +3,8 @@ use std::path::PathBuf; use clap::{Parser, Subcommand, ValueHint}; use clap_verbosity::{InfoLevel, Verbosity}; +use crate::shell::Shell; + #[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct CraneCli { @@ -17,6 +19,7 @@ pub struct CraneCli { pub enum CraneCommand { Add(Add), List(List), + Completion(Completion), } /// Add a brick to your directory @@ -35,9 +38,18 @@ pub struct Add { pub dry_run: bool, } +#[derive(Debug, Parser)] +pub struct Completion { + #[clap(required = true)] + pub shell: Shell, +} + /// List all available bricks #[derive(Debug, Parser, Clone)] pub struct List { #[arg(short, long, value_hint=ValueHint::DirPath, value_terminator=",")] pub brick_dirs: Option>, + + #[arg(long)] + pub no_format: bool, } diff --git a/crane/src/cmd/completion.rs b/crane/src/cmd/completion.rs new file mode 100644 index 0000000..90f2b52 --- /dev/null +++ b/crane/src/cmd/completion.rs @@ -0,0 +1,9 @@ +use crate::{ + cmd::{Completion, Run}, +}; + +impl Run for Completion { + fn run(&self) { + println!("{}", self.shell.to_string()); + } +} diff --git a/crane/src/cmd/list.rs b/crane/src/cmd/list.rs index c2a8704..da5026f 100644 --- a/crane/src/cmd/list.rs +++ b/crane/src/cmd/list.rs @@ -20,6 +20,18 @@ impl Run for List { &config.brick_dirs().to_vec() }; + if self.no_format { + for brick_dir in brick_dirs { + for brick in bricks_in_dir(brick_dir) { + println!("{}", brick.name()); + } + } + for alias in config.alias() { + println!("{}", alias.name()); + } + return; + } + let alias_mapped = map_aliases(config.alias()); for brick_dir in brick_dirs { diff --git a/crane/src/cmd/mod.rs b/crane/src/cmd/mod.rs index b87c666..dfb253f 100644 --- a/crane/src/cmd/mod.rs +++ b/crane/src/cmd/mod.rs @@ -1,5 +1,6 @@ mod add; mod commands; +mod completion; mod list; pub use crate::cmd::commands::*; @@ -13,6 +14,7 @@ impl Run for CraneCli { match &self.command { CraneCommand::Add(cmd) => cmd.run(), CraneCommand::List(cmd) => cmd.run(), + CraneCommand::Completion(cmd) => cmd.run(), } } } diff --git a/crane/src/main.rs b/crane/src/main.rs index 5666ab9..653e742 100644 --- a/crane/src/main.rs +++ b/crane/src/main.rs @@ -5,6 +5,7 @@ use crate::cmd::{CraneCli, Run}; mod cmd; mod config; mod logging; +mod shell; fn main() { let cli = CraneCli::parse(); diff --git a/crane/src/shell.rs b/crane/src/shell.rs new file mode 100644 index 0000000..c9c31cb --- /dev/null +++ b/crane/src/shell.rs @@ -0,0 +1,64 @@ +use clap::ValueEnum; + +#[derive(ValueEnum, Debug, Clone, Copy)] +pub enum Shell { + BASH, + ZSH, + FISH, +} + +impl ToString for Shell { + fn to_string(&self) -> String { + match self { + Shell::BASH => r#" +# START generated crane shell config +_crane() { + local cur + cur="${COMP_WORDS[COMP_CWORD]}" + local subcommands="list add completions" + if [[ $COMP_CWORD -eq 1 ]]; then + COMPREPLY=( $(compgen -W "$subcommands" -- "$cur") ) + return + fi + if [[ ${COMP_WORDS[1]} == add ]]; then + local items + items="$(crane list --no-format 2>/dev/null)" + COMPREPLY=( $(compgen -W "$items" -- "$cur") ) + return + fi +} +complete -F _crane crane +# END generated crane shell config"#, + Shell::ZSH => r#" +# START generated crane shell config +_crane() { + local -a subcmds add_args + subcmds=( + 'add:Add bricks' + 'list:List bricks' + 'completions:Generate shell completions' + ) + if (( CURRENT == 2 )); then + _describe 'subcommand' subcmds + return + fi + case $words[2] in + add) + _arguments "*:argument:($(crane list --no-format))" + ;; + esac +} +compdef _crane crane +# END generated crane shell config"#, + Shell::FISH => r#" +# START generated crane shell config +complete -c crane -f -n '__fish_use_subcommand' -a list -d 'List bricks' +complete -c crane -f -n '__fish_use_subcommand' -a add -d 'Add bricks' +complete -c crane -f -n '__fish_use_subcommand' -a completions -d 'Generate shell completions' +complete -c crane -f -n '__fish_seen_subcommand_from add' \ + -a '(crane list --no-format 2>/dev/null)' +# END generated crane shell config"#, + } + .to_string() + } +} From c04bfa34e860c6c2525064b54547442184a0f8e9 Mon Sep 17 00:00:00 2001 From: Timo Borer Date: Mon, 22 Dec 2025 15:11:48 +0100 Subject: [PATCH 2/5] docs: Improve readme and book --- README.md | 114 +++++++++++++++++++++++++++++++++++++++----- book/src/SUMMARY.md | 2 + book/src/faq.md | 3 ++ book/src/setup.md | 32 +++++++++++++ 4 files changed, 139 insertions(+), 12 deletions(-) create mode 100644 book/src/faq.md create mode 100644 book/src/setup.md diff --git a/README.md b/README.md index a5da0dc..845aef3 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,108 @@ -# crane 🏗️ +
+

crane 🏗️

-Easily add bricks (files or snippets) to your projects. +Create, use and share easily reusable bootstrap packages called bricks. +
+
+ +⭐ Consider starring this repo – your support motivates me a lot! ⭐ + +
+ + Crates.io Version + + + Crates.io Total Downloads + + + GitHub Repo stars + +
+
+Setup + ~  +FAQ + ~  +Documentation +
-🧱 A brick is an instruction. It can be a file that gets added, a command that + + +
+ +Crane is a CLI tool that allows you to create *bricks* that you can later add to any project. + +A brick is an instruction. It can be a file that gets added, a command that executes or lines getting replaced in a target file. -> 🚧 crane is currently being worked on :D -> Some features that are already documented don't work yet -> and everything could change until a stable release! +## Examples + +### License brick + +Instead of having to look up and copy your desired license from the web, you can create a brick out of it and then run `crane add some-license`. + +### Language specific bricks + +You can create multiple bricks and combine them behind an alias. + +This way, you can easily bootstrap new projects! + +```shell +$ cargo new my_project && cd my_project +# ... +$ crane add rust +→ Executing 4 bricks + • mit + • serde + • rustfmt + • rustauthor +# ... +``` + +## Getting Started + +Install the CLI using cargo (more options coming soon!) + +```shell +cargo install crane +``` + +and set up shell completions (not required): + +
+ZSH + +```shell +# ~/.zshrc +eval "$(crane completion zsh)" +``` + +
+ +
+Bash + +```shell +# ~/.bashrc +eval "$(crane completion bash)" +``` + +
+ +
+Fish + +```shell +# ~/.config/fish/config.fish +crane completion fish | source +``` + +
+ +## Issues & Contributions + +Feel free to open an issue or a PR. Help is always appreciated! -## ToDo +--- -- [ ] Regex support -- [ ] Path support -- [ ] Improve readme -- [ ] Variables support - - [ ] Input variables (ask for variable or command or something) +made with <3 by [timothebot](https://github.com/timothebot) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 78f0619..63b6863 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -1,6 +1,8 @@ # Summary - [Introduction](./intro.md) +- [Set Up](./setup.md) +- [Frequently Asked Questions](./faq.md) # User Guide diff --git a/book/src/faq.md b/book/src/faq.md new file mode 100644 index 0000000..e5b802b --- /dev/null +++ b/book/src/faq.md @@ -0,0 +1,3 @@ +# Frequently Asked Questions + +Feel free to open an issue with any questions. Common questions will then be added here! diff --git a/book/src/setup.md b/book/src/setup.md new file mode 100644 index 0000000..be31eb5 --- /dev/null +++ b/book/src/setup.md @@ -0,0 +1,32 @@ +# Setup + +Install the CLI using cargo (more options coming soon!) + +```shell +cargo install crane +``` + +## Shell Completions (optional) + +Set up shell completions: + +### ZSH + +```shell +# ~/.zshrc +eval "$(crane completion zsh)" +``` + +### Bash + +```shell +# ~/.bashrc +eval "$(crane completion bash)" +``` + +### Fish + +```shell +# ~/.config/fish/config.fish +crane completion fish | source +``` From 3fc59fc0f213a77ba37ce7499103c125d1a3bd48 Mon Sep 17 00:00:00 2001 From: Timo Borer Date: Mon, 22 Dec 2025 15:16:01 +0100 Subject: [PATCH 3/5] refactor: Fix clippy issues --- crane/src/cmd/completion.rs | 6 ++---- crane/src/shell.rs | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/crane/src/cmd/completion.rs b/crane/src/cmd/completion.rs index 90f2b52..1d668ed 100644 --- a/crane/src/cmd/completion.rs +++ b/crane/src/cmd/completion.rs @@ -1,9 +1,7 @@ -use crate::{ - cmd::{Completion, Run}, -}; +use crate::cmd::{Completion, Run}; impl Run for Completion { fn run(&self) { - println!("{}", self.shell.to_string()); + println!("{}", self.shell); } } diff --git a/crane/src/shell.rs b/crane/src/shell.rs index c9c31cb..4418545 100644 --- a/crane/src/shell.rs +++ b/crane/src/shell.rs @@ -1,16 +1,22 @@ +use std::fmt::Display; + use clap::ValueEnum; #[derive(ValueEnum, Debug, Clone, Copy)] pub enum Shell { - BASH, - ZSH, - FISH, + Bash, + Zsh, + Fish, } -impl ToString for Shell { - fn to_string(&self) -> String { - match self { - Shell::BASH => r#" +impl Display for Shell { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!( + f, + "{}", + match self { + Shell::Bash => + r#" # START generated crane shell config _crane() { local cur @@ -29,7 +35,8 @@ _crane() { } complete -F _crane crane # END generated crane shell config"#, - Shell::ZSH => r#" + Shell::Zsh => + r#" # START generated crane shell config _crane() { local -a subcmds add_args @@ -50,7 +57,8 @@ _crane() { } compdef _crane crane # END generated crane shell config"#, - Shell::FISH => r#" + Shell::Fish => + r#" # START generated crane shell config complete -c crane -f -n '__fish_use_subcommand' -a list -d 'List bricks' complete -c crane -f -n '__fish_use_subcommand' -a add -d 'Add bricks' @@ -58,7 +66,7 @@ complete -c crane -f -n '__fish_use_subcommand' -a completions -d 'Generate shel complete -c crane -f -n '__fish_seen_subcommand_from add' \ -a '(crane list --no-format 2>/dev/null)' # END generated crane shell config"#, - } - .to_string() + } + ) } } From 55ab48c202e7a6f262ec337a2197073854c27f06 Mon Sep 17 00:00:00 2001 From: Timo Borer Date: Mon, 22 Dec 2025 15:18:39 +0100 Subject: [PATCH 4/5] chore: Bump version numbers --- Cargo.lock | 2 +- crane/Cargo.toml | 2 +- crane_bricks/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19c2e0e..87c3e86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,7 +158,7 @@ dependencies = [ [[package]] name = "crane" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "clap", diff --git a/crane/Cargo.toml b/crane/Cargo.toml index e2791a0..fa25c25 100644 --- a/crane/Cargo.toml +++ b/crane/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crane" description = "Easily add bricks (files or snippets) to your projects!" -version = "0.2.0" +version = "0.3.0" edition = "2024" license = "MIT" readme = "../README.md" diff --git a/crane_bricks/Cargo.toml b/crane_bricks/Cargo.toml index b374a85..417ae6a 100644 --- a/crane_bricks/Cargo.toml +++ b/crane_bricks/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crane_bricks" description = "Execute bricks" -version = "0.1.0" +version = "0.2.0" edition = "2024" license = "MIT" repository = "https://github.com/timothebot/crane" From 9091aef1a17a2058087b8e50db6c18160e4c250e Mon Sep 17 00:00:00 2001 From: Timo Borer Date: Mon, 22 Dec 2025 15:19:25 +0100 Subject: [PATCH 5/5] fix: Use correct crane_bricks version --- Cargo.lock | 2 +- crane/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87c3e86..ec1d454 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ dependencies = [ [[package]] name = "crane_bricks" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "env_logger", diff --git a/crane/Cargo.toml b/crane/Cargo.toml index fa25c25..77c105c 100644 --- a/crane/Cargo.toml +++ b/crane/Cargo.toml @@ -18,7 +18,7 @@ fuzzy-matcher = "0.3.7" anyhow = "1.0.99" env_logger = "0.11.8" log = "0.4.28" -crane_bricks = { path = "../crane_bricks/", version = "0.1.0" } +crane_bricks = { path = "../crane_bricks/", version = "0.2.0" } colog = "1.4.0" colored = "3.0.0"