├── docs ├── api │ ├── .lock │ ├── crates.js │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── FiraSans-Medium.woff2 │ ├── noscript.css │ ├── FiraSans-Regular.woff2 │ ├── NanumBarunGothic.ttf.woff2 │ ├── SourceCodePro-It.ttf.woff2 │ ├── SourceSerif4-It.ttf.woff2 │ ├── SourceSerif4-Bold.ttf.woff2 │ ├── SourceCodePro-Regular.ttf.woff2 │ ├── SourceSerif4-Regular.ttf.woff2 │ ├── SourceCodePro-Semibold.ttf.woff2 │ ├── source-files.js │ ├── toggle-minus.svg │ ├── toggle-plus.svg │ ├── down-arrow.svg │ ├── implementors │ │ ├── std │ │ │ └── error │ │ │ │ └── trait.Error.js │ │ └── core │ │ │ ├── fmt │ │ │ ├── trait.Display.js │ │ │ └── trait.Debug.js │ │ │ ├── marker │ │ │ ├── trait.Copy.js │ │ │ ├── trait.Freeze.js │ │ │ ├── trait.Send.js │ │ │ ├── trait.Sync.js │ │ │ ├── trait.Unpin.js │ │ │ └── trait.StructuralPartialEq.js │ │ │ ├── default │ │ │ └── trait.Default.js │ │ │ ├── clone │ │ │ └── trait.Clone.js │ │ │ ├── panic │ │ │ └── unwind_safe │ │ │ │ ├── trait.UnwindSafe.js │ │ │ │ └── trait.RefUnwindSafe.js │ │ │ └── cmp │ │ │ └── trait.PartialEq.js │ ├── clipboard.svg │ ├── cliparser │ │ ├── types │ │ │ ├── sidebar-items.js │ │ │ └── index.html │ │ ├── sidebar-items.js │ │ ├── all.html │ │ ├── fn.help.html │ │ ├── fn.version.html │ │ ├── fn.parse_process.html │ │ ├── fn.parse_process_any.html │ │ └── fn.parse_any.html │ ├── LICENSE-MIT.txt │ ├── settings.css │ ├── normalize.css │ ├── COPYRIGHT.txt │ ├── storage.js │ ├── rust-logo.svg │ ├── wheel.svg │ ├── settings.html │ ├── favicon.svg │ ├── source-script.js │ ├── FiraSans-LICENSE.txt │ ├── SourceSerif4-LICENSE.md │ ├── SourceCodePro-LICENSE.txt │ ├── NanumBarunGothic-LICENSE.txt │ ├── settings.js │ ├── light.css │ └── dark.css └── index.html ├── .gitattributes ├── .rusty-hook.toml ├── .gitignore ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ └── ci.yml └── CONTRIBUTING.md ├── .editorconfig ├── CHANGELOG.md ├── Makefile.toml ├── Cargo.toml ├── tests ├── parse_any_test.rs └── parse_test.rs ├── benches └── bench_parse.rs ├── src ├── types_test.rs ├── types.rs ├── help.rs └── lib_test.rs ├── examples └── example.rs └── README.md /docs/api/.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api/crates.js: -------------------------------------------------------------------------------- 1 | window.ALL_CRATES = ["cliparser"]; -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.ico binary 3 | *.woff binary 4 | -------------------------------------------------------------------------------- /.rusty-hook.toml: -------------------------------------------------------------------------------- 1 | [hooks] 2 | pre-push = "cargo make ci-flow" 3 | -------------------------------------------------------------------------------- /docs/api/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/favicon-16x16.png -------------------------------------------------------------------------------- /docs/api/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/favicon-32x32.png -------------------------------------------------------------------------------- /docs/api/FiraSans-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/FiraSans-Medium.woff2 -------------------------------------------------------------------------------- /docs/api/noscript.css: -------------------------------------------------------------------------------- 1 | #main-content .attributes{margin-left:0 !important;}#copy-path{display:none;}.sub{display:none;} -------------------------------------------------------------------------------- /docs/api/FiraSans-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/FiraSans-Regular.woff2 -------------------------------------------------------------------------------- /docs/api/NanumBarunGothic.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/NanumBarunGothic.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceCodePro-It.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceCodePro-It.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceSerif4-It.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceSerif4-It.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceSerif4-Bold.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceSerif4-Bold.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceCodePro-Regular.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceCodePro-Regular.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceSerif4-Regular.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceSerif4-Regular.ttf.woff2 -------------------------------------------------------------------------------- /docs/api/SourceCodePro-Semibold.ttf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagiegurari/cliparser/HEAD/docs/api/SourceCodePro-Semibold.ttf.woff2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .c9 3 | /target 4 | temp/ 5 | **/*.rs.bk 6 | Cargo.lock 7 | **/*.log 8 | dump.rdb 9 | /rs*.sh 10 | /docs/_site 11 | /core 12 | -------------------------------------------------------------------------------- /docs/api/source-files.js: -------------------------------------------------------------------------------- 1 | var sourcesIndex = {}; 2 | sourcesIndex["cliparser"] = {"name":"","files":["help.rs","lib.rs","parser.rs","types.rs"]}; 3 | createSourceSidebar(); 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: '03:00' 8 | open-pull-requests-limit: 99 9 | -------------------------------------------------------------------------------- /docs/api/toggle-minus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api/toggle-plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [*.json] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## CHANGELOG 2 | 3 | ### v0.1.2 (2022-07-21) 4 | 5 | * Support windows paths for command scanning 6 | 7 | ### v0.1.1 (2022-07-21) 8 | 9 | * Ignore extensions while scanning for commands 10 | 11 | ### v0.1.0 (2022-07-21) 12 | 13 | * Initial release 14 | -------------------------------------------------------------------------------- /Makefile.toml: -------------------------------------------------------------------------------- 1 | 2 | [config] 3 | additional_profiles = [ 4 | "all-default-tasks", 5 | "multi-phase-tests", 6 | "docs-all-modification-tasks", 7 | "ci-coverage-tasks", 8 | "ci-all-build-tasks", 9 | "ci-static-code-analysis-tasks", 10 | "publish-pre-cleanup", 11 | ] 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: sagiegurari 7 | 8 | --- 9 | 10 | ### Feature Description 11 | 12 | 13 | ### Describe The Solution You'd Like 14 | 15 | 16 | ### Code Sample 17 | 18 | ```rust 19 | /// paste code here 20 | ``` 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: sagiegurari 7 | 8 | --- 9 | 10 | ### Describe The Bug 11 | 12 | 13 | ### To Reproduce 14 | 15 | 16 | ### Error Stack 17 | 18 | ```console 19 | The error stack trace 20 | ``` 21 | 22 | ### Code Sample 23 | 24 | ```rust 25 | /// paste code here 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/api/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api/implementors/std/error/trait.Error.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Error for ParserError","synthetic":false,"types":["cliparser::types::ParserError"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/clipboard.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/api/implementors/core/fmt/trait.Display.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Display for ParserError","synthetic":false,"types":["cliparser::types::ParserError"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/cliparser/types/sidebar-items.js: -------------------------------------------------------------------------------- 1 | initSidebarItems({"enum":[["ArgumentHelp","The argument help text"],["ArgumentOccurrence","The argument occurrence type (see values for more info)"],["ArgumentValueType","The argument value type (see values for more info)"],["Command","The command (not params) string/s"],["ParserError","Holds the error information"]],"struct":[["Argument","Holds the command line argument spec"],["CliParsed","Holds the command line parse result"],["CliSpec","Holds the command line spec (command/parameters/…)"],["CliSpecMetaInfo","Holds the command line spec meta information used to generate version and help messages"],["PositionalArgument","Holds the positional argument spec"]]}); -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | env: 4 | CLICOLOR_FORCE: 1 5 | jobs: 6 | ci: 7 | name: CI 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | rust: [stable, beta, nightly] 13 | os: [ubuntu-latest, windows-latest, macOS-latest] 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | - name: Install rust 18 | uses: dtolnay/rust-toolchain@master 19 | with: 20 | toolchain: ${{ matrix.rust }} 21 | - name: Install cargo-make 22 | run: cargo install --debug cargo-make 23 | - name: Run CI 24 | env: 25 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 26 | run: cargo make ci-flow 27 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cliparser" 3 | version = "0.1.2" 4 | authors = ["Sagie Gur-Ari "] 5 | description = "Simple command line parser." 6 | license = "Apache-2.0" 7 | edition = "2021" 8 | documentation = "https://sagiegurari.github.io/cliparser/api/cliparser/index.html" 9 | homepage = "http://github.com/sagiegurari/cliparser" 10 | repository = "https://github.com/sagiegurari/cliparser.git" 11 | readme = "README.md" 12 | keywords = ["os", "cli", "command", "parser", "params"] 13 | categories = ["command-line-interface"] 14 | include = [ 15 | "/benches/*", 16 | "/docs/*", 17 | "/examples/*", 18 | "/src/*", 19 | "/tests/*", 20 | "/Cargo.toml", 21 | "/LICENSE", 22 | "/README.md", 23 | "/Makefile.toml", 24 | ] 25 | 26 | [dev-dependencies] 27 | doc-comment = "^0.3" 28 | -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.Copy.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Copy for ArgumentOccurrence","synthetic":false,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Copy for ArgumentValueType","synthetic":false,"types":["cliparser::types::ArgumentValueType"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | 4 | ## Issues 5 | 6 | Found a bug? Got a question? Want some enhancement?
7 | First place to go is the repository issues section, and I'll try to help as much as possible. 8 | 9 | ## Pull Requests 10 | 11 | Fixed a bug or just want to provided additional functionality?
12 | Simply fork this repository, implement your changes and create a pull request.
13 | Few guidelines regarding pull requests: 14 | 15 | * This repository is integrated with github actions for continuous integration.
16 | 17 | Your pull request build must pass (the build will run automatically).
18 | You can run the following command locally to ensure the build will pass: 19 | 20 | ````sh 21 | cargo make ci-flow 22 | ```` 23 | 24 | * There are many automatic unit tests as part of the library which provide full coverage of the functionality.
Any fix/enhancement must come with a set of tests to ensure it's working well. 25 | -------------------------------------------------------------------------------- /docs/api/cliparser/sidebar-items.js: -------------------------------------------------------------------------------- 1 | initSidebarItems({"fn":[["help","Generates and returns the spec help text"],["parse","Parsers the given command line based on the given spec and returns the result. In case of error (such as invalid input), an error will be returned. In case the command line does not match the spec, Ok(None) will be returned."],["parse_any","Parsers the given command line based on the given specs and returns the result. In case of invalid input or none of the provided specs do not match the command line, an error will be returned."],["parse_process","Parsers the given command line based on the given spec and returns the result. In case of error (such as invalid input), an error will be returned. In case the command line does not match the spec, Ok(None) will be returned."],["parse_process_any","Parsers the current process command line based on the given specs and returns the result. In case of invalid input or none of the provided specs do not match the command line, an error will be returned."],["version","Generates and returns the spec version text"]],"mod":[["types","types"]]}); -------------------------------------------------------------------------------- /docs/api/LICENSE-MIT.txt: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /docs/api/implementors/core/default/trait.Default.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Default for CliSpecMetaInfo","synthetic":false,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Default for CliSpec","synthetic":false,"types":["cliparser::types::CliSpec"]},{"text":"impl Default for CliParsed","synthetic":false,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/settings.css: -------------------------------------------------------------------------------- 1 | .setting-line{margin:0.6em 0 0.6em 0.3em;position:relative;}.setting-line .choices{display:flex;flex-wrap:wrap;}.setting-line .radio-line input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:1px solid;outline:none;-webkit-appearance:none;cursor:pointer;border-radius:50%;}.setting-line .radio-line input+span{padding-bottom:1px;}.radio-line .setting-name{width:100%;}.radio-line .choice{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:flex;align-items:center;cursor:pointer;}.radio-line .choice+.choice{margin-left:0.5em;}.toggle{position:relative;display:inline-block;width:100%;height:27px;margin-right:20px;display:flex;align-items:center;cursor:pointer;}.toggle input{opacity:0;position:absolute;}.slider{position:relative;width:45px;display:block;height:28px;margin-right:20px;cursor:pointer;background-color:#ccc;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;transition:.3s;}input:checked+.slider:before{transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;}div#settings{position:absolute;right:0;z-index:1;display:block;margin-top:7px;border-radius:3px;border:1px solid;}#settings .setting-line{margin:1.2em 0.6em;}div#settings::before{content:'';position:absolute;right:11px;border:solid;border-width:1px 1px 0 0;display:inline-block;padding:4px;transform:rotate(-45deg);top:-5px;} -------------------------------------------------------------------------------- /tests/parse_any_test.rs: -------------------------------------------------------------------------------- 1 | use cliparser::parse_any; 2 | use cliparser::types::{Argument, ArgumentOccurrence, ArgumentValueType, CliSpec, Command}; 3 | use std::collections::HashSet; 4 | 5 | #[test] 6 | fn parse_any_test() { 7 | let mut cli_spec1 = CliSpec::new(); 8 | cli_spec1 9 | .command 10 | .push(Command::Command("test1".to_string())); 11 | cli_spec1.arguments.push(Argument { 12 | name: "testarg1".to_string(), 13 | key: vec!["--test".to_string()], 14 | argument_occurrence: ArgumentOccurrence::Single, 15 | value_type: ArgumentValueType::None, 16 | default_value: Some("test_default".to_string()), 17 | help: None, 18 | }); 19 | 20 | let mut cli_spec2 = CliSpec::new(); 21 | cli_spec2.command.push(Command::Command("test".to_string())); 22 | cli_spec2.arguments.push(Argument { 23 | name: "testarg2".to_string(), 24 | key: vec!["--test".to_string()], 25 | argument_occurrence: ArgumentOccurrence::Single, 26 | value_type: ArgumentValueType::None, 27 | default_value: None, 28 | help: None, 29 | }); 30 | 31 | let empty_cli_spec = CliSpec::new(); 32 | 33 | let result = parse_any( 34 | &vec!["test", "--test"], 35 | vec![&cli_spec1, &empty_cli_spec, &cli_spec2], 36 | ); 37 | 38 | assert!(result.is_ok()); 39 | let (index, cli_parsed) = result.unwrap(); 40 | assert_eq!(index, 2); 41 | 42 | let mut argument_names = HashSet::new(); 43 | argument_names.insert("testarg2".to_string()); 44 | assert_eq!(cli_parsed.arguments, argument_names); 45 | assert!(cli_parsed.argument_values.is_empty()); 46 | } 47 | -------------------------------------------------------------------------------- /docs/api/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} -------------------------------------------------------------------------------- /docs/api/COPYRIGHT.txt: -------------------------------------------------------------------------------- 1 | These documentation pages include resources by third parties. This copyright 2 | file applies only to those resources. The following third party resources are 3 | included, and carry their own copyright notices and license terms: 4 | 5 | * Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): 6 | 7 | Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ 8 | with Reserved Font Name Fira Sans. 9 | 10 | Copyright (c) 2014, Telefonica S.A. 11 | 12 | Licensed under the SIL Open Font License, Version 1.1. 13 | See FiraSans-LICENSE.txt. 14 | 15 | * rustdoc.css, main.js, and playpen.js: 16 | 17 | Copyright 2015 The Rust Developers. 18 | Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or 19 | the MIT license (LICENSE-MIT.txt) at your option. 20 | 21 | * normalize.css: 22 | 23 | Copyright (c) Nicolas Gallagher and Jonathan Neal. 24 | Licensed under the MIT license (see LICENSE-MIT.txt). 25 | 26 | * Source Code Pro (SourceCodePro-Regular.ttf.woff2, 27 | SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): 28 | 29 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), 30 | with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark 31 | of Adobe Systems Incorporated in the United States and/or other countries. 32 | 33 | Licensed under the SIL Open Font License, Version 1.1. 34 | See SourceCodePro-LICENSE.txt. 35 | 36 | * Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, 37 | SourceSerif4-It.ttf.woff2): 38 | 39 | Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 40 | 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United 41 | States and/or other countries. 42 | 43 | Licensed under the SIL Open Font License, Version 1.1. 44 | See SourceSerif4-LICENSE.md. 45 | 46 | This copyright file is intended to be distributed with rustdoc output. 47 | -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.Freeze.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Freeze for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl Freeze for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl Freeze for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Freeze for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Freeze for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Freeze for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl Freeze for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Freeze for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Freeze for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl Freeze for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/implementors/core/clone/trait.Clone.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Clone for Command","synthetic":false,"types":["cliparser::types::Command"]},{"text":"impl Clone for ArgumentOccurrence","synthetic":false,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Clone for ArgumentValueType","synthetic":false,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Clone for ArgumentHelp","synthetic":false,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Clone for Argument","synthetic":false,"types":["cliparser::types::Argument"]},{"text":"impl Clone for PositionalArgument","synthetic":false,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Clone for CliSpecMetaInfo","synthetic":false,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Clone for CliSpec","synthetic":false,"types":["cliparser::types::CliSpec"]},{"text":"impl Clone for CliParsed","synthetic":false,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/storage.js: -------------------------------------------------------------------------------- 1 | "use strict";const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");window.mainTheme=document.getElementById("mainThemeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}const dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current!==null){return current}if(settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return null}const localStoredTheme=getSettingValue("theme");const savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){if(reversed){const length=arr.length;for(let i=length-1;i>=0;--i){if(func(arr[i])){return true}}}else{for(const elem of arr){if(func(elem)){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){const newHref=mainStyleElem.href.replace(/\/rustdoc([^/]*)\.css/,"/"+newTheme+"$1"+".css");if(saveTheme){updateLocalStorage("theme",newTheme)}if(styleElem.href===newHref){return}let found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),el=>{savedHref.push(el.href)})}onEach(savedHref,el=>{if(el===newHref){found=true;return true}});if(found){styleElem.href=newHref}}function useSystemTheme(value){if(value===undefined){value=true}updateLocalStorage("use-system-theme",value);const toggle=document.getElementById("use-system-theme");if(toggle&&toggle instanceof HTMLInputElement){toggle.checked=value}}const updateSystemTheme=(function(){if(!window.matchMedia){return()=>{const cssTheme=getComputedStyle(document.documentElement).getPropertyValue("content");switchTheme(window.currentTheme,window.mainTheme,JSON.parse(cssTheme)||"light",true)}}const mql=window.matchMedia("(prefers-color-scheme: dark)");function handlePreferenceChange(mql){const use=theme=>{switchTheme(window.currentTheme,window.mainTheme,theme,true)};if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";if(mql.matches){use(darkTheme)}else{use(lightTheme)}}else{use(getSettingValue("theme"))}}mql.addListener(handlePreferenceChange);return()=>{handlePreferenceChange(mql)}})();function switchToSavedTheme(){switchTheme(window.currentTheme,window.mainTheme,getSettingValue("theme")||"light",false)}if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchToSavedTheme()}window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(switchToSavedTheme,0)}}) -------------------------------------------------------------------------------- /docs/api/rust-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 61 | 62 | -------------------------------------------------------------------------------- /docs/api/implementors/core/fmt/trait.Debug.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Debug for ParserError","synthetic":false,"types":["cliparser::types::ParserError"]},{"text":"impl Debug for Command","synthetic":false,"types":["cliparser::types::Command"]},{"text":"impl Debug for ArgumentOccurrence","synthetic":false,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Debug for ArgumentValueType","synthetic":false,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Debug for ArgumentHelp","synthetic":false,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Debug for Argument","synthetic":false,"types":["cliparser::types::Argument"]},{"text":"impl Debug for PositionalArgument","synthetic":false,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Debug for CliSpecMetaInfo","synthetic":false,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Debug for CliSpec","synthetic":false,"types":["cliparser::types::CliSpec"]},{"text":"impl Debug for CliParsed","synthetic":false,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.Send.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Send for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl Send for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl Send for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Send for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Send for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Send for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl Send for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Send for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Send for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl Send for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.Sync.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Sync for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl Sync for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl Sync for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Sync for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Sync for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Sync for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl Sync for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Sync for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Sync for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl Sync for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.Unpin.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl Unpin for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl Unpin for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl Unpin for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl Unpin for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl Unpin for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl Unpin for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl Unpin for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl Unpin for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl Unpin for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl Unpin for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/wheel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api/implementors/core/marker/trait.StructuralPartialEq.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl StructuralPartialEq for Command","synthetic":false,"types":["cliparser::types::Command"]},{"text":"impl StructuralPartialEq for ArgumentOccurrence","synthetic":false,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl StructuralPartialEq for ArgumentValueType","synthetic":false,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl StructuralPartialEq for ArgumentHelp","synthetic":false,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl StructuralPartialEq for Argument","synthetic":false,"types":["cliparser::types::Argument"]},{"text":"impl StructuralPartialEq for PositionalArgument","synthetic":false,"types":["cliparser::types::PositionalArgument"]},{"text":"impl StructuralPartialEq for CliSpecMetaInfo","synthetic":false,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl StructuralPartialEq for CliSpec","synthetic":false,"types":["cliparser::types::CliSpec"]},{"text":"impl StructuralPartialEq for CliParsed","synthetic":false,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/settings.html: -------------------------------------------------------------------------------- 1 | Rustdoc settings 2 | 5 |

