简体   繁体   中英

How to parse command line arguments in `clojure` using `tools.cli` in better way?

I'm newbie in clojure . I'm learning about parsing arguments using tools.cli library. Here is my code:

  1 (ns json.core
  2   (:import
  3     (com.fasterxml.jackson.core JsonParseException))
  4   (:require
  5      [cheshire.core :as c]
  6     [clojure.tools.cli :refer [parse-opts]])
  7   (:gen-class))
  8 
  9 (def json-cli-options
 10   [["-j" "--jsonfile INFILE"  :default false]
 11    ["-d" "--data JSON-DATA" :default false]])
 12 
 13 (defn -main
 14   [& args]
 15   (case (first args)
 16     "parsejson" (let [{:keys [jsonfile data]} (get (parse-opts (rest args) json-cli-options) :options)
 17                   file-json (if jsonfile (try (c/parse-string (slurp jsonfile))
 18                                               (catch JsonParseException e (println "Invalid file"))))
 19                   data-json (if data (try (c/parse-string data)
 20                                            (catch JsonParseException e (println "Invalid data"))))
 21                   complete-json (merge file-json data-json)]
 22                   (if (and (not data) (not jsonfile)) (do (println "Pass either json-data or json-file or both") (System/exit 1)))
 23                   (println complete-json))
 24     (println "No argument passed")))

It's just a code for paring json data. User can pass json either using --jsonfile or --data or both . User must have to select at least one option, otherwise It will thrown an error. It's like this:

$ lein run parsejson --jsonfile file.json
;;=> {Name Bob, Gen Male}

$ lein run parsejson --data '{"age":21}'
;;=> {age 21}

$ lein run parsejson --jsonfile file.json --data '{"age":21}'
;;=> {Name Bob, Gen Male, age 21}

$ lein run parsejson 
;;=>Pass either json-data or json-file or both

But this code is not thrown an error in this case:

$ lein run parsejson --jsonfile file.json --data

I want to implement this feature as well. If I do this:

$ lein run parsejson --jsonfile file.json --data
$ lein run parsejson --data '{"age":21}' --jsonfile

The code should give some message(or error). How can I implement this thing in my code? Please give your suggestion. Thanks.

as my old code follow tools.cli doc, it will save all into a map.

(defn -main
  ""
  [& args]
  (let [[options extra-args banner]
        (cli args
             ["-j" "--jsonfile" "json file"]
             ["-d" "--data" "json data"]
             ["-h" "--help" "Show help" :default false :flag true]
             ["-v" "--verbose" "debug mode" :default false :flag true])]

    (println options)
    (when (:help options)
      (println banner)
      (System/exit 0))))

out res: --jsonfile 1.json --data '{"age":21}' -h

{:help true, :verbose false, :jsonfile 1.json, :data {"age":21}}
Usage:

 Switches                     Default  Desc       
 --------                     -------  ----       
 -j, --jsonfile                        json file  
 -d, --data                            json data  
 -h, --no-help, --help        false    Show help  
 -v, --no-verbose, --verbose  false    debug mode

You should be validating the values passed after each flag. See here for an example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM