diff --git a/.gitignore b/.gitignore index 568c6a5..7988b1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +*.json /.nickel /target diff --git a/flake.nix b/flake.nix index 8be8736..139be3a 100644 --- a/flake.nix +++ b/flake.nix @@ -28,6 +28,7 @@ # For Oclis itself cargo graphviz # For generating the processing-pipeline infographic + nickel # For testing the Nickel code pre-commit rustc rustfmt diff --git a/makefile b/makefile index 6abc9b9..52c427c 100644 --- a/makefile +++ b/makefile @@ -12,11 +12,29 @@ install: cargo install --path . +%.json: %.ncl + nickel export \ + --color=always \ + oclis-contract.ncl \ + --output $@ \ + $< + + +spec-files := $(wildcard src/*.ncl examples/*.ncl) +spec-files-json := $(spec-files:.ncl=.json) + .PHONY: test -test: +test: $(spec-files-json) cargo clippy cargo test processing-pipeline.svg: processing-pipeline.dot dot -T svg -o $@ $< + + +.PHONY: clean +clean: + rm -f $(spec-files-json) + rm -f processing-pipeline.svg + rm -rf .nickel diff --git a/oclis-contract.ncl b/oclis-contract.ncl index 0250851..301a306 100644 --- a/oclis-contract.ncl +++ b/oclis-contract.ncl @@ -120,6 +120,7 @@ let Command = { | Array Option, arguments | doc "The list of arguments" + | optional | Array Argument | NotRequiredIfList, funcName diff --git a/oclis.ncl b/oclis.ncl index 922cd6a..47aa9af 100644 --- a/oclis.ncl +++ b/oclis.ncl @@ -1,8 +1,19 @@ { - name = "oclis", - version = "0.1.0.0", + name = "{{name}}", description = m%" - Generate a CLI parser and executor - from a given `oclis.ncl` specification file. + {{name}} is an awesome CLI tool "%, + version = "0.0.0", + options = [ + { + name = "debug", + description = "Print debug output", + }, + ], + commands = [ + { + name = "hello", + description = "Print \"hello\"", + }, + ], } diff --git a/readme.md b/readme.md index 2cf0c23..682280f 100644 --- a/readme.md +++ b/readme.md @@ -13,22 +13,19 @@ But fear not, Oclis is here to help you out! ## Usage -1. Install Oclis with - `cargo install --git https://github.com/Airsequel/Oclis` -1. Create a `oclis.ncl` specifcation file in the root of your project. \ - (Check out the [examples](./examples) directory for inspiration.) +1. `cargo install oclis` +1. `oclis init` - Creates an `oclis.ncl` specifcation file. +1. Adapt the specification file to your liking. \ + (Check out the [examples directory](./examples) for inspiration.) 1. Run `oclis build` to generate the CLI parsing code \ - (Automatically detects main repo language, - but only supports PureScript at the moment.) + (It automatically detects the main repo language, + but only PureScript is supported at the moment.) 1. Define the handler functions for your commands. \ (Check out the [main function of Transity][tr-main] for an example.) -1. Build and use your project as usual 🎉 +1. Commit the generated code to the repository. [tr-main]: https://github.com/feramhq/Transity/blob/master/src/Main.purs#L332 -> [!NOTE] -> The generated code must be committed to the repository. - ## How It Works diff --git a/src/main.rs b/src/main.rs index f6c45fd..721d601 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,6 +50,8 @@ enum Commands { // #[arg(short, long, default_value_t = Language::Json)] // language: Language, }, + /// Creates a bare bones `oclis.ncl` file + Init, } fn convert_spec_to_json( @@ -270,5 +272,19 @@ fn main() -> Result<(), String> { None => Err(String::from("No spec file provided")), } } + + Commands::Init => { + let cwd_path = std::env::current_dir().unwrap(); + let cwd = cwd_path.file_name().unwrap(); + let cwd_str = cwd.to_str().unwrap(); + + if fs::metadata("oclis.ncl").is_ok() { + Err(String::from("Spec file 'oclis.ncl' already exists")) + } else { + const TEMPLATE: &str = include_str!("template.ncl"); + let spec = TEMPLATE.replace("{{name}}", cwd_str); + fs::write("oclis.ncl", spec).map_err(|err| err.to_string()) + } + } } } diff --git a/src/template.ncl b/src/template.ncl new file mode 100644 index 0000000..47aa9af --- /dev/null +++ b/src/template.ncl @@ -0,0 +1,19 @@ +{ + name = "{{name}}", + description = m%" + {{name}} is an awesome CLI tool + "%, + version = "0.0.0", + options = [ + { + name = "debug", + description = "Print debug output", + }, + ], + commands = [ + { + name = "hello", + description = "Print \"hello\"", + }, + ], +}