{"id":13692514,"url":"https://github.com/guonaihong/clop","last_synced_at":"2025-10-09T23:36:50.656Z","repository":{"id":38240494,"uuid":"234701236","full_name":"guonaihong/clop","owner":"guonaihong","description":"^=^ clop是基于struct的命令行解析库，专注是它的灵魂，像AK47一样，简单，强大，专注，让命令行里面的疑难杂症统统走开[从零实现]","archived":false,"fork":false,"pushed_at":"2024-05-26T07:02:41.000Z","size":167,"stargazers_count":133,"open_issues_count":7,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-08-15T08:13:25.785Z","etag":null,"topics":["argparse","cli","command-line","env","subcommand"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guonaihong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-18T07:59:50.000Z","updated_at":"2025-02-14T02:20:58.000Z","dependencies_parsed_at":"2024-01-13T22:55:07.952Z","dependency_job_id":"f8e94bcc-9893-480f-88d9-0e8a71befa81","html_url":"https://github.com/guonaihong/clop","commit_stats":null,"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/guonaihong/clop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guonaihong%2Fclop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guonaihong%2Fclop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guonaihong%2Fclop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guonaihong%2Fclop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guonaihong","download_url":"https://codeload.github.com/guonaihong/clop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guonaihong%2Fclop/sbom","scorecard":{"id":449610,"data":{"date":"2025-08-11","repo":{"name":"github.com/guonaihong/clop","commit":"ba7a9fd2c9d5ddd106407c9e1fa7337e8ad7e3b9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.9,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":3,"reason":"Found 10/30 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/go.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/guonaihong/clop/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/guonaihong/clop/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/guonaihong/clop/go.yml/master?enable=pin","Warn: downloadThenRun not pinned by hash: .github/workflows/go.yml:27","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   1 out of   1 goCommand dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 26 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T07:50:45.827Z","repository_id":38240494,"created_at":"2025-08-19T07:50:45.827Z","updated_at":"2025-08-19T07:50:45.827Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002310,"owners_count":26083340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argparse","cli","command-line","env","subcommand"],"created_at":"2024-08-02T17:00:58.938Z","updated_at":"2025-10-09T23:36:50.626Z","avatar_url":"https://github.com/guonaihong.png","language":"Go","funding_links":[],"categories":["开源类库","Open source library","Go"],"sub_categories":["命令行","Command Line"],"readme":"# clop\n\n[![Go](https://github.com/guonaihong/clop/workflows/Go/badge.svg)](https://github.com/guonaihong/clop/actions)\n[![codecov](https://codecov.io/gh/guonaihong/clop/branch/master/graph/badge.svg)](https://codecov.io/gh/guonaihong/clop)\n[![Go Report Card](https://goreportcard.com/badge/github.com/guonaihong/clop)](https://goreportcard.com/report/github.com/guonaihong/clop)\n\nclop (Command Line Option Parse)是一款基于struct的命令行解析器，麻雀虽小，五脏俱全(从零实现)。\n\n![clop.png](https://github.com/guonaihong/images/blob/master/clop/clop.png)\n\n## feature\n\n* 支持环境变量绑定 ```env DEBUG=xx ./proc```\n* 支持参数搜集 ```cat a.txt b.txt```，可以把```a.txt, b.txt```散装成员归归类，收集到你指定的结构体成员里\n* 支持短选项```proc -d``` 或者长选项```proc --debug```不在话下\n* posix风格命令行支持，支持命令组合```ls -ltr```是```ls -l -t -r```简写形式，方便实现普通posix 标准命令\n* 子命令(```subcommand```)支持，方便实现git风格子命令```git add ```，简洁的子命令注册方式，只要会写结构体就行，3,4,5到无穷尽子命令也支持，只要你喜欢，用上clop就可以实现\n* 默认值支持```default:\"1\"```，支持多种数据类型，让你省去类型转换的烦恼\n* 贴心的重复命令报错\n* 严格的短选项，长选项报错。避免二义性选项诞生\n* 效验模式支持，不需要写一堆的```if x!= \"\" ``` or ```if y!=0```浪费青春的代码\n* 可以获取命令优先级别，方便设置命令别名\n* 解析flag包代码生成clop代码\n* 指定`解析`函数， 自动绑定数据\n\n![feature list](https://github.com/guonaihong/images/blob/master/clop/featurelist.png)\n\n## 内容\n\n- [Installation](#Installation)\n- [Quick start](#quick-start)\n- [example](#example)\n\t- [base type](#base-type)\n\t\t- [int](#int)\n\t\t- [float64](#float64)\n\t\t- [time.Duration](#duration)\n\t\t- [string](#string)\n\t- [array](#array)\n\t\t- [similar to curl command](#similar-to-curl-command)\n\t\t- [similar to join command](#similar-to-join-command)\n\t- [1. How to use required tags](#required-flag)\n\t- [2. Support environment variables](#support-environment-variables)\n\t\t- [2.1 Custom environment variable name](#custom-environment-variable-name)\n\t\t- [2.2 Quick writing of environment variables](#quick-writing-of-environment-variables)\n\t- [3. Set default value](#set-default-value)\n\t- [4. How to implement git style commands](#subcommand)\n\t\t- [4.1 Sub command implementation method 1](#sub-command-implementation-method-1)\n\t\t- [4.2 Sub command implementation method 2](#sub-command-implementation-method-2)\n\t- [5. Get command priority](#get-command-priority)\n\t- [6. Can only be set once](#can-only-be-set-once)\n\t- [7. Quick write](#quick-write)\n\t- [8. Multi structure series](#multi-structure-series)\n\t- [9. Support callback function parsing](#support-callback-function-parsing)\n\t- [Advanced features](#Advanced-features)\n\t\t- [Parsing flag code to generate clop code](#Parsing-flag-code-to-generate-clop-code)\n- [Implementing linux command options](#Implementing-linux-command-options)\n\t- [cat](#cat)\n- [faq](#faq)\n\t- [The subcommand or option does not take effect](#The-subcommand-or-option-does-not-take-effect)\n\n## Installation\n\n```\ngo get github.com/guonaihong/clop\n```\n\n## Quick start\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype Hello struct {\n\tFile string `clop:\"-f; --file\" usage:\"file\"`\n}\n\nfunc main() {\n\n\th := Hello{}\n\tclop.SetVersion(\"v0.2.0\")\n\tclop.SetVersionOption(\"\", \"version\")\n\tclop.SetAbout(\"这是一个简单的示例demo\")\n\tclop.Bind(\u0026h)\n\tfmt.Printf(\"%#v\\n\", h)\n}\n// ./one -f test\n// main.Hello{File:\"test\"}\n// ./one --file test\n// main.Hello{File:\"test\"}\n\n```\n## example\n### base type\n#### int \n```go\npackage main\n\nimport (\n        \"fmt\"\n\n        \"github.com/guonaihong/clop\"\n)\n\ntype IntDemo struct {\n        Int int `clop:\"short;long\" usage:\"int\"`\n}\n\nfunc main() {\n        id := \u0026IntDemo{}\n        clop.Bind(id)\n        fmt.Printf(\"id = %v\\n\", id)\n}\n//  ./int -i 3\n// id = \u0026{3}\n// ./int --int 3\n// id = \u0026{3}\n```\n#### float64\n```go\npackage main\n\nimport (\n        \"fmt\"\n\n        \"github.com/guonaihong/clop\"\n)\n\ntype Float64Demo struct {\n        Float64 float64 `clop:\"short;long\" usage:\"float64\"`\n}\n\nfunc main() {\n        fd := \u0026Float64Demo{}\n        clop.Bind(fd)\n        fmt.Printf(\"fd = %v\\n\", fd)\n}\n// ./float64 -f 3.14\n// fd = \u0026{3.14}\n// ./float64 --float64 3.14\n// fd = \u0026{3.14}\n```\n#### duration\n```go\npackage main\n\nimport (\n        \"fmt\"\n        \"time\"\n\n        \"github.com/guonaihong/clop\"\n)\n\ntype DurationDemo struct {\n        Duration time.Duration `clop:\"short;long\" usage:\"duration\"`\n}\n\nfunc main() {\n        dd := \u0026DurationDemo{}\n        clop.Bind(dd)\n        fmt.Printf(\"dd = %v\\n\", dd)\n}\n// ./duration -d 1h\n// dd = \u0026{1h0m0s}\n// ./duration --duration 1h\n// dd = \u0026{1h0m0s}\n```\n#### string\n```go\npackage main\n\nimport (\n        \"fmt\"\n\n        \"github.com/guonaihong/clop\"\n)\n\ntype StringDemo struct {\n        String string `clop:\"short;long\" usage:\"string\"`\n}\n\nfunc main() {\n        s := \u0026StringDemo{}\n        clop.Bind(s)\n        fmt.Printf(\"s = %v\\n\", s)\n}\n// ./string --string hello\n// s = \u0026{hello}\n// ./string -s hello\n// s = \u0026{hello}\n```\n\n## array\n#### similar to curl command\n```go\npackage main\n\nimport (\n        \"fmt\"\n\n        \"github.com/guonaihong/clop\"\n)\n\ntype ArrayDemo struct {\n        Header []string `clop:\"-H;long\" usage:\"header\"`\n}\n\nfunc main() {\n        h := \u0026ArrayDemo{}\n        clop.Bind(h)\n        fmt.Printf(\"h = %v\\n\", h)\n}\n// ./array -H session:sid --header token:my\n// h = \u0026{[session:sid token:my]}\n```\n## similar to join command\n加上greedy属性，就支持数组贪婪写法。类似join命令。\n```go\npackage main\n\nimport (\n    \"fmt\"\n\n    \"github.com/guonaihong/clop\"\n)\n\ntype test struct {\n    A []int `clop:\"-a;greedy\" usage:\"test array\"`\n    B int   `clop:\"-b\" usage:\"test int\"`\n}\n\nfunc main() {\n    a := \u0026test{}\n    clop.Bind(a)\n    fmt.Printf(\"%#v\\n\", a)\n}\n\n/*\n运行\n./use_array -a 12 34 56 78 -b 100\n输出\n\u0026main.test{A:[]int{12, 34, 56, 78}, B:100}\n*/\n\n```\n### required flag\n```go\npackage main\n\nimport (\n\t\"github.com/guonaihong/clop\"\n)\n\ntype curl struct {\n\tUrl string `clop:\"-u; --url\" usage:\"url\" valid:\"required\"`\n}\n\nfunc main() {\n\n\tc := curl{}\n\tclop.Bind(\u0026c)\n}\n\n// ./required \n// error: -u; --url must have a value!\n// For more information try --help\n```\n#### set default value\n可以使用default tag设置默认值，普通类型直接写，复合类型用json表示\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/guonaihong/clop\"\n)\n\ntype defaultExample struct {\n    Int          int       `default:\"1\"`\n    Float64      float64   `default:\"3.64\"`\n    Float32      float32   `default:\"3.32\"`\n    SliceString  []string  `default:\"[\\\"one\\\", \\\"two\\\"]\"`\n    SliceInt     []int     `default:\"[1,2,3,4,5]\"`\n    SliceFloat64 []float64 `default:\"[1.1,2.2,3.3,4.4,5.5]\"`\n}\n\nfunc main() {\n    de := defaultExample{}\n    clop.Bind(\u0026de)\n    fmt.Printf(\"%v\\n\", de) \n}\n// run\n//         ./use_def\n// output:\n//         {1 3.64 3.32 [one two] [1 2 3 4 5] [1.1 2.2 3.3 4.4 5.5]}\n```\n### Support environment variables\n#### custom environment variable name\n```go\n// file name use_env.go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype env struct {\n\tOmpNumThread string `clop:\"env=omp_num_thread\" usage:\"omp num thread\"`\n\tPath         string `clop:\"env=XPATH\" usage:\"xpath\"`\n\tMax          int    `clop:\"env=MAX\" usage:\"max thread\"`\n}\n\nfunc main() {\n\te := env{}\n\tclop.Bind(\u0026e)\n\tfmt.Printf(\"%#v\\n\", e)\n}\n// run\n// env XPATH=`pwd` omp_num_thread=3 MAX=4 ./use_env \n// output\n// main.env{OmpNumThread:\"3\", Path:\"/home/guo\", Max:4}\n```\n#### Quick writing of environment variables\n使用env tag会根据结构体名, 生成一个环境变量名, 规则就是驼峰命令名, 改成大写下划线\n```go\n// file name use_env.go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype env struct {\n\tOmpNumThread string `clop:\"env\" usage:\"omp num thread\"`\n\tXpath         string `clop:\"env\" usage:\"xpath\"`\n\tMax          int    `clop:\"env\" usage:\"max thread\"`\n}\n\nfunc main() {\n\te := env{}\n\tclop.Bind(\u0026e)\n\tfmt.Printf(\"%#v\\n\", e)\n}\n// run\n// env XPATH=`pwd` OMP_NUM_THREAD=3 MAX=4 ./use_env \n// output\n// main.env{OmpNumThread:\"3\", Xpath:\"/home/guo\", Max:4}\n```\n### subcommand\n#### Sub command implementation method 1\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype add struct {\n\tAll      bool     `clop:\"-A; --all\" usage:\"add changes from all tracked and untracked files\"`\n\tForce    bool     `clop:\"-f; --force\" usage:\"allow adding otherwise ignored files\"`\n\tPathspec []string `clop:\"args=pathspec\"`\n}\n\ntype mv struct {\n\tForce bool `clop:\"-f; --force\" usage:\"allow adding otherwise ignored files\"`\n}\n\ntype git struct {\n\tAdd add `clop:\"subcommand=add\" usage:\"Add file contents to the index\"`\n\tMv  mv  `clop:\"subcommand=mv\" usage:\"Move or rename a file, a directory, or a symlink\"`\n}\n\nfunc main() {\n\tg := git{}\n\tclop.Bind(\u0026g)\n\tfmt.Printf(\"git:%#v\\n\", g)\n\tfmt.Printf(\"git:set mv(%t) or set add(%t)\\n\", clop.IsSetSubcommand(\"mv\"), clop.IsSetSubcommand(\"add\"))\n\n\tswitch {\n\tcase clop.IsSetSubcommand(\"mv\"):\n\t\tfmt.Printf(\"subcommand mv\\n\")\n\tcase clop.IsSetSubcommand(\"add\"):\n\t\tfmt.Printf(\"subcommand add\\n\")\n\t}\n}\n\n// run:\n// ./git add -f\n\n// output:\n// git:main.git{Add:main.add{All:false, Force:true, Pathspec:[]string(nil)}, Mv:main.mv{Force:false}}\n// git:set mv(false) or set add(true)\n// subcommand add\n\n```\n#### Sub command implementation method 2\n使用clop实现子命令的第2种做法, 子命令结构体只要实现```SubMain```方法, 该方法clop库会帮你自动调用. 省去在main里面写一堆if else判断(相对方法1来说), 特别是子命令特别多的情况, 推荐用这种方法.\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype add struct {\n\tAll      bool     `clop:\"-A; --all\" usage:\"add changes from all tracked and untracked files\"`\n\tForce    bool     `clop:\"-f; --force\" usage:\"allow adding otherwise ignored files\"`\n\tPathspec []string `clop:\"args=pathspec\"`\n}\n\nfunc (a *add) SubMain() {\n// 当add子命令被设置时\n// clop会自动调用这个函数\n}\n\ntype mv struct {\n\tForce bool `clop:\"-f; --force\" usage:\"allow adding otherwise ignored files\"`\n}\n\nfunc (m *mv) SubMain() {\n// 当mv 子命令被设置时\n// clop会自动调用这个函数\n}\n\ntype git struct {\n\tAdd add `clop:\"subcommand=add\" usage:\"Add file contents to the index\"`\n\tMv  mv  `clop:\"subcommand=mv\" usage:\"Move or rename a file, a directory, or a symlink\"`\n}\n\nfunc main() {\n\tg := git{}\n\tclop.Bind(\u0026g)\n}\n```\n## Get command priority\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype cat struct {\n\tNumberNonblank bool `clop:\"-b;--number-nonblank\"\n                             usage:\"number nonempty output lines, overrides\"`\n\n\tShowEnds bool `clop:\"-E;--show-ends\"\n                       usage:\"display $ at end of each line\"`\n}\n\nfunc main() {\n\n\tc := cat{}\n\tclop.Bind(\u0026c)\n\n\tif clop.GetIndex(\"number-nonblank\") \u003c clop.GetIndex(\"show-ends\") {\n\t\tfmt.Printf(\"cat -b -E\\n\")\n\t} else {\n\t\tfmt.Printf(\"cat -E -b \\n\")\n\t}\n}\n// cat -be \n// 输出 cat -b -E\n// cat -Eb\n// 输出 cat -E -b\n```\n\n\n## Can only be set once\n指定选项只能被设置一次，如果命令行选项，使用两次则会报错。\n```go\npackage main\n\nimport (\n    \"github.com/guonaihong/clop\"\n)\n\ntype Once struct {\n    Debug bool `clop:\"-d; --debug; once\" usage:\"debug mode\"`\n}\n\nfunc main() {\n    o := Once{}\n    clop.Bind(\u0026o)\n}\n/*\n./once -debug -debug\nerror: The argument '-d' was provided more than once, but cannot be used multiple times\nFor more information try --help\n*/\n```\n\n\n## quick write\n快速写法，通过使用固定的short, long tag生成短，长选项。可以和 [cat](#cat) 例子直观比较下。命令行选项越多，越能节约时间，提升效率。\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/guonaihong/clop\"\n)\n\ntype cat struct {\n\tNumberNonblank bool `clop:\"-c;long\" \n\t                     usage:\"number nonempty output lines, overrides\"`\n\n\tShowEnds bool `clop:\"-E;long\" \n\t               usage:\"display $ at end of each line\"`\n\n\tNumber bool `clop:\"-n;long\" \n\t             usage:\"number all output lines\"`\n\n\tSqueezeBlank bool `clop:\"-s;long\" \n\t                   usage:\"suppress repeated empty output lines\"`\n\n\tShowTab bool `clop:\"-T;long\" \n\t              usage:\"display TAB characters as ^I\"`\n\n\tShowNonprinting bool `clop:\"-v;long\" \n\t                      usage:\"use ^ and M- notation, except for LFD and TAB\" `\n\n\tFiles []string `clop:\"args=files\"`\n}\n\nfunc main() {\n \tc := cat{}\n\terr := clop.Bind(\u0026c)\n\n\tfmt.Printf(\"%#v, %s\\n\", c, err)\n}\n```\n## Multi structure series\n多结构体串联功能. 多结构体统一组成一个命令行视图\n\n如果命令行解析是要怼到多个(\u003e=2)结构体里面, 可以使用结构体串联功能, 前面几个结构体使用```clop.Register()```接口, 最后一个结构体使用```clop.Bind()```函数.\n```go\n/*\n┌────────────────┐\n│                │\n│                │\n│  ServerAddress │                        ┌─────────────────────┐\n├────────────────┤                        │                     │\n│                │   ──────────────────►  │                     │\n│                │                        │  clop.MustRegitser()│\n│     Rate       │                        │                     │\n│                │                        └─────────────────────┘\n└────────────────┘\n\n\n\n┌────────────────┐\n│                │\n│   ThreadNum    │\n│                │                        ┌─────────────────────┐\n│                │                        │                     │\n├────────────────┤   ──────────────────►  │                     │\n│                │                        │ clop.Bind()         │\n│   OpenVad      │                        │                     │\n│                │                        │                     │\n└────────────────┘                        └─────────────────────┘\n */\n\ntype Server struct {\n\tServerAddress string `clop:\"long\" usage:\"Server address\"`\n\tRate time.Duration `clop:\"long\" usage:\"The speed at which audio is sent\"`\n}\n\ntype Asr struct{\n\tThreadNum int `clop:\"long\" usage:\"thread number\"`\n\tOpenVad bool `clop:\"long\" usage:\"open vad\"`\n}\n\n func main() {\n\t asr := Asr{}\n\t ser := Server{}\n\t clop.MustRegister(\u0026asr)\n\t clop.Bind(\u0026ser)\n }\n\n // 可以使用如下命令行参数测试下效果\n // ./example --server-address\", \":8080\", \"--rate\", \"1s\", \"--thread-num\", \"20\", \"--open-vad\"\n ```\n## Support callback function parsing\n* 使用callback=name的写法， 其中name就是需要调用的解析函数。\n```go\ntype TestCallback struct {\n\tSize int `clop:\"short;long;callback=ParseSize\" usage:\"parse size\"`\n\tMax  int `clop:\"short;long\"`\n}\n\nfunc (t *TestCallback) ParseSize(val string) {\n\t// 做些解析工作\n\t// t.Size = 解析之后的值\n}\n\nfunc main() {\n \tt := TestCallback{}\n\terr := clop.Bind(\u0026t)\n\n\tfmt.Printf(\"%#v, %s\\n\", t, err)\n}\n``` \n## Advanced features\n高级功能里面有一些clop包比较有特色的功能\n### Parsing flag code to generate clop code\n让你爽翻天, 如果你的command想迁移至clop, 但是面对众多的flag代码, 又不想花费太多时间在无谓的人肉code转换上, 这时候你就需要clop命令, 一行命令解决你的痛点.\n\n#### 1.安装clop命令\n```bash\ngo get github.com/guonaihong/clop/cmd/clop\n```\n#### 2.使用clop解析包含flag包的代码\n就可以把main.go里面的flag库转成clop包的调用方式\n```bash\nclop -f main.go\n````\n```main.go```代码如下\n```go\npackage main\n\nimport \"flag\"\n\nfunc main() {\n\ts := flag.String(\"string\", \"\", \"string usage\")\n\ti := flag.Int(\"int\", \"\", \"int usage\")\n\tflag.Parse()\n}\n```\n\n输出代码如下\n```go\npackage main\n\nimport (\n\t\"github.com/guonaihong/clop\"\n)\n\ntype flagAutoGen struct {\n\tFlag string `clop:\"--string\" usage:\"string usage\" `\n\tFlag int    `clop:\"--int\" usage:\"int usage\" `\n}\n\nfunc main() {\n\tvar flagVar flagAutoGen\n\tclop.Bind(\u0026flagVar)\n}\n```\n\n## Implementing linux command options\n### cat\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/guonaihong/clop\"\n)\n\ntype cat struct {\n\tNumberNonblank bool `clop:\"-c;--number-nonblank\" \n\t                     usage:\"number nonempty output lines, overrides\"`\n\n\tShowEnds bool `clop:\"-E;--show-ends\" \n\t               usage:\"display $ at end of each line\"`\n\n\tNumber bool `clop:\"-n;--number\" \n\t             usage:\"number all output lines\"`\n\n\tSqueezeBlank bool `clop:\"-s;--squeeze-blank\" \n\t                   usage:\"suppress repeated empty output lines\"`\n\n\tShowTab bool `clop:\"-T;--show-tabs\" \n\t              usage:\"display TAB characters as ^I\"`\n\n\tShowNonprinting bool `clop:\"-v;--show-nonprinting\" \n\t                      usage:\"use ^ and M- notation, except for LFD and TAB\" `\n\n\tFiles []string `clop:\"args=files\"`\n}\n\nfunc main() {\n\n\tc := cat{}\n\terr := clop.Bind(\u0026c)\n\n\tfmt.Printf(\"%#v, %s\\n\", c, err)\n}\n\n/*\nUsage:\n    ./cat [Flags] \u003cfiles\u003e \n\nFlags:\n    -E,--show-ends           display $ at end of each line \n    -T,--show-tabs           display TAB characters as ^I \n    -c,--number-nonblank     number nonempty output lines, overrides \n    -n,--number              number all output lines \n    -s,--squeeze-blank       suppress repeated empty output lines \n    -v,--show-nonprinting    use ^ and M- notation, except for LFD and TAB \n\nArgs:\n    \u003cfiles\u003e\n*/\n```\n\n## faq\n### The subcommand or option does not take effect\nq: 关于子命令或者命令行命令没有生效  \na: 可以检查下结构体的字段是否是大写开头。","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguonaihong%2Fclop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguonaihong%2Fclop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguonaihong%2Fclop/lists"}