与Golang的Cobra Cli一起自动完成和鸡尾酒混合
#go #cli #ux

Raftt,我们构建了一个开发工具,可以在Kubernetes Envs上轻松开发。使用RAFTT创建的开发环境可以与我们使用GO编程语言构建的CLI程序进行交互和控制。最近,我们添加了自动完成Dev Env中Kubernetes资源名称的功能。自动完成功能改善了我们的UX,使许多用户很高兴他们可以利用终端来自动完成资源名称,而不必将其输入。

在这篇文章中,我们说明了如何为使用Cobra编写的CLI工具实现自定义自动完成能力。我们首先使用Cobra浏览了一个小型mixologist应用程序的创建。调酒师应用程序是使用COBRA框架编写的CLI工具,该工具使用COBRA框架可以从成分列表中制作鸡尾酒,并使用自定义自动完成来改善用户体验。作为参考,可以在此处找到CLI应用程序的代码:https://github.com/rafttio/mixologist

这是mixologist CLI自动完成的示例:

Auto-completion of the mixologist app

然后,该帖子将介绍如何启用特定子命令的基本自动完成,最后如何实现自定义自动完成。该帖子结束时,简要讨论了Raftt CLI中如何使用此功能。

用眼镜蛇创建一个CLI实用程序

本段讨论了如何使用COBRA框架在GO编写的CLI工具中启用自动完成。它介绍了使用眼镜蛇,添加子命令并为该子命令实现基本自动完成的过程。然后,它解释了如何实现自定义自动完成以改善用户体验。

什么是眼镜蛇ð

眼镜蛇是一个用于创建强大的现代CLI应用程序的库。 https://github.com/spf13/cobra

您可能已经知道眼镜蛇了,如果您曾经在GO中写下CLI工具,但是对于少数人来说,本文包含有关如何使用它的简短介绍。

对于GO编写的CLI实用程序,Cobra是KubernetesGithub CLIHelmand many more的首选命令行包装纸。

在下一部分中,我们将使用cobra框架在GO中构建一个小应用程序。

调酒师应用程序

在此简介中,我们将创建一个mixologist应用程序。该应用将充当mixologist,可以从成分列表中制成鸡尾酒。

首先为我们的应用创建root命令:

// cmd/root.govar
rootCmd = &cobra.Command{
    Use: "mixologist",
    Short: "Mixologist is your personal bartender.",
    Long: `Mixologist acts as a bartender who specializes in cocktail making.`,
    RunE: func(cmd *cobra.Command, args []string) error {
        return cmd.Help()
    },
}
func Execute() {
    if err := rootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

rootCmd是我们mixologist应用程序的入口点,它打印了帮助和退出。如前所述,我们希望我们的mixologist混合鸡尾酒,以便我们添加sub命令mix。混音子命令将至少获得2个参数,由cobra.CommandArgs字段控制。

// cmd/mix.go
import (
    "github.com/spf13/cobra"
    "golang.org/x/exp/slices"
)
var mixCmd = &cobra.Command{
    Use:   "mix",
    Short: "make a cocktail.",
    Long:  `Mix some ingredients together to make a cocktail`,
    Args:  cobra.MinimumNArgs(2),
    RunE: func(cmd *cobra.Command, args []string) error {
        // Psuedo code
        if slices.IndexFunc(
            args, func(s string) bool { return s == "Vodka" }) > -1 &&
            slices.IndexFunc(
                args, func(s string) bool { return s == "Orange Juice" }) > -1 {
            fmt.Println("You can make a screwdriver cocktail!")
            return nil
        }
        return fmt.Errorf("i can't make a cocktail from %v", args)
    },
}
func init() {
    rootCmd.AddCommand(mixCmd)
}

现在,我们需要将它们全部绑在一起,以

package main
    
import (
  "{pathToYourApp}/cmd"
)

func main() {
  cmd.Execute()
}

通过使用正确的成分执行mixologist,它可以使我们成为伏特加螺丝刀!但是,如果我们弄错了成分,我们会遇到错误。

在下一段中,我们将演示如何利用cobra在终端中进行自动完成,并使用户更容易享受我们的应用程序。

基本自动完成

mixologist应用程序的用户可能会发现很难猜测可用的成分。如果在我们的酒吧中可用,我们应该通过使我们的CLI实用程序自动完成成分来更容易使用该应用程序。

要实现基本的自动完成,我们将设置命令的ValidArgs字段:

var availableIngredients = []string{
    "Vodka",
    "Gin",
    "Orange Juice",
    "Triple Sec",
    "Tequila",
    "simple syrup",
    "white rum",
    "Kahlua coffee liqueur",
}

var mixCmd = &cobra.Command{
    Use:   "mix",
    Short: "make a cocktail.",
    ValidArgs: availableIngredients,
    ...
}

现在,我们需要在外壳中安装自动完成,Cobra可以为bashzshfish外壳生成自动完成。选择外壳后,我们可以做:

./mixologist completion zsh > /tmp/completion
source /tmp/completion

然后,当我们键入mixologist [tab][tab]时,我们将获得自动完成的成分列表!

Auto-completion of ingredients for the mix subcommand

这真的很酷,但仍然不是最佳的,该命令可以自动填充成分,当混合在一起时不会制成任何鸡尾酒。我们只想在实际上可以与所有先前提到的成分结合时自动完成下一个成分。为了实现最佳的用户体验,我们需要实现自定义自动完成,我们将在下一段中看到如何做到这一点。

自定义自动完成

现在,我们的mixologist应用程序自动完成在mix子命令上的成分列表中的成分列表,但我们希望使其更聪明。

我们自以为是的调酒师认为,唯一可以与伏特加酒配对的是橙汁,因此,如果前面提到的成分是伏特加酒,我们希望我们的自动完成仅建议橙汁。我们也不想重复两次相同的成分,因此我们不会将Kahlua与Kahlua混合4次。

为了实现这一点,我们需要编辑mix子命令并使用Awesome koude22软件包以寻求帮助:

import "github.com/samber/lo"
var availableIngredients = []string{...}
var mixCmd = &cobra.Command{
    Use:   "mix",
    Short: "make a cocktail.",
    ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
        if len(args) == 1 && args[0] == "Vodka" {
            return []string{"Orange Juice"}, cobra.ShellCompDirectiveNoFileComp
        }
        _, unusedIngredients := lo.Difference(args, availableIngredients)
        return unusedIngredients, cobra.ShellCompDirectiveNoFileComp
    },
}

