AIP-2602
参数依赖的选项
在设计CLI命令时,一个常见的场景是,对应于某个概念性操作的命令可能会根据特定参数的值采取不同的、大部分不重叠的选项。
例如,假设我们正在设计一个新的gcloud界面来管理图像,并且需要一个命令来将图像格式化为JPEG、GIF或PNG。无论图像格式如何,该命令都需要源文件和目标文件的选项,但除此之外,根据格式的不同,将适用完全不同的选项集。例如,JPEG可能会采用平滑、子采样和DCT方法的选项,这些选项仅适用于JPEG图像。另一方面,GIF可能会采用控制动画GIF的选项,例如是否无限循环以及帧之间的延迟时间。最后,PNG可能会采用颜色类型和每通道位数的选项。
指导
当特定参数的选项相对于其他选项较多时,为该操作创建一个命令组,并以每个参数值命名单独的子命令。在上面的示例中,我们将创建一个`gcloud images format`命令组,其中包含名为`jpeg`、`gif`和`png`的子命令。这些子命令可以接受它们自己的格式特定标志。
示例用法:
``` $ gcloud images format jpeg –help
$ gcloud images format jpeg –source-file=foo –destination-file=bar \ –dct-method=integer –smoothing=0.1 –subsampling=4:4:4
$ gcloud images format png –source-file=foo –destination-file=bar \ –color-type=0 –bits-per-channel=16
$ gcloud images format gif –source-file=foo –destination-file=bar \ –loop-forever –frame-delay=1ms ```
随着时间的推移,可能会添加越来越多的对所有参数都通用的选项。在这种情况下,使用一个接受参数值的单一命令可能更有意义。这可以通过将参数设置为位置参数来实现,而不会破坏向后兼容性。在上面的示例中,这将涉及将`format`从命令组更改为命令,并使其接受一个位置图像格式参数,该参数可以是`jpeg`、`gif`或`png`之一。请注意,所有上述示例命令仍然可以相同地运行(除了第一个命令,但由于它只影响帮助文本,因此不被视为破坏性更改)。
考虑的替代方案
设计此类命令还有其他几种可能性,概述如下:
### 单一命令,带有对应于参数的显式标志
在示例中,这将涉及一个`–type`标志来指定图像格式:
``` $ gcloud images format –source-file=source –destination-file=dest \ –type=JPEG –dct-method=integer –smoothing=0.1 –subsampling=4:4:4
$ gcloud images format –source-file=source –destination-file=dest \ –type=GIF –loop-forever –frame-delay=1ms
$ gcloud images format –source-file=source –destination-file=dest \ –type=PNG –color-type=0 –bits-per-channel=16 ```
从概念上讲,只使用一个格式命令最有意义。然而,这种方法有几个缺点:
- 不必要的帮助文本。用户将看到所有格式特定的选项,其中大多数将无关紧要,因为它们适用于不同的格式。在图形图像编辑程序(如Photoshop或GIMP)中,一旦用户从下拉菜单中选择所需的格式,UI可以选择性地显示这些格式特定的选项。然而,在CLI上,我们没有这种能力,因为帮助文本是静态生成的。
- 需要额外的验证逻辑。由于某些选项在格式不同时无效,命令作者需要确保指定无效组合时返回适当的错误。虽然这可以通过适当嵌套的互斥组来实现,但嵌套有可能变得过于深和复杂。
### 多个命令,以操作名称与参数值连字符命名
在示例中,这将如下所示:
``` $ gcloud images format-jpeg … $ gcloud images format-gif … $ gcloud images format-png … ```
这与推荐的设计类似,因为每个参数值都有自己的命令。然而,存在以下缺点:
- 向后兼容性。如果将来希望将参数值作为单一命令的参数,这将需要进行破坏性更改。
- 从命令树布局的角度来看,它不太优雅。将特定参数的命令分组到一个命令组中,允许自然分解命令空间,符合gcloud的CLI设计理念,并允许在帮助文本和自动完成中进行渐进式披露。