Rustdoc settings

Back
9 | -------------------------------------------------------------------------------- /benches/bench_parse.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | use cliparser::parse; 5 | use cliparser::types::{ 6 | Argument, ArgumentHelp, ArgumentOccurrence, ArgumentValueType, CliSpec, CliSpecMetaInfo, 7 | PositionalArgument, 8 | }; 9 | use test::Bencher; 10 | 11 | #[bench] 12 | fn parse_test(bencher: &mut Bencher) { 13 | let mut cli_spec = CliSpec::new(); 14 | 15 | cli_spec = cli_spec 16 | .set_meta_info(Some(CliSpecMetaInfo { 17 | author: Some("Sagie Gur-Ari".to_string()), 18 | version: Some("1.2.3-beta".to_string()), 19 | description: Some("Amazing example".to_string()), 20 | project: Some("example".to_string()), 21 | help_post_text: Some( 22 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 23 | ), 24 | })) 25 | .add_command("makers") 26 | .add_subcommand(vec!["cargo", "make"]) 27 | .set_positional_argument(Some(PositionalArgument { 28 | name: "args".to_string(), 29 | help: Some(ArgumentHelp::TextAndParam( 30 | "The command line arguments".to_string(), 31 | "ARGS".to_string(), 32 | )), 33 | })) 34 | .add_argument(Argument { 35 | name: "flag".to_string(), 36 | key: vec!["--flag".to_string(), "-f".to_string()], 37 | argument_occurrence: ArgumentOccurrence::Single, 38 | value_type: ArgumentValueType::None, 39 | default_value: None, 40 | help: Some(ArgumentHelp::Text( 41 | "A flag without value example".to_string(), 42 | )), 43 | }) 44 | .add_argument(Argument { 45 | name: "single".to_string(), 46 | key: vec!["--s1".to_string(), "-s".to_string()], 47 | argument_occurrence: ArgumentOccurrence::Single, 48 | value_type: ArgumentValueType::Single, 49 | default_value: None, 50 | help: Some(ArgumentHelp::Text( 51 | "A parameter with single value example".to_string(), 52 | )), 53 | }) 54 | .add_argument(Argument { 55 | name: "mo".to_string(), 56 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 57 | argument_occurrence: ArgumentOccurrence::Multiple, 58 | value_type: ArgumentValueType::Single, 59 | default_value: None, 60 | help: Some(ArgumentHelp::Text( 61 | "A parameter with multiple values example".to_string(), 62 | )), 63 | }) 64 | .add_argument(Argument { 65 | name: "mv".to_string(), 66 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 67 | argument_occurrence: ArgumentOccurrence::Single, 68 | value_type: ArgumentValueType::Multiple, 69 | default_value: None, 70 | help: Some(ArgumentHelp::Text( 71 | "A parameter with single value but can appear multiple times example".to_string(), 72 | )), 73 | }) 74 | .add_argument(Argument { 75 | name: "default".to_string(), 76 | key: vec!["--d1".to_string(), "-d".to_string()], 77 | argument_occurrence: ArgumentOccurrence::Single, 78 | value_type: ArgumentValueType::Single, 79 | default_value: Some("some default".to_string()), 80 | help: Some(ArgumentHelp::Text( 81 | "A parameter with default value example".to_string(), 82 | )), 83 | }); 84 | 85 | let command_line = vec![ 86 | "cargo", "make", "-mv2", "4", "5", "6", "--mo1=1", "-mo2", "2", "-f", "-s", "3", "arg1", 87 | "arg2", "-mo2", "arg5", 88 | ]; 89 | 90 | bencher.iter(|| { 91 | let result = parse(&command_line, &cli_spec); 92 | assert!(result.is_ok()); 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /docs/api/implementors/core/panic/unwind_safe/trait.UnwindSafe.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl UnwindSafe for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl UnwindSafe for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl UnwindSafe for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl UnwindSafe for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl UnwindSafe for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl UnwindSafe for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl UnwindSafe for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl UnwindSafe for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl UnwindSafe for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl UnwindSafe for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl RefUnwindSafe for ParserError","synthetic":true,"types":["cliparser::types::ParserError"]},{"text":"impl RefUnwindSafe for Command","synthetic":true,"types":["cliparser::types::Command"]},{"text":"impl RefUnwindSafe for ArgumentOccurrence","synthetic":true,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl RefUnwindSafe for ArgumentValueType","synthetic":true,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl RefUnwindSafe for ArgumentHelp","synthetic":true,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl RefUnwindSafe for Argument","synthetic":true,"types":["cliparser::types::Argument"]},{"text":"impl RefUnwindSafe for PositionalArgument","synthetic":true,"types":["cliparser::types::PositionalArgument"]},{"text":"impl RefUnwindSafe for CliSpecMetaInfo","synthetic":true,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl RefUnwindSafe for CliSpec","synthetic":true,"types":["cliparser::types::CliSpec"]},{"text":"impl RefUnwindSafe for CliParsed","synthetic":true,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/api/cliparser/all.html: -------------------------------------------------------------------------------- 1 | List of all items in this crate 2 | 5 |
9 | -------------------------------------------------------------------------------- /docs/api/implementors/core/cmp/trait.PartialEq.js: -------------------------------------------------------------------------------- 1 | (function() {var implementors = {}; 2 | implementors["cliparser"] = [{"text":"impl PartialEq<Command> for Command","synthetic":false,"types":["cliparser::types::Command"]},{"text":"impl PartialEq<ArgumentOccurrence> for ArgumentOccurrence","synthetic":false,"types":["cliparser::types::ArgumentOccurrence"]},{"text":"impl PartialEq<ArgumentValueType> for ArgumentValueType","synthetic":false,"types":["cliparser::types::ArgumentValueType"]},{"text":"impl PartialEq<ArgumentHelp> for ArgumentHelp","synthetic":false,"types":["cliparser::types::ArgumentHelp"]},{"text":"impl PartialEq<Argument> for Argument","synthetic":false,"types":["cliparser::types::Argument"]},{"text":"impl PartialEq<PositionalArgument> for PositionalArgument","synthetic":false,"types":["cliparser::types::PositionalArgument"]},{"text":"impl PartialEq<CliSpecMetaInfo> for CliSpecMetaInfo","synthetic":false,"types":["cliparser::types::CliSpecMetaInfo"]},{"text":"impl PartialEq<CliSpec> for CliSpec","synthetic":false,"types":["cliparser::types::CliSpec"]},{"text":"impl PartialEq<CliParsed> for CliParsed","synthetic":false,"types":["cliparser::types::CliParsed"]}]; 3 | if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() -------------------------------------------------------------------------------- /docs/api/cliparser/fn.help.html: -------------------------------------------------------------------------------- 1 | help in cliparser - Rust 2 | 5 |
9 |

Function cliparser::help

source · []
pub fn help(spec: &CliSpec) -> String
Expand description

Generates and returns the spec help text

10 |
11 | -------------------------------------------------------------------------------- /docs/api/cliparser/fn.version.html: -------------------------------------------------------------------------------- 1 | version in cliparser - Rust 2 | 5 |
9 |

Function cliparser::version

source · []
pub fn version(spec: &CliSpec) -> String
Expand description

Generates and returns the spec version text

10 |
11 | -------------------------------------------------------------------------------- /docs/api/source-script.js: -------------------------------------------------------------------------------- 1 | "use strict";(function(){function getCurrentFilePath(){const parts=window.location.pathname.split("/");const rootPathParts=window.rootPath.split("/");for(const rootPathPart of rootPathParts){if(rootPathPart===".."){parts.pop()}}let file=window.location.pathname.substring(parts.join("/").length);if(file.startsWith("/")){file=file.substring(1)}return file.substring(0,file.length-5)}function createDirEntry(elem,parent,fullPath,currentFile,hasFoundFile){const name=document.createElement("div");name.className="name";fullPath+=elem["name"]+"/";name.onclick=()=>{if(hasClass(this,"expand")){removeClass(this,"expand")}else{addClass(this,"expand")}};name.innerText=elem["name"];const children=document.createElement("div");children.className="children";const folders=document.createElement("div");folders.className="folders";if(elem.dirs){for(const dir of elem.dirs){if(createDirEntry(dir,folders,fullPath,currentFile,hasFoundFile)){addClass(name,"expand");hasFoundFile=true}}}children.appendChild(folders);const files=document.createElement("div");files.className="files";if(elem.files){for(const file_text of elem.files){const file=document.createElement("a");file.innerText=file_text;file.href=window.rootPath+"src/"+fullPath+file_text+".html";if(!hasFoundFile&¤tFile===fullPath+file_text){file.className="selected";addClass(name,"expand");hasFoundFile=true}files.appendChild(file)}}children.appendChild(files);parent.appendChild(name);parent.appendChild(children);return hasFoundFile&¤tFile.startsWith(fullPath)}function toggleSidebar(){const sidebar=document.querySelector("nav.sidebar");const child=this.children[0];if(child.innerText===">"){sidebar.classList.add("expanded");child.innerText="<";updateLocalStorage("source-sidebar-show","true")}else{sidebar.classList.remove("expanded");child.innerText=">";updateLocalStorage("source-sidebar-show","false")}}function createSidebarToggle(){const sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;const inner=document.createElement("div");if(getCurrentValue("source-sidebar-show")==="true"){inner.innerText="<"}else{inner.innerText=">"}sidebarToggle.appendChild(inner);return sidebarToggle}function createSourceSidebar(){if(!window.rootPath.endsWith("/")){window.rootPath+="/"}const container=document.querySelector("nav.sidebar");const sidebarToggle=createSidebarToggle();container.insertBefore(sidebarToggle,container.firstChild);const sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("source-sidebar-show")!=="true"){container.classList.remove("expanded")}else{container.classList.add("expanded")}const currentFile=getCurrentFilePath();let hasFoundFile=false;const title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(key=>{sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}const lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("span"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSourceHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",()=>{const match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(match)}});onEachLazy(document.getElementsByClassName("line-numbers"),el=>{el.addEventListener("click",handleSourceHighlight)});highlightSourceLines();window.createSourceSidebar=createSourceSidebar})() -------------------------------------------------------------------------------- /docs/api/FiraSans-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. 2 | with Reserved Font Name < Fira >, 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /docs/api/SourceSerif4-LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/api/SourceCodePro-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /tests/parse_test.rs: -------------------------------------------------------------------------------- 1 | use cliparser::parse; 2 | use cliparser::types::{ 3 | Argument, ArgumentHelp, ArgumentOccurrence, ArgumentValueType, CliSpec, CliSpecMetaInfo, 4 | PositionalArgument, 5 | }; 6 | use std::collections::{HashMap, HashSet}; 7 | 8 | #[test] 9 | fn parse_test() { 10 | let mut cli_spec = CliSpec::new(); 11 | 12 | cli_spec = cli_spec 13 | .set_meta_info(Some(CliSpecMetaInfo { 14 | author: Some("Sagie Gur-Ari".to_string()), 15 | version: Some("1.2.3-beta".to_string()), 16 | description: Some("Amazing example".to_string()), 17 | project: Some("example".to_string()), 18 | help_post_text: Some( 19 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 20 | ), 21 | })) 22 | .add_command("makers") 23 | .add_subcommand(vec!["cargo", "make"]) 24 | .set_positional_argument(Some(PositionalArgument { 25 | name: "args".to_string(), 26 | help: Some(ArgumentHelp::TextAndParam( 27 | "The command line arguments".to_string(), 28 | "ARGS".to_string(), 29 | )), 30 | })) 31 | .add_argument(Argument { 32 | name: "flag".to_string(), 33 | key: vec!["--flag".to_string(), "-f".to_string()], 34 | argument_occurrence: ArgumentOccurrence::Single, 35 | value_type: ArgumentValueType::None, 36 | default_value: None, 37 | help: Some(ArgumentHelp::Text( 38 | "A flag without value example".to_string(), 39 | )), 40 | }) 41 | .add_argument(Argument { 42 | name: "single".to_string(), 43 | key: vec!["--s1".to_string(), "-s".to_string()], 44 | argument_occurrence: ArgumentOccurrence::Single, 45 | value_type: ArgumentValueType::Single, 46 | default_value: None, 47 | help: Some(ArgumentHelp::Text( 48 | "A parameter with single value example".to_string(), 49 | )), 50 | }) 51 | .add_argument(Argument { 52 | name: "mo".to_string(), 53 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 54 | argument_occurrence: ArgumentOccurrence::Multiple, 55 | value_type: ArgumentValueType::Single, 56 | default_value: None, 57 | help: Some(ArgumentHelp::Text( 58 | "A parameter with multiple values example".to_string(), 59 | )), 60 | }) 61 | .add_argument(Argument { 62 | name: "mv".to_string(), 63 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 64 | argument_occurrence: ArgumentOccurrence::Single, 65 | value_type: ArgumentValueType::Multiple, 66 | default_value: None, 67 | help: Some(ArgumentHelp::Text( 68 | "A parameter with single value but can appear multiple times example".to_string(), 69 | )), 70 | }) 71 | .add_argument(Argument { 72 | name: "default".to_string(), 73 | key: vec!["--d1".to_string(), "-d".to_string()], 74 | argument_occurrence: ArgumentOccurrence::Single, 75 | value_type: ArgumentValueType::Single, 76 | default_value: Some("some default".to_string()), 77 | help: Some(ArgumentHelp::Text( 78 | "A parameter with default value example".to_string(), 79 | )), 80 | }); 81 | 82 | let result = parse( 83 | &vec![ 84 | "cargo", "make", "-mv2", "4", "5", "6", "--mo1", "1", "-mo2", "2", "-f", "-s", "3", 85 | "arg1", "arg2", "-mo2", "arg5", 86 | ], 87 | &cli_spec, 88 | ); 89 | 90 | assert!(result.is_ok()); 91 | let cli_parsed = result.unwrap(); 92 | 93 | let mut argument_names = HashSet::new(); 94 | argument_names.insert("flag".to_string()); 95 | argument_names.insert("single".to_string()); 96 | argument_names.insert("mo".to_string()); 97 | argument_names.insert("mv".to_string()); 98 | argument_names.insert("args".to_string()); 99 | let mut argument_values = HashMap::new(); 100 | argument_values.insert("single".to_string(), vec!["3".to_string()]); 101 | argument_values.insert("mo".to_string(), vec!["1".to_string(), "2".to_string()]); 102 | argument_values.insert( 103 | "mv".to_string(), 104 | vec!["4".to_string(), "5".to_string(), "6".to_string()], 105 | ); 106 | argument_values.insert( 107 | "args".to_string(), 108 | vec![ 109 | "arg1".to_string(), 110 | "arg2".to_string(), 111 | "-mo2".to_string(), 112 | "arg5".to_string(), 113 | ], 114 | ); 115 | argument_values.insert("default".to_string(), vec!["some default".to_string()]); 116 | assert_eq!(cli_parsed.arguments, argument_names); 117 | assert_eq!(cli_parsed.argument_values, argument_values); 118 | } 119 | -------------------------------------------------------------------------------- /docs/api/NanumBarunGothic-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), 2 | 3 | with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, 4 | NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, 5 | Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, 6 | NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, 7 | Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri 8 | 9 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 10 | This license is copied below, and is also available with a FAQ at: 11 | http://scripts.sil.org/OFL 12 | 13 | 14 | ----------------------------------------------------------- 15 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 16 | ----------------------------------------------------------- 17 | 18 | PREAMBLE 19 | The goals of the Open Font License (OFL) are to stimulate worldwide 20 | development of collaborative font projects, to support the font creation 21 | efforts of academic and linguistic communities, and to provide a free and 22 | open framework in which fonts may be shared and improved in partnership 23 | with others. 24 | 25 | The OFL allows the licensed fonts to be used, studied, modified and 26 | redistributed freely as long as they are not sold by themselves. The 27 | fonts, including any derivative works, can be bundled, embedded, 28 | redistributed and/or sold with any software provided that any reserved 29 | names are not used by derivative works. The fonts and derivatives, 30 | however, cannot be released under any other type of license. The 31 | requirement for fonts to remain under this license does not apply 32 | to any document created using the fonts or their derivatives. 33 | 34 | DEFINITIONS 35 | "Font Software" refers to the set of files released by the Copyright 36 | Holder(s) under this license and clearly marked as such. This may 37 | include source files, build scripts and documentation. 38 | 39 | "Reserved Font Name" refers to any names specified as such after the 40 | copyright statement(s). 41 | 42 | "Original Version" refers to the collection of Font Software components as 43 | distributed by the Copyright Holder(s). 44 | 45 | "Modified Version" refers to any derivative made by adding to, deleting, 46 | or substituting -- in part or in whole -- any of the components of the 47 | Original Version, by changing formats or by porting the Font Software to a 48 | new environment. 49 | 50 | "Author" refers to any designer, engineer, programmer, technical 51 | writer or other person who contributed to the Font Software. 52 | 53 | PERMISSION & CONDITIONS 54 | Permission is hereby granted, free of charge, to any person obtaining 55 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 56 | redistribute, and sell modified and unmodified copies of the Font 57 | Software, subject to the following conditions: 58 | 59 | 1) Neither the Font Software nor any of its individual components, 60 | in Original or Modified Versions, may be sold by itself. 61 | 62 | 2) Original or Modified Versions of the Font Software may be bundled, 63 | redistributed and/or sold with any software, provided that each copy 64 | contains the above copyright notice and this license. These can be 65 | included either as stand-alone text files, human-readable headers or 66 | in the appropriate machine-readable metadata fields within text or 67 | binary files as long as those fields can be easily viewed by the user. 68 | 69 | 3) No Modified Version of the Font Software may use the Reserved Font 70 | Name(s) unless explicit written permission is granted by the corresponding 71 | Copyright Holder. This restriction only applies to the primary font name as 72 | presented to the users. 73 | 74 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 75 | Software shall not be used to promote, endorse or advertise any 76 | Modified Version, except to acknowledge the contribution(s) of the 77 | Copyright Holder(s) and the Author(s) or with their explicit written 78 | permission. 79 | 80 | 5) The Font Software, modified or unmodified, in part or in whole, 81 | must be distributed entirely under this license, and must not be 82 | distributed under any other license. The requirement for fonts to 83 | remain under this license does not apply to any document created 84 | using the Font Software. 85 | 86 | TERMINATION 87 | This license becomes null and void if any of the above conditions are 88 | not met. 89 | 90 | DISCLAIMER 91 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 92 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 93 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 94 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 95 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 96 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 97 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 98 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 99 | OTHER DEALINGS IN THE FONT SOFTWARE. 100 | -------------------------------------------------------------------------------- /docs/api/cliparser/fn.parse_process.html: -------------------------------------------------------------------------------- 1 | parse_process in cliparser - Rust 2 | 5 |
pub fn parse_process(spec: &CliSpec) -> Result<CliParsed, ParserError>
Expand description

Parsers the given command line based on the given spec and returns the result.
10 | In case of error (such as invalid input), an error will be returned.
11 | In case the command line does not match the spec, Ok(None) will be returned.

12 |
13 | -------------------------------------------------------------------------------- /src/types_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn display_invalid_command_line() { 5 | let error = ParserError::InvalidCommandLine("test".to_string()); 6 | assert!(error.to_string().contains("test")); 7 | } 8 | 9 | #[test] 10 | fn display_invalid_cli_spec() { 11 | let error = ParserError::InvalidCliSpec("test".to_string()); 12 | assert!(error.to_string().contains("test")); 13 | } 14 | 15 | #[test] 16 | fn display_command_does_not_match_spec() { 17 | let error = ParserError::CommandDoesNotMatchSpec("test".to_string()); 18 | assert!(error.to_string().contains("test")); 19 | } 20 | 21 | #[test] 22 | fn display_internal_error() { 23 | let error = ParserError::InternalError("test".to_string()); 24 | assert!(error.to_string().contains("test")); 25 | } 26 | 27 | #[test] 28 | fn clispecmetainfo_new() { 29 | let meta_info = CliSpecMetaInfo::new(); 30 | 31 | assert!(meta_info.author.is_none()); 32 | assert!(meta_info.version.is_none()); 33 | assert!(meta_info.description.is_none()); 34 | assert!(meta_info.project.is_none()); 35 | assert!(meta_info.help_post_text.is_none()); 36 | } 37 | 38 | #[test] 39 | fn clispec_new() { 40 | let cli_spec = CliSpec::new(); 41 | 42 | assert!(cli_spec.command.is_empty()); 43 | assert!(cli_spec.arguments.is_empty()); 44 | assert!(cli_spec.positional_argument.is_none()); 45 | assert!(cli_spec.meta_info.is_none()); 46 | } 47 | 48 | #[test] 49 | fn clispec_builder_function() { 50 | let mut cli_spec1 = CliSpec::new(); 51 | cli_spec1 = cli_spec1 52 | .set_meta_info(Some(CliSpecMetaInfo { 53 | author: Some("Sagie Gur-Ari".to_string()), 54 | version: Some("1.2.3-beta".to_string()), 55 | description: Some("Amazing example".to_string()), 56 | project: Some("example".to_string()), 57 | help_post_text: Some( 58 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 59 | ), 60 | })) 61 | .add_command("makers") 62 | .add_subcommand(vec!["cargo", "make"]) 63 | .set_positional_argument(Some(PositionalArgument { 64 | name: "args".to_string(), 65 | help: Some(ArgumentHelp::TextAndParam( 66 | "The command line arguments".to_string(), 67 | "ARGS".to_string(), 68 | )), 69 | })) 70 | .add_argument(Argument { 71 | name: "flag".to_string(), 72 | key: vec!["--flag".to_string(), "-f".to_string()], 73 | argument_occurrence: ArgumentOccurrence::Single, 74 | value_type: ArgumentValueType::None, 75 | default_value: None, 76 | help: Some(ArgumentHelp::Text( 77 | "A flag without value example".to_string(), 78 | )), 79 | }); 80 | 81 | let mut cli_spec2 = CliSpec::new(); 82 | cli_spec2.meta_info = Some(CliSpecMetaInfo { 83 | author: Some("Sagie Gur-Ari".to_string()), 84 | version: Some("1.2.3-beta".to_string()), 85 | description: Some("Amazing example".to_string()), 86 | project: Some("example".to_string()), 87 | help_post_text: Some( 88 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 89 | ), 90 | }); 91 | cli_spec2 92 | .command 93 | .push(Command::Command("makers".to_string())); 94 | cli_spec2.command.push(Command::SubCommand(vec![ 95 | "cargo".to_string(), 96 | "make".to_string(), 97 | ])); 98 | cli_spec2.positional_argument = Some(PositionalArgument { 99 | name: "args".to_string(), 100 | help: Some(ArgumentHelp::TextAndParam( 101 | "The command line arguments".to_string(), 102 | "ARGS".to_string(), 103 | )), 104 | }); 105 | cli_spec2.arguments.push(Argument { 106 | name: "flag".to_string(), 107 | key: vec!["--flag".to_string(), "-f".to_string()], 108 | argument_occurrence: ArgumentOccurrence::Single, 109 | value_type: ArgumentValueType::None, 110 | default_value: None, 111 | help: Some(ArgumentHelp::Text( 112 | "A flag without value example".to_string(), 113 | )), 114 | }); 115 | 116 | assert_eq!(cli_spec1, cli_spec2); 117 | } 118 | 119 | #[test] 120 | fn cliparsed_new() { 121 | let cli_parsed = CliParsed::new(); 122 | 123 | assert!(cli_parsed.arguments.is_empty()); 124 | assert!(cli_parsed.argument_values.is_empty()); 125 | } 126 | 127 | #[test] 128 | fn cliparsed_get_first_none() { 129 | let cli_parsed = CliParsed::new(); 130 | 131 | assert!(cli_parsed.get_first_value("test").is_none()); 132 | } 133 | 134 | #[test] 135 | fn cliparsed_get_first_empty() { 136 | let mut cli_parsed = CliParsed::new(); 137 | cli_parsed 138 | .argument_values 139 | .insert("test".to_string(), vec![]); 140 | 141 | assert!(cli_parsed.get_first_value("test").is_none()); 142 | } 143 | 144 | #[test] 145 | fn cliparsed_get_first_multiple() { 146 | let mut cli_parsed = CliParsed::new(); 147 | cli_parsed 148 | .argument_values 149 | .insert("test".to_string(), vec!["1".to_string(), "2".to_string()]); 150 | 151 | assert_eq!(cli_parsed.get_first_value("test").unwrap(), "1"); 152 | } 153 | -------------------------------------------------------------------------------- /docs/api/cliparser/fn.parse_process_any.html: -------------------------------------------------------------------------------- 1 | parse_process_any in cliparser - Rust 2 | 5 |
pub fn parse_process_any(
    specs: Vec<&CliSpec>
) -> Result<(usize, CliParsed), ParserError>
Expand description

Parsers the current process command line based on the given specs and returns the result.
10 | In case of invalid input or none of the provided specs do not match the command line, an error will be returned.

11 |
12 | -------------------------------------------------------------------------------- /docs/api/cliparser/fn.parse_any.html: -------------------------------------------------------------------------------- 1 | parse_any in cliparser - Rust 2 | 5 |
9 |

Function cliparser::parse_any

source · []
pub fn parse_any(
    command_line: &Vec<&str>,
    specs: Vec<&CliSpec>
) -> Result<(usize, CliParsed), ParserError>
Expand description

Parsers the given command line based on the given specs and returns the result.
10 | In case of invalid input or none of the provided specs do not match the command line, an error will be returned.

11 |
12 | -------------------------------------------------------------------------------- /docs/api/settings.js: -------------------------------------------------------------------------------- 1 | "use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();updateLightAndDark();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function showLightAndDark(){addClass(document.getElementById("theme").parentElement,"hidden");removeClass(document.getElementById("preferred-light-theme").parentElement,"hidden");removeClass(document.getElementById("preferred-dark-theme").parentElement,"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme").parentElement,"hidden");addClass(document.getElementById("preferred-dark-theme").parentElement,"hidden");removeClass(document.getElementById("theme").parentElement,"hidden")}function updateLightAndDark(){if(getSettingValue("use-system-theme")!=="false"){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.getElementsByClassName("slider"),elem=>{const toggle=elem.previousElementSibling;const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(settingsElement.getElementsByClassName("select-wrapper"),elem=>{const select=elem.getElementsByTagName("select")[0];const settingId=select.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;const settingValue=getSettingValue(settingId);if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){output+="
";const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`
\ 2 | ${setting_name}\ 3 |
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";output+=``});output+="
"}else{const checked=setting["default"]===true?" checked":"";output+=``}output+="
"}return output}function buildSettingsPage(){const themes=getVar("themes").split(",");const settings=[{"name":"Use system theme","js_name":"use-system-theme","default":true,},{"name":"Theme","js_name":"theme","default":"light","options":themes,},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":themes,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":themes,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display=""}function elemIsInParent(elem,parent){while(elem&&elem!==document.body){if(elem===parent){return true}elem=elem.parentElement}return false}function blurHandler(event){const settingsButton=getSettingsButton();if(!elemIsInParent(document.activeElement,settingsButton)&&!elemIsInParent(event.relatedTarget,settingsButton)){window.hideSettings()}}if(isSettingsPage){getSettingsButton().onclick=function(event){event.preventDefault()}}else{const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");window.hideSettings=function(){settingsMenu.style.display="none"};settingsButton.onclick=function(event){if(elemIsInParent(event.target,settingsMenu)){return}event.preventDefault();if(settingsMenu.style.display!=="none"){window.hideSettings()}else{displaySettings()}};settingsButton.onblur=blurHandler;settingsButton.querySelector("a").onblur=blurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=blurHandler});settingsMenu.onblur=blurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() -------------------------------------------------------------------------------- /docs/api/cliparser/types/index.html: -------------------------------------------------------------------------------- 1 | cliparser::types - Rust 2 | 5 |
9 |

Module cliparser::types

source · []
Expand description

types

10 |

Defines the various types.

11 |

Structs

12 |

Holds the command line argument spec

13 |

Holds the command line parse result

14 |

Holds the command line spec (command/parameters/…)

15 |

Holds the command line spec meta information used to generate version and help messages

16 |

Holds the positional argument spec

17 |

Enums

18 |

The argument help text

19 |

The argument occurrence type (see values for more info)

20 |

The argument value type (see values for more info)

21 |

The command (not params) string/s

22 |

Holds the error information

23 |
24 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | //! # types 2 | //! 3 | //! Defines the various types. 4 | //! 5 | 6 | #[cfg(test)] 7 | #[path = "./types_test.rs"] 8 | mod types_test; 9 | 10 | use std::collections::{HashMap, HashSet}; 11 | use std::error::Error; 12 | use std::fmt; 13 | use std::fmt::Display; 14 | 15 | #[derive(Debug)] 16 | /// Holds the error information 17 | pub enum ParserError { 18 | /// Error Info Type 19 | InvalidCommandLine(String), 20 | /// Error Info Type 21 | InvalidCliSpec(String), 22 | /// Error Info Type 23 | CommandDoesNotMatchSpec(String), 24 | /// Error Info Type 25 | InternalError(String), 26 | } 27 | 28 | impl Display for ParserError { 29 | fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { 30 | match self { 31 | Self::InvalidCommandLine(ref message) => write!(formatter, "{}", message), 32 | Self::InvalidCliSpec(ref message) => write!(formatter, "{}", message), 33 | Self::CommandDoesNotMatchSpec(ref message) => write!(formatter, "{}", message), 34 | Self::InternalError(ref message) => write!(formatter, "{}", message), 35 | } 36 | } 37 | } 38 | 39 | impl Error for ParserError { 40 | fn source(&self) -> Option<&(dyn Error + 'static)> { 41 | match self { 42 | Self::InvalidCommandLine(_) => None, 43 | Self::InvalidCliSpec(_) => None, 44 | Self::CommandDoesNotMatchSpec(_) => None, 45 | Self::InternalError(_) => None, 46 | } 47 | } 48 | } 49 | 50 | #[derive(Debug, Clone, PartialEq)] 51 | /// The command (not params) string/s 52 | pub enum Command { 53 | /// Single command (not sub command) such as: "ls". 54 | /// Any path prefix will be ignored while parsing. 55 | Command(String), 56 | /// Sub command value such as: vec!["cargo".to_string(), "myplugin".to_string()]. 57 | /// Any path prefix will be ignored while parsing for the first element only. 58 | SubCommand(Vec), 59 | } 60 | 61 | #[derive(Debug, Clone, PartialEq, Copy)] 62 | /// The argument occurrence type (see values for more info) 63 | pub enum ArgumentOccurrence { 64 | /// The argument can appear only once 65 | Single, 66 | /// The argument can appear multiple times. The value of each occurrence will be 67 | /// picked up so even args with single value constraint can have multiple values if 68 | /// they support multiple occurrences. 69 | Multiple, 70 | } 71 | 72 | #[derive(Debug, Clone, PartialEq, Copy)] 73 | /// The argument value type (see values for more info) 74 | pub enum ArgumentValueType { 75 | /// The argument does not accept any value 76 | None, 77 | /// Only single value is allowed 78 | Single, 79 | /// Allows multiple values (minimum one) 80 | Multiple, 81 | } 82 | 83 | #[derive(Debug, Clone, PartialEq)] 84 | /// The argument help text 85 | pub enum ArgumentHelp { 86 | /// Text value 87 | Text(String), 88 | /// Text and variable name 89 | TextAndParam(String, String), 90 | } 91 | 92 | #[derive(Debug, Clone, PartialEq)] 93 | /// Holds the command line argument spec 94 | pub struct Argument { 95 | /// Unique name for the argument later used to pull the parsed information 96 | pub name: String, 97 | /// All possible argument keys in the command line (for example: vec!["--env".to_string(), "-e".to_string()]) 98 | pub key: Vec, 99 | /// The argument occurrence (see enum) 100 | pub argument_occurrence: ArgumentOccurrence, 101 | /// The possible value type for this specific argument 102 | pub value_type: ArgumentValueType, 103 | /// Default value if not found 104 | pub default_value: Option, 105 | /// Help text 106 | pub help: Option, 107 | } 108 | 109 | #[derive(Debug, Clone, PartialEq)] 110 | /// Holds the positional argument spec 111 | pub struct PositionalArgument { 112 | /// Unique name for the argument later used to pull the parsed information 113 | pub name: String, 114 | /// Help text 115 | pub help: Option, 116 | } 117 | 118 | #[derive(Debug, Clone, PartialEq, Default)] 119 | /// Holds the command line spec meta information used to generate version and help messages 120 | pub struct CliSpecMetaInfo { 121 | /// Author name 122 | pub author: Option, 123 | /// Version string 124 | pub version: Option, 125 | /// Description string 126 | pub description: Option, 127 | /// Project name 128 | pub project: Option, 129 | /// Post help text 130 | pub help_post_text: Option, 131 | } 132 | 133 | impl CliSpecMetaInfo { 134 | /// Returns new instance 135 | pub fn new() -> CliSpecMetaInfo { 136 | Default::default() 137 | } 138 | } 139 | 140 | #[derive(Debug, Clone, PartialEq, Default)] 141 | /// Holds the command line spec (command/parameters/...) 142 | pub struct CliSpec { 143 | /// A list of all possible commands and sub commands. 144 | pub command: Vec, 145 | /// A list of all possible command line arguments. 146 | pub arguments: Vec, 147 | /// The name of the argument that will hold all arguments after the last known key based 148 | /// argument. If not defined, such positional arguments are not allowed. 149 | pub positional_argument: Option, 150 | /// Meta information used for generating version and help messages 151 | pub meta_info: Option, 152 | } 153 | 154 | impl CliSpec { 155 | /// Returns new instance 156 | pub fn new() -> CliSpec { 157 | Default::default() 158 | } 159 | 160 | /// Sets the spec meta info 161 | pub fn set_meta_info(mut self, meta_info: Option) -> Self { 162 | self.meta_info = meta_info; 163 | self 164 | } 165 | 166 | /// Adds a command to the spec 167 | pub fn add_command(mut self, command: &str) -> Self { 168 | self.command.push(Command::Command(command.to_string())); 169 | self 170 | } 171 | 172 | /// Adds a sub command to the spec 173 | pub fn add_subcommand(mut self, sub_command: Vec<&str>) -> Self { 174 | let string_vec = sub_command.iter().map(|value| value.to_string()).collect(); 175 | self.command.push(Command::SubCommand(string_vec)); 176 | self 177 | } 178 | 179 | /// Sets the PositionalArgument 180 | pub fn set_positional_argument(mut self, argument: Option) -> Self { 181 | self.positional_argument = argument; 182 | self 183 | } 184 | 185 | /// Adds a Argument 186 | pub fn add_argument(mut self, argument: Argument) -> Self { 187 | self.arguments.push(argument); 188 | self 189 | } 190 | } 191 | 192 | #[derive(Debug, Clone, PartialEq, Default)] 193 | /// Holds the command line parse result 194 | pub struct CliParsed { 195 | /// A collection of all arguments found (list of names not keys). 196 | /// Arguments that were not found by defaulted to a given value will not be listed here. 197 | pub arguments: HashSet, 198 | /// A map of all values for arguments found. 199 | /// The map will exclude arguments that do not accept value but include arguments not provided 200 | /// on the command line but were defaulted to a given value. 201 | /// The map keys are the argument names (not keys) and the value is the list of all values 202 | /// found for all occurrences. 203 | pub argument_values: HashMap>, 204 | } 205 | 206 | impl CliParsed { 207 | /// Returns new instance 208 | pub fn new() -> CliParsed { 209 | Default::default() 210 | } 211 | 212 | /// returns the first value (if exists) 213 | pub fn get_first_value(&self, key: &str) -> Option { 214 | match self.argument_values.get(key) { 215 | Some(ref values) => { 216 | if values.len() == 0 { 217 | None 218 | } else { 219 | let first_value = values.first().clone().unwrap(); 220 | Some(first_value.to_string()) 221 | } 222 | } 223 | None => None, 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /examples/example.rs: -------------------------------------------------------------------------------- 1 | use cliparser::types::{ 2 | Argument, ArgumentHelp, ArgumentOccurrence, ArgumentValueType, CliSpec, CliSpecMetaInfo, 3 | PositionalArgument, 4 | }; 5 | use cliparser::{help, parse, version}; 6 | use std::collections::{HashMap, HashSet}; 7 | 8 | fn main() { 9 | let mut cli_spec = CliSpec::new(); 10 | 11 | // Add meta info to support help and version text generation 12 | cli_spec = cli_spec 13 | .set_meta_info(Some(CliSpecMetaInfo { 14 | author: Some("Sagie Gur-Ari".to_string()), 15 | version: Some("1.2.3-beta".to_string()), 16 | description: Some("Amazing example".to_string()), 17 | project: Some("example".to_string()), 18 | help_post_text: Some( 19 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 20 | ), 21 | })) 22 | // Define the prefix of the arguments. 23 | // It can be a command/s (path prefix ignored) and/or a sub command/s 24 | // If not defined, the parsing will start checking the arguments only. 25 | // In this example, the spec defines two ways to invoke a process, either 26 | // as 'makers' or as 'cargo make' and afterwards the arguments. 27 | .add_command("makers") 28 | .add_subcommand(vec!["cargo", "make"]) 29 | // Positional arguments come after all the known argument keys. 30 | // If the positional is None, positional arguments are not allowed. 31 | // Add -- to the command line forces positional arguments and stops key 32 | // based argument parsing. 33 | .set_positional_argument(Some(PositionalArgument { 34 | name: "args".to_string(), 35 | help: Some(ArgumentHelp::TextAndParam( 36 | "The command line arguments".to_string(), 37 | "ARGS".to_string(), 38 | )), 39 | })) 40 | // Add a 'flag' only argument which is an argument that does not accept any value. 41 | // You can define multiple variations of the parameter name. 42 | // For example, in this case putting --flag or -f in the command line would be parsed 43 | // as the 'flag' parameter. 44 | .add_argument(Argument { 45 | name: "flag".to_string(), 46 | key: vec!["--flag".to_string(), "-f".to_string()], 47 | argument_occurrence: ArgumentOccurrence::Single, 48 | value_type: ArgumentValueType::None, 49 | default_value: None, 50 | help: Some(ArgumentHelp::Text( 51 | "A flag without value example".to_string(), 52 | )), 53 | }) 54 | // Add an argument that accepts a single value, for example -s value 55 | .add_argument(Argument { 56 | name: "single".to_string(), 57 | key: vec!["--s1".to_string(), "-s".to_string()], 58 | argument_occurrence: ArgumentOccurrence::Single, 59 | value_type: ArgumentValueType::Single, 60 | default_value: None, 61 | help: Some(ArgumentHelp::Text( 62 | "A parameter with single value example".to_string(), 63 | )), 64 | }) 65 | // Add an argument that accepts multiple values 66 | .add_argument(Argument { 67 | name: "mo".to_string(), 68 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 69 | argument_occurrence: ArgumentOccurrence::Multiple, 70 | value_type: ArgumentValueType::Single, 71 | default_value: None, 72 | help: Some(ArgumentHelp::Text( 73 | "A parameter with multiple values example".to_string(), 74 | )), 75 | }) 76 | // Add an argument that can appear multiple times. 77 | // Even if the value type if Single, multiple occurrences will 78 | // enable the argument to collect multiple values (one for each occurrence). 79 | .add_argument(Argument { 80 | name: "mv".to_string(), 81 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 82 | argument_occurrence: ArgumentOccurrence::Single, 83 | value_type: ArgumentValueType::Multiple, 84 | default_value: None, 85 | help: Some(ArgumentHelp::Text( 86 | "A parameter with single value but can appear multiple times example".to_string(), 87 | )), 88 | }) 89 | // We can define a 'default' value. 90 | // In case the argument is not in the command line, we will get the default value. 91 | // However, the argument names list in the parsed struct will not include this 92 | // argument as it was not found. Only the argument values will contain it. 93 | // This is a good way to understand that we have a value but it was not entered by the caller. 94 | .add_argument(Argument { 95 | name: "default".to_string(), 96 | key: vec!["--d1".to_string(), "-d".to_string()], 97 | argument_occurrence: ArgumentOccurrence::Single, 98 | value_type: ArgumentValueType::Single, 99 | default_value: Some("some default".to_string()), 100 | help: Some(ArgumentHelp::Text( 101 | "A parameter with default value example".to_string(), 102 | )), 103 | }); 104 | 105 | // Parsers the given command line based on the given spec and returns the result. 106 | // In case of invalid input or the provided spec does not match the command line, an error will be returned. 107 | // In order to parse the process command line instead of providing it, use the parse_process. 108 | // Also, if you want to provide multiple specs and have each one checked, until the first one 109 | // which fits is found, use the parse_any and parse_process_any functions. 110 | let result = parse( 111 | &vec![ 112 | "cargo", "make", "-mv2", "4", "5", "6", "--mo1=1", "-mo2", "2", "-f", "-s", "3", 113 | "arg1", "arg2", "-mo2", "arg5", 114 | ], 115 | &cli_spec, 116 | ); 117 | 118 | // The CliParsed struct includes multiple members that define what was found 119 | // arguments - A collection of all arguments found (list of names not keys). 120 | // Arguments that were not found by defaulted to a given value will not be listed here. 121 | // argument_values - A map of all values for arguments found. 122 | // The map will exclude arguments that do not accept value but include arguments not provided 123 | // on the command line but were defaulted to a given value. 124 | // The map keys are the argument names (not keys) and the value is the list of all values 125 | // found for all occurrences. 126 | assert!(result.is_ok()); 127 | let cli_parsed = result.unwrap(); 128 | println!("Cli Parsed:\n{:?}", &cli_parsed); 129 | 130 | let mut argument_names = HashSet::new(); 131 | argument_names.insert("flag".to_string()); 132 | argument_names.insert("single".to_string()); 133 | argument_names.insert("mo".to_string()); 134 | argument_names.insert("mv".to_string()); 135 | argument_names.insert("args".to_string()); 136 | let mut argument_values = HashMap::new(); 137 | argument_values.insert("single".to_string(), vec!["3".to_string()]); 138 | argument_values.insert("mo".to_string(), vec!["1".to_string(), "2".to_string()]); 139 | argument_values.insert( 140 | "mv".to_string(), 141 | vec!["4".to_string(), "5".to_string(), "6".to_string()], 142 | ); 143 | argument_values.insert( 144 | "args".to_string(), 145 | vec![ 146 | "arg1".to_string(), 147 | "arg2".to_string(), 148 | "-mo2".to_string(), 149 | "arg5".to_string(), 150 | ], 151 | ); 152 | argument_values.insert("default".to_string(), vec!["some default".to_string()]); 153 | assert_eq!(cli_parsed.arguments, argument_names); 154 | assert_eq!(cli_parsed.argument_values, argument_values); 155 | 156 | // generate help text 157 | let help_text = help(&cli_spec); 158 | println!("{}", help_text); 159 | 160 | // generate version text 161 | let version_text = version(&cli_spec); 162 | println!("{}", version_text); 163 | } 164 | -------------------------------------------------------------------------------- /src/help.rs: -------------------------------------------------------------------------------- 1 | //! # help 2 | //! 3 | //! Generates help/version text based on given spec. 4 | //! 5 | 6 | #[cfg(test)] 7 | #[path = "./help_test.rs"] 8 | mod help_test; 9 | 10 | use crate::types::{ 11 | Argument, ArgumentHelp, ArgumentValueType, CliSpec, Command, PositionalArgument, 12 | }; 13 | 14 | /// Generates and returns the spec version text 15 | pub(crate) fn version(spec: &CliSpec) -> String { 16 | let mut buffer = String::new(); 17 | 18 | match spec.meta_info { 19 | Some(ref meta_info) => { 20 | if let Some(ref project) = meta_info.project { 21 | buffer.push_str(&project); 22 | } 23 | 24 | if let Some(ref version) = meta_info.version { 25 | if !buffer.is_empty() { 26 | buffer.push_str(" "); 27 | } 28 | buffer.push_str(&version); 29 | } 30 | } 31 | None => (), 32 | } 33 | 34 | buffer 35 | } 36 | 37 | /// Generates and returns the spec help text 38 | pub(crate) fn help(spec: &CliSpec) -> String { 39 | let mut buffer = version(spec); 40 | 41 | match spec.meta_info { 42 | Some(ref meta_info) => { 43 | if let Some(ref author) = meta_info.author { 44 | if !buffer.is_empty() { 45 | buffer.push_str("\n"); 46 | } 47 | buffer.push_str(&author); 48 | } 49 | 50 | if let Some(ref description) = meta_info.description { 51 | if !buffer.is_empty() { 52 | buffer.push_str("\n"); 53 | } 54 | buffer.push_str(&description); 55 | } 56 | } 57 | None => (), 58 | } 59 | 60 | if !buffer.is_empty() { 61 | buffer.push_str("\n\n"); 62 | } 63 | 64 | if append_usage_line(spec, &mut buffer) { 65 | buffer.push_str("\n\n"); 66 | } 67 | if append_args_line(spec, &mut buffer) { 68 | buffer.push_str("\n\n"); 69 | } 70 | if append_options_block(spec, &mut buffer) { 71 | buffer.push_str("\n\n"); 72 | } 73 | 74 | match spec.meta_info { 75 | Some(ref meta_info) => match meta_info.help_post_text { 76 | Some(ref text) => buffer.push_str(text), 77 | None => (), 78 | }, 79 | None => (), 80 | } 81 | 82 | buffer = buffer.trim().to_string(); 83 | buffer.push_str("\n"); 84 | 85 | buffer 86 | } 87 | 88 | fn append_usage_line(spec: &CliSpec, buffer: &mut String) -> bool { 89 | if spec.command.is_empty() && spec.arguments.is_empty() && spec.positional_argument.is_none() { 90 | return false; 91 | } 92 | 93 | buffer.push_str("USAGE:\n "); 94 | let mut sub_buffer = String::new(); 95 | let mut multiple = false; 96 | let mut added_content = false; 97 | for command in &spec.command { 98 | if !sub_buffer.is_empty() { 99 | sub_buffer.push_str(" | "); 100 | multiple = true; 101 | added_content = true; 102 | } 103 | 104 | match command { 105 | Command::Command(value) => sub_buffer.push_str(value), 106 | Command::SubCommand(values) => sub_buffer.push_str(values.join(" ").as_str()), 107 | } 108 | } 109 | if multiple { 110 | buffer.push_str("["); 111 | } 112 | buffer.push_str(&sub_buffer); 113 | if multiple { 114 | buffer.push_str("]"); 115 | } 116 | 117 | if !spec.arguments.is_empty() { 118 | if added_content { 119 | buffer.push_str(" "); 120 | } 121 | added_content = true; 122 | buffer.push_str("[OPTIONS]"); 123 | } 124 | 125 | if let Some(ref positional_argument_spec) = spec.positional_argument { 126 | let name = get_positional_argument_value_name(positional_argument_spec); 127 | 128 | if added_content { 129 | buffer.push_str(" "); 130 | } 131 | buffer.push_str("[--] [<"); 132 | buffer.push_str(&name); 133 | buffer.push_str(">...]"); 134 | } 135 | 136 | true 137 | } 138 | 139 | fn append_args_line(spec: &CliSpec, buffer: &mut String) -> bool { 140 | if let Some(ref positional_argument_spec) = spec.positional_argument { 141 | let name = get_positional_argument_value_name(positional_argument_spec); 142 | 143 | buffer.push_str("ARGS:\n <"); 144 | buffer.push_str(&name); 145 | buffer.push_str(">"); 146 | 147 | if let Some(ref help) = positional_argument_spec.help { 148 | buffer.push_str(" "); 149 | 150 | match help { 151 | ArgumentHelp::Text(text) => buffer.push_str(text), 152 | ArgumentHelp::TextAndParam(text, _) => buffer.push_str(text), 153 | } 154 | } 155 | 156 | true 157 | } else { 158 | false 159 | } 160 | } 161 | 162 | fn append_options_block(spec: &CliSpec, buffer: &mut String) -> bool { 163 | if !spec.arguments.is_empty() { 164 | let mut names = vec![]; 165 | let mut max_width = 0; 166 | 167 | for argument in &spec.arguments { 168 | let mut sub_buffer = String::new(); 169 | sub_buffer.push_str(" "); 170 | let mut added = false; 171 | for key in &argument.key { 172 | if added { 173 | sub_buffer.push_str(", "); 174 | } 175 | added = true; 176 | sub_buffer.push_str(&key); 177 | } 178 | 179 | let value_name = get_argument_value_name(argument); 180 | if let Some(name) = value_name { 181 | sub_buffer.push_str(" <"); 182 | sub_buffer.push_str(&name); 183 | sub_buffer.push_str(">"); 184 | } 185 | 186 | let name_len = sub_buffer.len(); 187 | names.push(sub_buffer); 188 | if max_width < name_len { 189 | max_width = name_len; 190 | } 191 | } 192 | 193 | buffer.push_str("OPTIONS:\n"); 194 | 195 | let mut index = 0; 196 | let help_offset = max_width + 4; 197 | for argument in &spec.arguments { 198 | if index > 0 { 199 | buffer.push_str("\n"); 200 | } 201 | 202 | let help_text = match argument.help { 203 | Some(ref help) => { 204 | let mut text = match help { 205 | ArgumentHelp::Text(ref text) => text.to_string(), 206 | ArgumentHelp::TextAndParam(ref text, _) => text.to_string(), 207 | }; 208 | if !text.is_empty() { 209 | text.push_str(" "); 210 | } 211 | 212 | text 213 | } 214 | None => "".to_string(), 215 | }; 216 | 217 | let default_text = match argument.value_type { 218 | ArgumentValueType::None => "".to_string(), 219 | _ => match argument.default_value { 220 | Some(ref value) => format!("[default: {}]", value), 221 | None => "".to_string(), 222 | }, 223 | }; 224 | 225 | let line = format!( 226 | "{: String { 243 | match positional_argument_spec.help { 244 | Some(ref help) => match help { 245 | ArgumentHelp::TextAndParam(_, value) => value.to_string(), 246 | ArgumentHelp::Text(_) => positional_argument_spec.name.clone(), 247 | }, 248 | None => positional_argument_spec.name.clone(), 249 | } 250 | } 251 | 252 | fn get_argument_value_name(argument_spec: &Argument) -> Option { 253 | if argument_spec.value_type == ArgumentValueType::None { 254 | None 255 | } else { 256 | let name = match argument_spec.help { 257 | Some(ref help) => match help { 258 | ArgumentHelp::TextAndParam(_, value) => value.to_string(), 259 | ArgumentHelp::Text(_) => argument_spec.name.clone(), 260 | }, 261 | None => argument_spec.name.clone(), 262 | }; 263 | 264 | Some(name) 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /docs/api/light.css: -------------------------------------------------------------------------------- 1 | body,#settings-menu #settings,#settings-menu #settings::before{background-color:white;color:black;}.setting-line .radio-line input{border-color:black;}.setting-line .radio-line input:checked{box-shadow:inset 0 0 0 3px white;background-color:#2196f3;}.setting-line .radio-line input:focus{box-shadow:0 0 1px 1px #2196f3;}.setting-line .radio-line input:checked:focus{box-shadow:inset 0 0 0 3px white,0 0 2px 2px #2196f3;}.setting-line .radio-line input:hover{border-color:#2196f3 !important;}.slider{background-color:#ccc;}.slider:before{background-color:white;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}h1,h2,h3,h4{color:black;}h1.fqn{border-bottom-color:#DDDDDD;}h2,h3,h4{border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre,.rustdoc.source .example-wrap{background-color:#F5F5F5;}.sidebar,.mobile-topbar,.sidebar-menu-toggle{background-color:#F5F5F5;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.rust-logo{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current,.sidebar a:hover{background-color:#fff;}.source .sidebar{background-color:#f1f1f1;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#FDFFD3 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5,.docblock h6{border-bottom-color:#ddd;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.search-results a:hover{background-color:#ddd;}.search-results a:focus{color:#000 !important;background-color:#ccc;}.search-results a:focus span{color:#000 !important;}a.result-trait:focus{background-color:#c7b6ff;}a.result-traitalias:focus{background-color:#c7b6ff;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-enum:focus{background-color:#e7b1a0;}a.result-struct:focus{background-color:#e7b1a0;}a.result-union:focus{background-color:#e7b1a0;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#c6afb3;}a.result-type:focus{background-color:#e7b1a0;}a.result-associatedtype:focus{background-color:#afc6e4;}a.result-foreigntype:focus{background-color:#e7b1a0;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#8ce488;}a.result-constant:focus,a.result-static:focus{background-color:#afc6e4;}a.result-primitive:focus{background-color:#e7b1a0;}a.result-keyword:focus{background-color:#afc6e4;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#AD378A;}.content span.struct,.content a.struct,.block a.current.struct{color:#AD378A;}.content span.type,.content a.type,.block a.current.type{color:#AD378A;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#3873AD;}.content span.associatedtype,.content a.associatedtype,.block a.current.associatedtype{color:#3873AD;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#AD378A;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#3873AD;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#AD378A;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#3873AD;}.content span.trait,.content a.trait,.block a.current.trait{color:#6E4FC9;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#5137AD;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#AD7C37;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#3873AD;}.sidebar a{color:#356da4;}.sidebar a.current.enum{color:#a63283;}.sidebar a.current.struct{color:#a63283;}.sidebar a.current.type{color:#a63283;}.sidebar a.current.associatedtype{color:#356da4;}.sidebar a.current.foreigntype{color:#356da4;}.sidebar a.current.attr,.sidebar a.current.derive,.sidebar a.current.macro{color:#067901;}.sidebar a.current.union{color:#a63283;}.sidebar a.current.constant .sidebar a.current.static{color:#356da4;}.sidebar a.current.primitive{color:#a63283;}.sidebar a.current.externcrate .sidebar a.current.mod{color:#356da4;}.sidebar a.current.trait{color:#6849c3;}.sidebar a.current.traitalias{color:#4b349e;}.sidebar a.current.fn,.sidebar a.current.method,.sidebar a.current.tymethod{color:#a67736;}.sidebar a.current.keyword{color:#356da4;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#3873AD;}a#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,pre.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,.in-band a{color:#000;}.search-results a{color:initial;}a.test-arrow{color:#f5f5f5;}body.source .example-wrap pre.rust a{background:#eee;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}#crate-search,.search-input{background-color:white;border-color:#e0e0e0 !important;}.search-input:focus{border-color:#66afe9;}.module-item .stab,.import-item .stab{color:#000;}.stab.empty-impl{background:#FFF5D6;border-color:#FFC600;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;}.stab.portability>code{background:none;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}.rightside,.out-of-band{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgb(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target{background:#FDFFD3;border-right:3px solid #AD7C37;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#3873AD;}.tooltip::after{background-color:#000;color:#fff;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}.notable-traits-tooltiptext .notable{border-bottom-color:#DDDDDD;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F5F5F5;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F5F5F5;border-right-color:#000;}#sidebar-filler{background-color:#F5F5F5;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow:inset 0 -1px 0 #c6cbd1;}#settings-menu>a,#help-button{border-color:#e0e0e0;background-color:#fff;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button:hover,#help-button:focus{border-color:#717171;}#settings-menu #settings,#settings-menu #settings::before{border-color:#DDDDDD;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(35%);}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}.search-results .result-name span.alias{color:#000;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#F5F5F5;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F5F5F5;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.scraped-example-list .scrape-help{border-color:#555;color:#333;}.scraped-example-list .scrape-help:hover{border-color:black;color:black;}.more-examples-toggle summary,.more-examples-toggle .hide-more{color:#999;}.scraped-example .example-wrap .rust span.highlight{background:#fcffd6;}.scraped-example .example-wrap .rust span.highlight.focus{background:#f6fdb0;}.scraped-example:not(.expanded) .code-wrapper:before{background:linear-gradient(to bottom,rgba(255,255,255,1),rgba(255,255,255,0));}.scraped-example:not(.expanded) .code-wrapper:after{background:linear-gradient(to top,rgba(255,255,255,1),rgba(255,255,255,0));}.toggle-line-inner{background:#ccc;}.toggle-line:hover .toggle-line-inner{background:#999;} -------------------------------------------------------------------------------- /src/lib_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::types::{ 3 | Argument, ArgumentOccurrence, ArgumentValueType, CliSpec, Command, PositionalArgument, 4 | }; 5 | use doc_comment as _; 6 | use std::collections::{HashMap, HashSet}; 7 | use std::env; 8 | 9 | #[test] 10 | fn parse_combination() { 11 | let mut cli_spec = CliSpec::new(); 12 | cli_spec.positional_argument = Some(PositionalArgument { 13 | name: "args".to_string(), 14 | help: None, 15 | }); 16 | cli_spec.arguments.push(Argument { 17 | name: "flag".to_string(), 18 | key: vec!["--flag".to_string(), "-f".to_string()], 19 | argument_occurrence: ArgumentOccurrence::Single, 20 | value_type: ArgumentValueType::None, 21 | default_value: None, 22 | help: None, 23 | }); 24 | cli_spec.arguments.push(Argument { 25 | name: "single".to_string(), 26 | key: vec!["--s1".to_string(), "-s".to_string()], 27 | argument_occurrence: ArgumentOccurrence::Single, 28 | value_type: ArgumentValueType::Single, 29 | default_value: None, 30 | help: None, 31 | }); 32 | cli_spec.arguments.push(Argument { 33 | name: "mo".to_string(), 34 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 35 | argument_occurrence: ArgumentOccurrence::Multiple, 36 | value_type: ArgumentValueType::Single, 37 | default_value: None, 38 | help: None, 39 | }); 40 | cli_spec.arguments.push(Argument { 41 | name: "mv".to_string(), 42 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 43 | argument_occurrence: ArgumentOccurrence::Single, 44 | value_type: ArgumentValueType::Multiple, 45 | default_value: None, 46 | help: None, 47 | }); 48 | cli_spec.arguments.push(Argument { 49 | name: "default".to_string(), 50 | key: vec!["--d1".to_string(), "-d".to_string()], 51 | argument_occurrence: ArgumentOccurrence::Single, 52 | value_type: ArgumentValueType::Single, 53 | default_value: Some("some default".to_string()), 54 | help: None, 55 | }); 56 | 57 | let result = parse( 58 | &vec![ 59 | "-mv2", "4", "5", "6", "--mo1", "1", "-mo2", "2", "-f", "-s", "3", "arg1", "arg2", 60 | "-mo2", "arg5", 61 | ], 62 | &cli_spec, 63 | ); 64 | 65 | assert!(result.is_ok()); 66 | let cli_parsed = result.unwrap(); 67 | 68 | let mut argument_names = HashSet::new(); 69 | argument_names.insert("flag".to_string()); 70 | argument_names.insert("single".to_string()); 71 | argument_names.insert("mo".to_string()); 72 | argument_names.insert("mv".to_string()); 73 | argument_names.insert("args".to_string()); 74 | let mut argument_values = HashMap::new(); 75 | argument_values.insert("single".to_string(), vec!["3".to_string()]); 76 | argument_values.insert("mo".to_string(), vec!["1".to_string(), "2".to_string()]); 77 | argument_values.insert( 78 | "mv".to_string(), 79 | vec!["4".to_string(), "5".to_string(), "6".to_string()], 80 | ); 81 | argument_values.insert( 82 | "args".to_string(), 83 | vec![ 84 | "arg1".to_string(), 85 | "arg2".to_string(), 86 | "-mo2".to_string(), 87 | "arg5".to_string(), 88 | ], 89 | ); 90 | argument_values.insert("default".to_string(), vec!["some default".to_string()]); 91 | assert_eq!(cli_parsed.arguments, argument_names); 92 | assert_eq!(cli_parsed.argument_values, argument_values); 93 | } 94 | 95 | #[test] 96 | #[ignore] 97 | fn parse_process_combination() { 98 | let mut cli_spec = CliSpec::new(); 99 | cli_spec.positional_argument = Some(PositionalArgument { 100 | name: "args".to_string(), 101 | help: None, 102 | }); 103 | cli_spec.arguments.push(Argument { 104 | name: "flag".to_string(), 105 | key: vec!["--flag".to_string(), "-f".to_string()], 106 | argument_occurrence: ArgumentOccurrence::Single, 107 | value_type: ArgumentValueType::None, 108 | default_value: None, 109 | help: None, 110 | }); 111 | cli_spec.arguments.push(Argument { 112 | name: "single".to_string(), 113 | key: vec!["--s1".to_string(), "-s".to_string()], 114 | argument_occurrence: ArgumentOccurrence::Single, 115 | value_type: ArgumentValueType::Single, 116 | default_value: None, 117 | help: None, 118 | }); 119 | cli_spec.arguments.push(Argument { 120 | name: "mo".to_string(), 121 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 122 | argument_occurrence: ArgumentOccurrence::Multiple, 123 | value_type: ArgumentValueType::Single, 124 | default_value: None, 125 | help: None, 126 | }); 127 | cli_spec.arguments.push(Argument { 128 | name: "mv".to_string(), 129 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 130 | argument_occurrence: ArgumentOccurrence::Single, 131 | value_type: ArgumentValueType::Multiple, 132 | default_value: None, 133 | help: None, 134 | }); 135 | cli_spec.arguments.push(Argument { 136 | name: "default".to_string(), 137 | key: vec!["--d1".to_string(), "-d".to_string()], 138 | argument_occurrence: ArgumentOccurrence::Single, 139 | value_type: ArgumentValueType::Single, 140 | default_value: Some("some default".to_string()), 141 | help: None, 142 | }); 143 | 144 | env::set_var( 145 | "TEST_CLI_PARSER_COMMAND_LINE", 146 | vec![ 147 | "-mv2", "4", "5", "6", "--mo1", "1", "-mo2", "2", "-f", "-s", "3", "arg1", "arg2", 148 | "-mo2", "arg5", 149 | ] 150 | .join(" "), 151 | ); 152 | let result = parse_process(&cli_spec); 153 | 154 | assert!(result.is_ok()); 155 | let cli_parsed = result.unwrap(); 156 | 157 | let mut argument_names = HashSet::new(); 158 | argument_names.insert("flag".to_string()); 159 | argument_names.insert("single".to_string()); 160 | argument_names.insert("mo".to_string()); 161 | argument_names.insert("mv".to_string()); 162 | argument_names.insert("args".to_string()); 163 | let mut argument_values = HashMap::new(); 164 | argument_values.insert("single".to_string(), vec!["3".to_string()]); 165 | argument_values.insert("mo".to_string(), vec!["1".to_string(), "2".to_string()]); 166 | argument_values.insert( 167 | "mv".to_string(), 168 | vec!["4".to_string(), "5".to_string(), "6".to_string()], 169 | ); 170 | argument_values.insert( 171 | "args".to_string(), 172 | vec![ 173 | "arg1".to_string(), 174 | "arg2".to_string(), 175 | "-mo2".to_string(), 176 | "arg5".to_string(), 177 | ], 178 | ); 179 | argument_values.insert("default".to_string(), vec!["some default".to_string()]); 180 | assert_eq!(cli_parsed.arguments, argument_names); 181 | assert_eq!(cli_parsed.argument_values, argument_values); 182 | } 183 | 184 | #[test] 185 | fn parse_any_match() { 186 | let mut cli_spec1 = CliSpec::new(); 187 | cli_spec1 188 | .command 189 | .push(Command::Command("test1".to_string())); 190 | cli_spec1.arguments.push(Argument { 191 | name: "testarg1".to_string(), 192 | key: vec!["--test".to_string()], 193 | argument_occurrence: ArgumentOccurrence::Single, 194 | value_type: ArgumentValueType::None, 195 | default_value: Some("test_default".to_string()), 196 | help: None, 197 | }); 198 | 199 | let mut cli_spec2 = CliSpec::new(); 200 | cli_spec2.command.push(Command::Command("test".to_string())); 201 | cli_spec2.arguments.push(Argument { 202 | name: "testarg2".to_string(), 203 | key: vec!["--test".to_string()], 204 | argument_occurrence: ArgumentOccurrence::Single, 205 | value_type: ArgumentValueType::None, 206 | default_value: None, 207 | help: None, 208 | }); 209 | 210 | let empty_cli_spec = CliSpec::new(); 211 | 212 | let result = parse_any( 213 | &vec!["test", "--test"], 214 | vec![&cli_spec1, &empty_cli_spec, &cli_spec2], 215 | ); 216 | 217 | assert!(result.is_ok()); 218 | let (index, cli_parsed) = result.unwrap(); 219 | assert_eq!(index, 2); 220 | 221 | let mut argument_names = HashSet::new(); 222 | argument_names.insert("testarg2".to_string()); 223 | assert_eq!(cli_parsed.arguments, argument_names); 224 | assert!(cli_parsed.argument_values.is_empty()); 225 | } 226 | 227 | #[test] 228 | #[ignore] 229 | fn parse_process_any_match() { 230 | let mut cli_spec1 = CliSpec::new(); 231 | cli_spec1 232 | .command 233 | .push(Command::Command("test1".to_string())); 234 | cli_spec1.arguments.push(Argument { 235 | name: "testarg1".to_string(), 236 | key: vec!["--test".to_string()], 237 | argument_occurrence: ArgumentOccurrence::Single, 238 | value_type: ArgumentValueType::None, 239 | default_value: Some("test_default".to_string()), 240 | help: None, 241 | }); 242 | 243 | let mut cli_spec2 = CliSpec::new(); 244 | cli_spec2.command.push(Command::Command("test".to_string())); 245 | cli_spec2.arguments.push(Argument { 246 | name: "testarg2".to_string(), 247 | key: vec!["--test".to_string()], 248 | argument_occurrence: ArgumentOccurrence::Single, 249 | value_type: ArgumentValueType::None, 250 | default_value: None, 251 | help: None, 252 | }); 253 | 254 | let empty_cli_spec = CliSpec::new(); 255 | 256 | env::set_var( 257 | "TEST_CLI_PARSER_COMMAND_LINE", 258 | vec!["test", "--test"].join(" "), 259 | ); 260 | let result = parse_process_any(vec![&cli_spec1, &empty_cli_spec, &cli_spec2]); 261 | 262 | assert!(result.is_ok()); 263 | let (index, cli_parsed) = result.unwrap(); 264 | assert_eq!(index, 2); 265 | 266 | let mut argument_names = HashSet::new(); 267 | argument_names.insert("testarg2".to_string()); 268 | assert_eq!(cli_parsed.arguments, argument_names); 269 | assert!(cli_parsed.argument_values.is_empty()); 270 | } 271 | -------------------------------------------------------------------------------- /docs/api/dark.css: -------------------------------------------------------------------------------- 1 | body,#settings-menu #settings,#settings-menu #settings::before{background-color:#353535;color:#ddd;}.setting-line .radio-line input{border-color:#ddd;}.setting-line .radio-line input:checked{box-shadow:inset 0 0 0 3px #353535;background-color:#2196f3;}.setting-line .radio-line input:focus{box-shadow:0 0 1px 1px #2196f3;}.setting-line .radio-line input:checked:focus{box-shadow:inset 0 0 0 3px #353535,0 0 2px 2px #2196f3;}.setting-line .radio-line input:hover{border-color:#2196f3 !important;}.slider{background-color:#ccc;}.slider:before{background-color:white;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}h1,h2,h3,h4{color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3,h4{border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre,.rustdoc.source .example-wrap{background-color:#2A2A2A;}.sidebar,.mobile-topbar,.sidebar-menu-toggle{background-color:#505050;}.rust-logo{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) #5a5a5a;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current,.sidebar a:hover{background:#444;}.source .sidebar{background-color:#565656;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5,.docblock h6{border-bottom-color:#DDD;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#eee !important;background-color:#616161;}.search-results a:focus span{color:#eee !important;}a.result-trait:focus{background-color:#013191;}a.result-traitalias:focus{background-color:#013191;}a.result-mod:focus,a.result-externcrate:focus{background-color:#884719;}a.result-enum:focus{background-color:#194e9f;}a.result-struct:focus{background-color:#194e9f;}a.result-union:focus{background-color:#194e9f;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#4950ed;}a.result-type:focus{background-color:#194e9f;}a.result-associatedtype:focus{background-color:#884719;}a.result-foreigntype:focus{background-color:#194e9f;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#217d1c;}a.result-constant:focus,a.result-static:focus{background-color:#884719;}a.result-primitive:focus{background-color:#194e9f;}a.result-keyword:focus{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#2dbfb8;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#2dbfb8;}.content span.associatedtype,.content a.associatedtype,.block a.current.associatedtype{color:#D2991D;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#2dbfb8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#2dbfb8;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#D2991D;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2dbfb8;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#D2991D;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b78cf2;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#D2991D;}.sidebar a{color:#fdbf35;}.sidebar a.current.enum{color:#12ece2;}.sidebar a.current.struct{color:#12ece2;}.sidebar a.current.type{color:#12ece2;}.sidebar a.current.associatedtype{color:#fdbf35;}.sidebar a.current.foreigntype{color:#12ece2;}.sidebar a.current.attr,.sidebar a.current.derive,.sidebar a.current.macro{color:#0be900;}.sidebar a.current.union{color:#12ece2;}.sidebar a.current.constant .sidebar a.current.static{color:#fdbf35;}.sidebar a.current.primitive{color:#12ece2;}.sidebar a.current.externcrate .sidebar a.current.mod{color:#fdbf35;}.sidebar a.current.trait{color:#cca7ff;}.sidebar a.current.traitalias{color:#cca7ff;}.sidebar a.current.fn,.sidebar a.current.method,.sidebar a.current.tymethod{color:#32d479;}.sidebar a.current.keyword{color:#fdbf35;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#D2991D;}a#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,pre.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,.in-band a{color:#ddd;}.search-results a{color:#ddd;}a.test-arrow{color:#dedede;}body.source .example-wrap pre.rust a{background:#333;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search,.search-input{color:#111;background-color:#f0f0f0;border-color:#f0f0f0 !important;}.search-input{border-color:#e0e0e0;}.search-input:focus{border-color:#008dfd;}.module-item .stab,.import-item .stab{color:#ddd;}.stab.empty-impl{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;color:#2f2f2f;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;color:#2f2f2f;}.stab.portability>code{background:none;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);}.rightside,.out-of-band{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target{background-color:#494a3d;border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;border-color:#000;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}.notable-traits-tooltiptext .notable{border-bottom-color:#d2d2d2;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow:inset 0 -1px 0 #c6cbd1;}#settings-menu>a,#help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button:hover,#help-button:focus{border-color:#ffb900;}#settings-menu #settings,#settings-menu #settings::before{border-color:#d2d2d2;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(65%);}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}.search-results .result-name span.alias{color:#fff;}.search-results .result-name span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.scraped-example-list .scrape-help{border-color:#aaa;color:#eee;}.scraped-example-list .scrape-help:hover{border-color:white;color:white;}.more-examples-toggle summary,.more-examples-toggle .hide-more{color:#999;}.scraped-example .example-wrap .rust span.highlight{background:rgb(91,59,1);}.scraped-example .example-wrap .rust span.highlight.focus{background:rgb(124,75,15);}.scraped-example:not(.expanded) .code-wrapper:before{background:linear-gradient(to bottom,rgba(53,53,53,1),rgba(53,53,53,0));}.scraped-example:not(.expanded) .code-wrapper:after{background:linear-gradient(to top,rgba(53,53,53,1),rgba(53,53,53,0));}.toggle-line-inner{background:#999;}.toggle-line:hover .toggle-line-inner{background:#c5c5c5;} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cliparser 2 | 3 | [![crates.io](https://img.shields.io/crates/v/cliparser.svg)](https://crates.io/crates/cliparser) [![CI](https://github.com/sagiegurari/cliparser/workflows/CI/badge.svg?branch=master)](https://github.com/sagiegurari/cliparser/actions) [![codecov](https://codecov.io/gh/sagiegurari/cliparser/branch/master/graph/badge.svg)](https://codecov.io/gh/sagiegurari/cliparser)
4 | [![license](https://img.shields.io/crates/l/cliparser.svg)](https://github.com/sagiegurari/cliparser/blob/master/LICENSE) [![Libraries.io for GitHub](https://img.shields.io/librariesio/github/sagiegurari/cliparser.svg)](https://libraries.io/cargo/cliparser) [![Documentation](https://docs.rs/cliparser/badge.svg)](https://docs.rs/crate/cliparser/) [![downloads](https://img.shields.io/crates/d/cliparser.svg)](https://crates.io/crates/cliparser)
5 | [![Built with cargo-make](https://sagiegurari.github.io/cargo-make/assets/badges/cargo-make.svg)](https://sagiegurari.github.io/cargo-make) 6 | 7 | > Simple command line parser. 8 | 9 | * [Overview](#overview) 10 | * [Usage](#usage) 11 | * [Installation](#installation) 12 | * [API Documentation](https://sagiegurari.github.io/cliparser/) 13 | * [Contributing](.github/CONTRIBUTING.md) 14 | * [Release History](CHANGELOG.md) 15 | * [License](#license) 16 | 17 | 18 | ## Overview 19 | This library provide a very simple API to parse command line arguments.
20 | It will not cover all possible use cases in order to ensure a simple thin API. 21 | 22 | 23 | ## Usage 24 | The following is a simple usage example (there are more capabilities, see API docs): 25 | 26 | 27 | ```rust 28 | use cliparser::types::{ 29 | Argument, ArgumentHelp, ArgumentOccurrence, ArgumentValueType, CliSpec, CliSpecMetaInfo, 30 | PositionalArgument, 31 | }; 32 | use cliparser::{help, parse, version}; 33 | use std::collections::{HashMap, HashSet}; 34 | 35 | fn main() { 36 | let mut cli_spec = CliSpec::new(); 37 | 38 | // Add meta info to support help and version text generation 39 | cli_spec = cli_spec 40 | .set_meta_info(Some(CliSpecMetaInfo { 41 | author: Some("Sagie Gur-Ari".to_string()), 42 | version: Some("1.2.3-beta".to_string()), 43 | description: Some("Amazing example".to_string()), 44 | project: Some("example".to_string()), 45 | help_post_text: Some( 46 | "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), 47 | ), 48 | })) 49 | // Define the prefix of the arguments. 50 | // It can be a command/s (path prefix ignored) and/or a sub command/s 51 | // If not defined, the parsing will start checking the arguments only. 52 | // In this example, the spec defines two ways to invoke a process, either 53 | // as 'makers' or as 'cargo make' and afterwards the arguments. 54 | .add_command("makers") 55 | .add_subcommand(vec!["cargo", "make"]) 56 | // Positional arguments come after all the known argument keys. 57 | // If the positional is None, positional arguments are not allowed. 58 | // Add -- to the command line forces positional arguments and stops key 59 | // based argument parsing. 60 | .set_positional_argument(Some(PositionalArgument { 61 | name: "args".to_string(), 62 | help: Some(ArgumentHelp::TextAndParam( 63 | "The command line arguments".to_string(), 64 | "ARGS".to_string(), 65 | )), 66 | })) 67 | // Add a 'flag' only argument which is an argument that does not accept any value. 68 | // You can define multiple variations of the parameter name. 69 | // For example, in this case putting --flag or -f in the command line would be parsed 70 | // as the 'flag' parameter. 71 | .add_argument(Argument { 72 | name: "flag".to_string(), 73 | key: vec!["--flag".to_string(), "-f".to_string()], 74 | argument_occurrence: ArgumentOccurrence::Single, 75 | value_type: ArgumentValueType::None, 76 | default_value: None, 77 | help: Some(ArgumentHelp::Text( 78 | "A flag without value example".to_string(), 79 | )), 80 | }) 81 | // Add an argument that accepts a single value, for example -s value 82 | .add_argument(Argument { 83 | name: "single".to_string(), 84 | key: vec!["--s1".to_string(), "-s".to_string()], 85 | argument_occurrence: ArgumentOccurrence::Single, 86 | value_type: ArgumentValueType::Single, 87 | default_value: None, 88 | help: Some(ArgumentHelp::Text( 89 | "A parameter with single value example".to_string(), 90 | )), 91 | }) 92 | // Add an argument that accepts multiple values 93 | .add_argument(Argument { 94 | name: "mo".to_string(), 95 | key: vec!["--mo1".to_string(), "-mo2".to_string()], 96 | argument_occurrence: ArgumentOccurrence::Multiple, 97 | value_type: ArgumentValueType::Single, 98 | default_value: None, 99 | help: Some(ArgumentHelp::Text( 100 | "A parameter with multiple values example".to_string(), 101 | )), 102 | }) 103 | // Add an argument that can appear multiple times. 104 | // Even if the value type if Single, multiple occurrences will 105 | // enable the argument to collect multiple values (one for each occurrence). 106 | .add_argument(Argument { 107 | name: "mv".to_string(), 108 | key: vec!["--mv1".to_string(), "-mv2".to_string()], 109 | argument_occurrence: ArgumentOccurrence::Single, 110 | value_type: ArgumentValueType::Multiple, 111 | default_value: None, 112 | help: Some(ArgumentHelp::Text( 113 | "A parameter with single value but can appear multiple times example".to_string(), 114 | )), 115 | }) 116 | // We can define a 'default' value. 117 | // In case the argument is not in the command line, we will get the default value. 118 | // However, the argument names list in the parsed struct will not include this 119 | // argument as it was not found. Only the argument values will contain it. 120 | // This is a good way to understand that we have a value but it was not entered by the caller. 121 | .add_argument(Argument { 122 | name: "default".to_string(), 123 | key: vec!["--d1".to_string(), "-d".to_string()], 124 | argument_occurrence: ArgumentOccurrence::Single, 125 | value_type: ArgumentValueType::Single, 126 | default_value: Some("some default".to_string()), 127 | help: Some(ArgumentHelp::Text( 128 | "A parameter with default value example".to_string(), 129 | )), 130 | }); 131 | 132 | // Parsers the given command line based on the given spec and returns the result. 133 | // In case of invalid input or the provided spec does not match the command line, an error will be returned. 134 | // In order to parse the process command line instead of providing it, use the parse_process. 135 | // Also, if you want to provide multiple specs and have each one checked, until the first one 136 | // which fits is found, use the parse_any and parse_process_any functions. 137 | let result = parse( 138 | &vec![ 139 | "cargo", "make", "-mv2", "4", "5", "6", "--mo1=1", "-mo2", "2", "-f", "-s", "3", 140 | "arg1", "arg2", "-mo2", "arg5", 141 | ], 142 | &cli_spec, 143 | ); 144 | 145 | // The CliParsed struct includes multiple members that define what was found 146 | // arguments - A collection of all arguments found (list of names not keys). 147 | // Arguments that were not found by defaulted to a given value will not be listed here. 148 | // argument_values - A map of all values for arguments found. 149 | // The map will exclude arguments that do not accept value but include arguments not provided 150 | // on the command line but were defaulted to a given value. 151 | // The map keys are the argument names (not keys) and the value is the list of all values 152 | // found for all occurrences. 153 | assert!(result.is_ok()); 154 | let cli_parsed = result.unwrap(); 155 | println!("Cli Parsed:\n{:?}", &cli_parsed); 156 | 157 | let mut argument_names = HashSet::new(); 158 | argument_names.insert("flag".to_string()); 159 | argument_names.insert("single".to_string()); 160 | argument_names.insert("mo".to_string()); 161 | argument_names.insert("mv".to_string()); 162 | argument_names.insert("args".to_string()); 163 | let mut argument_values = HashMap::new(); 164 | argument_values.insert("single".to_string(), vec!["3".to_string()]); 165 | argument_values.insert("mo".to_string(), vec!["1".to_string(), "2".to_string()]); 166 | argument_values.insert( 167 | "mv".to_string(), 168 | vec!["4".to_string(), "5".to_string(), "6".to_string()], 169 | ); 170 | argument_values.insert( 171 | "args".to_string(), 172 | vec![ 173 | "arg1".to_string(), 174 | "arg2".to_string(), 175 | "-mo2".to_string(), 176 | "arg5".to_string(), 177 | ], 178 | ); 179 | argument_values.insert("default".to_string(), vec!["some default".to_string()]); 180 | assert_eq!(cli_parsed.arguments, argument_names); 181 | assert_eq!(cli_parsed.argument_values, argument_values); 182 | 183 | // generate help text 184 | let help_text = help(&cli_spec); 185 | println!("{}", help_text); 186 | 187 | // generate version text 188 | let version_text = version(&cli_spec); 189 | println!("{}", version_text); 190 | } 191 | ``` 192 | 193 | 194 | 195 | ## Installation 196 | In order to use this library, just add it as a dependency: 197 | 198 | ```ini 199 | [dependencies] 200 | cliparser = "^0.1.2" 201 | ``` 202 | 203 | ## API Documentation 204 | See full docs at: [API Docs](https://sagiegurari.github.io/cliparser/) 205 | 206 | ## Contributing 207 | See [contributing guide](.github/CONTRIBUTING.md) 208 | 209 | 210 | ## Release History 211 | 212 | See [Changelog](CHANGELOG.md) 213 | 214 | 215 | ## License 216 | Developed by Sagie Gur-Ari and licensed under the Apache 2 open source license. 217 | --------------------------------------------------------------------------------