当我们使用tab两次使用mix子命令的自动完成时,终端将显示:

custom-auto-completing-igredients-gif

请注意,所选成分不再以后续自动完成的选项出现。

如果我们将Vokda作为第一个参数,然后按两次按tab,则终端将立即自动完成Orange Juice

custom-auto-comleting-ingredients-gif-2

新的自动完成改进了我们的mixologist应用程序的UX,并使我们的用户更加快乐。

现在,我们知道如何使用cobra框架实现自定义自动完成,我们将简单地讨论如何在raftt Cli中使用此功能。

自动完成Raftt µ

在Raftt CLI中,我们使用COBRA框架实现了自定义自动完成。此功能允许用户在与Raftt Dev环境中的资源进行交互时,可以轻松,快速输入有效的Kubernetes资源名称。通过自定义自动完成,用户可以仅选择有效的资源名称,改善整体用户体验并防止沮丧的错别字。

如果您遵循我们的教程here,则可以在将frontendrecommendations Services转换为开发模式时为自己尝试自动完成。写raftt dev [tab][tab],然后查看它列出了选项ð。紧密整合的自动完成为我们提供了快速而轻松的UX,而不必担心错别字。

如果您使用brewsnap安装了RAFTT,则在上面运行上面的source命令来安装完成的步骤。否则,将eval $(raftt completion <SHELL>)添加到壳的rc文件中。

表现

最后,我们应该简要介绍自动完成功能的效率,如果自动完成逻辑很复杂或取决于远程服务,则连续完成将很慢,并且会导致不良的用户体验。例如,当自动完成一长串Kubernetes资源时,通过反复按[tab][tab]组合来自动完成。为了减轻此问题,我们可以缓存复杂的自动完成逻辑的结果。

缓存自动完成结果引入了两个新问题:

  1. 结果存储在哪里? CLI本身仅运行一秒钟即可生成完成,并且不会粘住。我们可能会将它们放在磁盘上,但这意味着一次与多个登录器打交道,锁定等。Raftt具有启动的守护程序,很自然地缓存结果。

  2. 过时的信息。如果我们的缓存太长,我们可能会提供不正确的信息。例如,如果此后删除了Kubernetes资源。我们以3秒的合理持续时间定居。

总而言之,使用眼镜蛇为CLI工具实施自定义自动完成,可以极大地改善用户体验,并使工具更有效地使用。通过遵循本文中概述的步骤,您可以将此功能添加到自己的基于GO的CLI工具中。借助自动完成,用户可以更轻松地与工具进行导航和交互,从而减少错误并改善整体体验。感谢您自动完成这篇文章ð

可以在此处找到调酒师应用程序的代码:https://github.com/rafttio/mixologist

如果您对Raftt如何帮助您在本地或远程Kubernetes群集中有效发展我们的教程here