2024 年 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面,了解更多有关此操作的信息。

0
工具 CLI

我有一个程序,它在 CLI 中接受一些选项,同时我也允许将它们指定在配置文件中。这样,我们就可以不必在所有调用中都传递 --quiet,而是可以将 {quiet true} 放入 .splint.edn 中,以自动启用它。有时通过传递 CLI 中的选项来覆盖配置文件是有价值的,这样在构建选项映射时,我首先加载配置文件,然后合并 CLI 选项:(merge local-config cli-options)

然而,如果在 tools.cli 规范中指定了一个默认值,我会失去这种行为,因为默认选项总是在 CLI 选项映射中,所以它会无条件地覆盖配置文件。

我已经开始从我的 tools.cli 规范中省略 :default 键,而是在选项描述字符串中只是简单地写 "默认为 true。"。例如,[nil "--[no-]parallel" "并行运行 splint。默认为 true。"] 然后稍后 (get config :parallel true) 然后稍后 (merge local-config cli-options)。这意味着我的总结没有显示格式化的 FALSE。(例如,--[no]-parallel FALSE 并行运行 splint。

关于这个小小的棘手问题,我想出了一些解决方案的想法(除了“你已经解决了,什么也不做!”之外)
1) 使 cli/parse-opts 返回一个额外的键,类似于 :defaults。它将是一个序列或集合,其中包含使用默认值的选项。这样,我可以添加一些逻辑,例如:(apply merge (select-keys cli-options defaults) local-config (apply dissoc cli-options defaults))
2) 在 cli/parse-opts 规范中添加一个 :default-display,它将打印默认值,但不会将其添加到选项映射中。这将由用户(开发者)来确保它实际上被添加到选项映射或以某种方式使用。
3) 添加一些功能,允许在总结中指定默认值,但在映射中使用其他值。例如,--[no]-parallel FALSE 但映射得到 {:parallel :false}。这将使我能够根据需要选择正确的值。

非常感谢!

您可以通过几种方式在不修改 tools.cli 的情况下实现这一点。

如果配置文件是众所周知的,那么程序可以首先读取配置文件,并将其内容用作 CLI 的默认值。(从技术上讲,配置文件将是默认文件。)

如果配置文件是由命令选项设置的,或者帮助信息必须声明基本事实默认值而不是配置文件设置,则程序可以在一个不同的映射中声明默认值,并从这个映射中计算 CLI 定义和有效的选项设置:使用将默认值捆绑到 CLI 定义选项描述中的函数计算 CLI 定义,并通过按顺序合并默认映射、配置设置和 CLI 设置来计算有效的选项设置。
我不太确定我是否完全理解你所描述的代码路径。我在被接受答案下的评论中进行了更详细的说明,因为 `:default-fn` (在有些帮助下)将对我有效。如果你愿意分享,我很想了解更多关于你的想法。这听起来很有趣,但很难将抽象转换为实际代码。

1 个回答

+1

选择
 
最佳答案

我不太确定你想要做什么,但我认为 :default-fn 选项可能更适合你?

by
抱歉有些复杂,我可以简单解释一下。

我的程序可以将内容打印到标准输出。要检查是否应该这样做,它会查看上下文对象中的`:quiet`。`:quiet`的值按照以下逻辑确定

如果用户传递了`--quiet`,则`:quiet`为真。
否则,如果用户已在配置文件中设置了`quiet`,则`:quiet`为真。
否则`:quiet`为假。

我希望在`tools.cli`中的`--help`摘要中显示`false`的默认值,因为它格式很漂亮(如下所示)。

```
--[no-]quiet              false  不打印诊断信息,只显示摘要。
```

然而,通过在`cli-options`中添加`:default false`,`cli/parse-opts`无条件返回`{:options {:quiet false}}`,因此我不能确定用户是否提供了`--quiet`选项,或者`tools.cli`仅仅是返回了默认值。

再次尝试`:default-fn`,我认为它应该可以工作,但是文档中没有任何使用示例,这就是为什么我之前没有成功。也许一些示例会有助于未来的其他人。

以下是如何`:default-fn`与`:default`和传递的参数交互的演示,供有相同请求的其他人

```
(def cli-options
  [[nil "--[no-]quiet" "不打印诊断信息,只显示摘要。"]
    :default false
    :default-fn (fn [v] (prn :default-fn v) :new-val)]])

(defn validate-opts
  [args]
  (let [{:keys [options]} (cli/parse-opts args cli-options)]
    (prn :options options)))
```

```
$ clojure -M:run
:default-fn {:quiet false}
:options {:quiet :new-val}

$ clojure -M:run --quiet
:options {:quiet true}

$ clojure -M:run --no-quiet
:options {:quiet false}
```
by
我忘了正式提出,所以如果你接受pull requests,我可以写几个示例。
by
contrib 库不接受拉取请求。我将为此创建一个 JIRA,如果你已签署 CLA,可以提供一段补丁代码。

如果你不想这么正式,可以在 Slack 上向我提出对文档更改的建议,我会根据这些建议更新 README 文件 :)
关于这件事,README 已经说了:













我即将加入以下内容:


我已经阅读了,但我发现它相当紧凑。将此段落与 README 中上面列出的规范各个部分的多个示例进行比较。

我将尝试将其改为更易阅读。
...