这实际上是一个修辞问题,因为我已经了解到,tools.cli无法对位置参数执行任何操作,只是将它们作为字符串向量传递给库的使用者。但我会分享我的用例。
我正在编写一个工具,该工具将文件从一个目录复制到另一个目录。它接受两个位置参数,即源和目的地。目前我的代码包含两次输入验证和解码,第一次使用tools.li,然后是第二次使用自己的函数parse-arguments
。如果能将这两件事情一起完成会很好。
下面是使用示例代码。
(ns multi-machine-rsync.cli
(:require [clojure.tools.cli :as cli]
[clojure.java.io :as io]
[clojure.string :as string]))
(defn read-settings
[path]
(read-string (slurp path)))
(def cli-options
[["-h" "--help" "Show this help text"]
["-s" "--settings SETTING-FILE" "Path to the settings file."
:parse-fn read-settings
:default "settings.edn"]])
(defn usage
[options-summary]
(string/join
\newline
["Copies a directory from one place to another in a common"
"directory structure using multiple machines."
""
"Usage: multi-machine-rsync [OPTIONS] SOURCE DESTINATION"
""
"Options:"
options-summary]))
(defn parse-arguments
"Parse and validate command line arguments. Either return a map
indicating the program should exit (with a error message, and
optional ok status), or a map indicating the action the program
should take and the options provided."
[args]
(let [{:keys [arguments options errors summary]} (cli/parse-opts args cli-options)
[source destination] (map io/file arguments)]
(cond
(:help options) {:exit-message (usage summary) :ok? true}
errors {:exit-message errors}
(nil? source) {:exit-message "First positional argument SOURCE not given."}
(nil? destination) {:exit-message "Second positional argument DESTINATION not given."}
(not (.exists source)) {:exit-message "Source directory does not exist."}
(not (.exists destination)) {:exit-message "Destination directory does not exist."}
:else {:options options
:source source
:destination destination})))