Skip to main content

babashkacli

Command-line argument parsing for turning Clojure functions into CLIs

معلومات المصدر

المستودع
hugoduncan/library-skills
آخر نشاط في المصدر
١٤ نوفمبر ٢٠٢٥ في ١٢:٢٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٣
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
babashka.cli
description
Command-line argument parsing for turning Clojure functions into CLIs
# babashka.cli Command-line argument parsing library for transforming Clojure functions into CLIs with minimal effort. ## Overview babashka.cli converts command-line arguments into Clojure data structures, supporting both keyword-style (`:opt value`) and Unix-style (`--opt value`) arguments. Designed to minimize friction when creating CLIs from existing Clojure functions. **Key Features:** - Automatic type coercion - Flexible argument syntax (`:foo` or `--foo`) - Subcommand dispatch - Validation and error handling - Boolean flags and negative flags - Collection handling for repeated options - Default values **Artifact:** `org.babashka/cli` **Latest Version:** 0.8.60 **License:** MIT **Repository:** https://github.com/babashka/cli ## Installation Add to `deps.edn`: ```clojure {:deps {org.babashka/cli {:mvn/version "0.8.60"}}} ``` Or `bb.edn` for Babashka: ```clojure {:deps {org.babashka/cli {:mvn/version "0.8.60"}}} ``` Since babashka 0.9.160, babashka.cli is built-in. ## Core Concepts ### Parsing vs. Args Separation - `parse-opts` - Returns flat map of parsed options - `parse-args` - Separates into `:opts`, `:cmds`, `:rest-args` ### Open World Assumption Extra arguments don't cause errors by default. Use `:restrict` for strict validation. ### Coercion Strategy Values are coerced based on specifications, not inferred from values alone. This ensures predictable type handling. ## API Reference ### Parsing Functions #### parse-opts Parse command-line arguments into options map. ```clojure (require '[babashka.cli :as cli]) ;; Basic parsing (cli/parse-opts ["--port" "8080"]) ;;=> {:port "8080"} ;; With coercion (cli/parse-opts ["--port" "8080"] {:coerce {:port :long}}) ;;=> {:port 8080} ;; With aliases (cli/parse-opts ["-p" "8080"] {:alias {:p :port} :coerce {:port :long}}) ;;=> {:port 8080} ``` **Options:** - `:coerce` - Type coercion map (`:boolean`, `:int`, `:long`, `:double`, `:symbol`, `:keyword`) - `:alias` - Short name to long name mappings - `:spec` - Structured option specifications - `:restrict` - Restrict to specified options only - `:require` - Required option keys - `:validate` - Validation predicates - `:exec-args` - Default values - `:args->opts` - Map positional args to option keys - `:no-keyword-opts` - Only accept `--foo` style (not `:foo`) - `:error-fn` - Custom error handler #### parse-args Parse arguments with separation of options, commands, and rest args. ```clojure (cli/parse-args ["--verbose" "deploy" "prod" "--force"] {:coerce {:verbose :boolean :force :boolean}}) ;;=> {:cmds ["deploy" "prod"] ;; :opts {:verbose true :force true} ;; :rest-args []} ``` Returns map with: - `:opts` - Parsed options - `:cmds` - Subcommands (non-option arguments) - `:rest-args` - Arguments after `--` #### parse-cmds Extract subcommands from arguments. ```clojure (cli/parse-cmds ["deploy" "prod" "--force"]) ;;=> {:cmds ["deploy" "prod"] ;; :args ["--force"]} ;; Without keyword opts (cli/parse-cmds ["deploy" ":env" "prod"] {:no-keyword-opts true}) ;;=> {:cmds ["deploy" ":env" "prod"] ;; :args []} ``` ### Coercion #### Type Keywords - `:boolean` - True/false values - `:int` - Integer - `:long` - Long integer - `:double` - Floating point - `:symbol` - Clojure symbol - `:keyword` - Clojure keyword #### Collection Coercion Use empty vector to collect multiple values: ```clojure (cli/parse-opts ["--path" "src" "--path" "test"] {:coerce {:path []}}) ;;=> {:path ["src" "test"]} ``` Typed collections: ```clojure (cli/parse-opts ["--port" "8080" "--port" "8081"] {:coerce {:port [:long]}}) ;;=> {:port [8080 8081]} ``` #### auto-coerce Automatic coercion for unspecified options (enabled by default): ```clojure (cli/parse-opts ["--enabled" "true" "--count" "42" "--mode" ":prod"]) ;;=> {:enabled true :count 42 :mode :prod} ``` Converts: - `"true"`/`"false"` → boolean - Numeric strings → numbers via `edn/read-string` - Strings starting with `:` → keywords ### Boolean Flags ```clojure ;; Flag present = true (cli/parse-opts ["--verbose"]) ;;=> {:verbose true} ;; Combined short flags (cli/parse-opts ["-vvv"]) ;;=> {:v true} ;; Negative flags (cli/parse-opts ["--no-colors"]) ;;=> {:colors false} ;; Explicit values (cli/parse-opts ["--force" "false"] {:coerce {:force :boolean}}) ;;=> {:force false} ``` ### Positional Arguments #### Basic args->opts Map positional arguments to named options: ```clojure (cli/parse-opts ["deploy" "production"] {:args->opts [:action :env]}) ;;=> {:action "deploy" :env "production"} ``` #### Variable Length Collections Use `repeat` for collecting remaining args: ```clojure (cli/parse-opts ["build" "foo.clj" "bar.clj" "baz.clj"] {:args->opts (cons :cmd (repeat :files)) :coerce {:files []}}) ;;=> {:cmd "build" :files ["foo.clj" "bar.clj" "baz.clj"]} ``` #### Mixed Options and Arguments ```clojure (cli/parse-opts ["--verbose" "deploy" "prod" "--force"] {:coerce {:verbose :boolean :force :boolean} :args->opts [:action :env]}) ;;=> {:verbose true :action "deploy" :env "prod" :force true} ``` ### Validation #### Required Options ```clojure (cli/parse-args ["--name" "app"] {:require [:name :version]}) ;; Throws: Required option: :version ``` #### Restricted Options ```clojure (cli/parse-args ["--verbose" "--debug"] {:restrict [:verbose]}) ;; Throws: Unknown option: :debug ``` #### Custom Validators ```clojure (cli/parse-args ["--port" "0"] {:coerce {:port :long} :validate {:port pos?}}) ;; Throws: Invalid value for option :port: 0 ;; With custom message (cli/parse-args ["--port" "-1"] {:coerce {:port :long} :validate {:port {:pred pos? :ex-msg (fn [{:keys [option value]}] (str option " must be positive, got: " value))}}}) ;; Throws: :port must be positive, got: -1 ``` ### Default Values Provide defaults via `:exec-args`: ```clojure (cli/parse-args ["--port" "9000"] {:coerce {:port :long} :exec-args {:port 8080 :host "localhost"}}) ;;=> {:opts {:port 9000 :host "localhost"}} ``` ### Error Handling Custom error handler: ```clojure (defn error-handler [{:keys [type cause msg option]}] (when (= type :org.babashka/cli) (println "Error:" msg) (when option (println "Option:" option)) (System/exit 1))) (cli/parse-args ["--invalid"] {:restrict [:valid] :error-fn error-handler}) ``` Error causes: - `:restrict` - Unknown option - `:require` - Missing required option - `:validate` - Validation failed - `:coerce` - Type coercion failed ### Subcommand Dispatch #### dispatch Route execution based on subcommands: ```clojure (defn deploy [opts] (println "Deploying to" (:env opts))) (defn rollback [opts] (println "Rolling back" (:version opts))) (def table [{:cmds ["deploy"] :fn deploy :args->opts [:env]} {:cmds ["rollback"] :fn rollback :args->opts [:version]} {:cmds [] :fn (fn [_] (println "No command specified"))}]) (cli/dispatch table ["deploy" "production"]) ;; Prints: Deploying to production (cli/dispatch table ["rollback" "v1.2.3"]) ;; Prints: Rolling back v1.2.3 ``` #### Nested Subcommands ```clojure (def table [{:cmds ["db" "migrate"] :fn db-migrate} {:cmds ["db" "rollback"] :fn db-rollback} {:cmds ["db"] :fn (fn [_] (println "db requires subcommand"))}]) (cli/dispatch table ["db" "migrate" "--env" "prod"]) ``` #### Dispatch Options Pass options to parse-args: ```clojure (cli/dispatch table args {:coerce {:port :long} :exec-args {:host "localhost"}}) ``` The `:fn` receives enhanced parse-args result: - `:dispatch` - Matched command path - `:args` - Remaining unparsed arguments - `:opts` - Parsed options - `:cmds` - Subcommands ### Formatting & Help #### format-opts Generate help text from spec: ```clojure (def spec {:port {:desc "Port to listen on" :default 8080 :coerce :long} :host {:desc "Host address" :default "localhost" :alias :h} :verbose {:desc "Enable verbose output" :alias :v}}) (println (cli/format-opts {:spec spec})) ;; Output: ;; --port Port to listen on (default: 8080) ;; --host, -h Host address (default: localhost)
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub