2024 年 Clojure 调查问卷! 分享你的想法。

欢迎!请查看 关于 页面,了解有关如何使用本站的更多信息。

+1 投票

这是一个修辞问题,因为我知道 tools.cli 无法对位置参数做任何事情,而只是将它们作为字符串向量传递给库的消费者。但我将分享我的用例。

我正在编写一个工具,该工具可以将文件从一个目录复制到另一个目录。它接受两个位置参数,即源和目标。目前我的代码包含两次输入验证和解析,首先是使用 tools.cli 进行选项,然后是使用我自己的函数 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})))

2 个答案

+1 投票

作为 tools.cli 的维护者,我将考虑这个问题,并决定是否为此创建一个 JIRA 问题。

大多数使用 tools.cli 的程序最终都需要一些用于帮助/使用的样板代码,以及一些额外的参数解析和/或验证,因此如果可以以相当简单的方式进行增强,这将有助于“每个人”。

需要解决的问题之一是,指定选项的格式仅适用于实际选项(即以 --- 开头)因此目前没有任何地方可以“挂载”任何自由文本参数处理。

你觉得这能节省你多少工作量吗?

位置参数带来了可选参数、序列、键值对等挑战。也许“短划线选项”就像是那条小溪中的更多鱼儿,就像“find”和“unzip”那样。Clojure Spec 已经照亮了那条路径。也许你可以将 Spec 整合到 tools.cli 扩展中。

(或者放弃使用 --src 和 --dest!)

...