cobra 开启自动补全功能

2023-11-13

cobra 开启自动补全功能

因工作原因,需要将一个由 cobra 写的命令行工具,支持在 bash 和 zsh 环境开启命令行自动补全功能。网上搜了一圈,大部分都是把 cobra github 的介绍翻译一下就完了。而且没有对命令行补全的功能进行讲解。所以就写一篇文章补充一下。

前提

  • 初始化 cobra 项目:
mkdir sulenn-cobra && cobra init --pkg-name github.com/sulenn/sulenn-cobra
# 开启 go module
go mod init github.com/sulenn/sulenn-cobra
# 修改文件名
mv main.go sulenn-cobra.go
  • 添加若干命令
cobra add serve
cobra add create
cobra add hello
cobra add completion
  • 查看命令
# 编译
 go build sulenn-cobra
 # 查看 help
 > ./main -h
 
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  sulenn-cobra [command]

Available Commands:
  completion  A brief description of your command
  create      A brief description of your command
  hello       A brief description of your command
  help        Help about any command
  serve       A brief description of your command

Flags:
      --config string   config file (default is $HOME/.sulenn-cobra.yaml)
  -h, --help            help for sulenn-cobra
  -t, --toggle          Help message for toggle

Use "sulenn-cobra [command] --help" for more information about a command.

开启命令行自动补全

开启 bash 命令行自动补全

  • 修改 completion.go 文件内容:
/*
Copyright © 2020 sulenn <273409891@qq.com>
This file is part of CLI application foo.
*/
package cmd

import (
	"github.com/spf13/cobra"
	"os"
)

// completionCmd represents the completion command
var completionCmd = &cobra.Command{
	Use:                   "completion [bash|zsh]",
	Short:                 "Generate completion script",
	Long: `To load completions:

Bash:

$ source <(yourprogram completion bash)

# To load completions for each session, execute once:
Linux:
  $ yourprogram completion bash > /etc/bash_completion.d/yourprogram
MacOS:
  $ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram

Zsh:

$ source <(yourprogram completion zsh)

# To load completions for each session, execute once:
$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
`,
	DisableFlagsInUseLine: true,
	ValidArgs:             []string{"bash", "zsh"},
	Args:                  cobra.ExactValidArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		switch args[0] {
		case "bash":
			cmd.Root().GenBashCompletion(os.Stdout)
		case "zsh":
			cmd.Root().GenZshCompletion(os.Stdout)
		}
	},
}

func init() {
	rootCmd.AddCommand(completionCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// completionCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// completionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

  • 开启补全
# 编译
go build main.go
# bash 环境下执行
./sulenn-cobra completion bash > cobra_completion && sudo mv cobra_completion /etc/bash_completion.d/
  • 重开 bash 即可使用命令行自动补全

开启 zsh 命令行自动补全

  • 修改 completion.go 文件内容:
/*
Copyright © 2020 sulenn <273409891@qq.com>
This file is part of CLI application foo.
*/
package cmd

import (
	"bytes"
	"fmt"
	"github.com/spf13/cobra"
	"io"
	"os"
)

// completionCmd represents the completion command
var completionCmd = &cobra.Command{
	Use:                   "completion [bash|zsh]",
	Short:                 "Generate completion script",
	Long: `To load completions:

Bash:

$ source <(yourprogram completion bash)

# To load completions for each session, execute once:
Linux:
  $ yourprogram completion bash > /etc/bash_completion.d/yourprogram
MacOS:
  $ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram

Zsh:

$ source <(yourprogram completion zsh)

# To load completions for each session, execute once:
$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
`,
	DisableFlagsInUseLine: true,
	ValidArgs:             []string{"bash", "zsh"},
	Args:                  cobra.ExactValidArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		switch args[0] {
		case "bash":
			cmd.Root().GenBashCompletion(os.Stdout)
		case "zsh":
			err := runCompletionZsh(os.Stdout, cmd.Root())
			if err != nil {
				fmt.Printf("completion for zsh failed: %v\n", err)
				return
			}
		}
	},
}

func init() {
	rootCmd.AddCommand(completionCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// completionCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// completionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func runCompletionZsh(out io.Writer,cmd *cobra.Command) error {
	zshHead := "#compdef kubectl\n"

	_, err := out.Write([]byte(zshHead))
	if err != nil {
		return err
	}

	zshInitialization := `
__kubectl_bash_source() {
	alias shopt=':'
	emulate -L sh
	setopt kshglob noshglob braceexpand

	source "$@"
}

__kubectl_type() {
	# -t is not supported by zsh
	if [ "$1" == "-t" ]; then
		shift

		# fake Bash 4 to disable "complete -o nospace". Instead
		# "compopt +-o nospace" is used in the code to toggle trailing
		# spaces. We don't support that, but leave trailing spaces on
		# all the time
		if [ "$1" = "__kubectl_compopt" ]; then
			echo builtin
			return 0
		fi
	fi
	type "$@"
}

__kubectl_compgen() {
	local completions w
	completions=( $(compgen "$@") ) || return $?

	# filter by given word as prefix
	while [[ "$1" = -* && "$1" != -- ]]; do
		shift
		shift
	done
	if [[ "$1" == -- ]]; then
		shift
	fi
	for w in "${completions[@]}"; do
		if [[ "${w}" = "$1"* ]]; then
			echo "${w}"
		fi
	done
}

__kubectl_compopt() {
	true # don't do anything. Not supported by bashcompinit in zsh
}

__kubectl_ltrim_colon_completions()
{
	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
		# Remove colon-word prefix from COMPREPLY items
		local colon_word=${1%${1##*:}}
		local i=${#COMPREPLY[*]}
		while [[ $((--i)) -ge 0 ]]; do
			COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
		done
	fi
}

__kubectl_get_comp_words_by_ref() {
	cur="${COMP_WORDS[COMP_CWORD]}"
	prev="${COMP_WORDS[${COMP_CWORD}-1]}"
	words=("${COMP_WORDS[@]}")
	cword=("${COMP_CWORD[@]}")
}

__kubectl_filedir() {
	# Don't need to do anything here.
	# Otherwise we will get trailing space without "compopt -o nospace"
	true
}

autoload -U +X bashcompinit && bashcompinit

# use word boundary patterns for BSD or GNU sed
LWORD='[[:<:]]'
RWORD='[[:>:]]'
if sed --help 2>&1 | grep -q 'GNU\|BusyBox'; then
	LWORD='\<'
	RWORD='\>'
fi

__kubectl_convert_bash_to_zsh() {
	sed \
	-e 's/declare -F/whence -w/' \
	-e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \
	-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
	-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
	-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
	-e "s/${LWORD}_filedir${RWORD}/__kubectl_filedir/g" \
	-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__kubectl_get_comp_words_by_ref/g" \
	-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__kubectl_ltrim_colon_completions/g" \
	-e "s/${LWORD}compgen${RWORD}/__kubectl_compgen/g" \
	-e "s/${LWORD}compopt${RWORD}/__kubectl_compopt/g" \
	-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
	-e "s/\\\$(type${RWORD}/\$(__kubectl_type/g" \
	<<'BASH_COMPLETION_EOF'
`
	_, err = out.Write([]byte(zshInitialization))
	if err != nil {
		return err
	}

	buf := new(bytes.Buffer)
	err = cmd.GenBashCompletion(buf)
	if err != nil {
		return err
	}

	_, err = out.Write(buf.Bytes())
	if err != nil {
		return err
	}

	zshTail := `
BASH_COMPLETION_EOF
}

__kubectl_bash_source <(__kubectl_convert_bash_to_zsh)
`
	_, err = out.Write([]byte(zshTail))
	if err != nil {
		return err
	}

	return nil
}
  • 开启补全
# 编译
go build main.go
# zsh 环境下执行
./sulenn-cobra completion zsh > ~/.cobra-completion.sh && echo 'source ~/.cobra-completion.sh' >> ~/.zshrc
  • 重开 zsh 即可使用命令行自动补全

zsh 环境下的命令行自动补全参考了 Kubernets 的实现。原理就是将 bash 生成的脚本转换成 zsh 兼容的格式

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cobra 开启自动补全功能 的相关文章

  • 运行最新版本时没有“最新”消息?

    我正在尝试使用Sparkle https sparkle project org与 Qt Go 的绑定 https github com therecipe qt app 闪光 m import
  • 如何使用 go1.6.2 构建 linux 32 位

    有没有任何组合GOARCH and GOOS我可以设置哪些值来构建 ELF 32 位二进制文 件 GOOS linux and GOARCH 386 更多示例 架构 32 bit gt GOARCH 386 64 bit gt GOARCH
  • 如何通过在切片上查找来从切片复制到数组

    我正在编写一个库来处理二进制格式 我有一个带有数组变量的结构 我想保留它以用于文档目的 我还需要从输入字节片中查找和判断 一些伪代码 type foo struct boo 5 byte coo 3 byte func main input
  • Go 指针 - 通过指针将值附加到切片

    我有一个 struct ProductData 及其实例 p 它有一个切片属性 type ProductInfo struct TopAttributes map string interface 我想设置 TopAttributes 如下
  • 管理多租户 ArangoDB 连接

    我使用 ArangoDB Go 使用 go driver 并且需要实现多租户 这意味着每个客户都将在单独的数据库中拥有他的数据 我想要弄清楚的是如何使这种多租户发挥作用 我知道为每个请求创建一个新的数据库连接是不可持续的 这意味着我必须维护
  • 共享 GOPATH 的良好做法是什么?

    我刚刚开始学习 Go 并阅读现有代码以了解 其他人是如何做的 在这样做时 go 工作空间 的使用 特别是当它与项目的依赖项相关时 似乎无处不在 在处理各种 Go 项目时 使用单个或多个 Go 工作区 即 GOPATH 的定义 的常见最佳实践
  • 使用生成的 Golang DLL 返回字符串或 *C.Char

    我一直在努力追随z505 goDLL https github com z505 goDLL回购并遇到了一个大问题 该方法无法返回字符串 我无法读取结果的输出变量 这是我到目前为止使用的代码 Go 完整代码https play golang
  • 如何使用 exec.Command 在 golang 中执行 Mysql 脚本

    您好 我正在尝试执行一个脚本以使用 Golang 将数据填充到数据库中 func executeTestScript cmd exec Command usr local mysql bin mysql h127 0 0 1 P3333 u
  • golang 中 *(*int)(nil) = 0 是什么意思?

    我注意到有一行 int nil 0在功能上throw https github com golang go blob master src runtime panic go L1113 go nosplit func throw s str
  • Golang http 写入响应,无需等待完成

    我正在构建一个应用程序 该应用程序构建 pdf 文件并在收到请求时将其返回给客户端 由于其中一些 pdf 文件可能需要一些时间才能生成 我想在客户端运行时定期将某种状态更新发送回客户端 当完成 pdf 文件的构建后 它也应该返回给客户 类似
  • 在 OSX 上交叉编译 Go?

    我正在尝试在 OSX 上交叉编译 go 应用程序以构建适用于 Windows 和 Linux 的二进制文件 我已经阅读了网上能找到的所有内容 我发现的最接近的例子已经发布在 除了疯狂邮件列表上许多未完成的讨论之外 http solovyov
  • 无法在 Golang 中导入本地模块

    我正在尝试导入本地模块 但无法使用以下命令导入它go mod 我最初使用以下方式构建了我的项目go mod init github com AP Ch2 GOMS 注意我的环境是go1 14我使用 VSCode 作为我的编辑器 这是我的文件
  • 如何从 golang fyne 容器中删除对象

    我正在开发 GUI 应用程序 需要动态添加和删除 gui 元素 我想知道是否有办法从 golang fyne 容器中删除元素 在下面的示例代码中 我创建了容器并动态添加元素 现在我希望能够删除这些元素而不是隐藏它们 我尝试的一个 解决方案
  • 命名和未命名类型

    问题 我最近开始阅读Golang规格手册 https golang org ref spec并陷入试图理解的困境有名和无名类型在相关部分 https golang org ref spec Types 我来自动态语言 这让我有点头疼 手册指
  • 修改现有的yaml文件并添加新的数据和注释

    我最近看到了yaml https github com go yaml yaml tree v3lib 有新版本 V3 与nodes https github com go yaml yaml blob v3 yaml go L348功能
  • 是否可以在 Golang 中 pickle 结构实例

    我正在 Golang 中做一些机器学习 我现在碰壁了 我训练有素的分类器需要将近半分钟的时间来训练 并且想要保存分类器的该实例 这样我就不必每次都从头开始训练 在 Golang 中应该如何去做呢 仅供参考 我的分类器是一个结构 当我用 py
  • Golang 从管道读取读取大量数据

    我正在尝试读取一个正在被焦油化 流式传输到标准输入的存档 但我正在以某种方式读取far管道中的数据多于 tar 发送的数据 我像这样运行我的命令 tar cf somefolder my go binary 源代码是这样的 package
  • 在 Go 中解析 RFC-3339 / ISO-8601 日期时间字符串

    我尝试解析日期字符串 2014 09 12T11 45 26 371Z 在围棋中 该时间格式定义为 RFC 3339 日期时间 https datatracker ietf org doc html rfc3339 section 5 6
  • 将 []string 传递给需要可变参数的函数

    为了不一遍又一遍地重复我的自我 我想创建一个处理运行一些命令的函数 func runCommand name string arg string error cmd exec Command name arg if err cmd Run
  • java.lang.NoSuchMethodError:com.fasterxml.jackson.databind.type。使用 apache beam Spark runner 运行 go 示例时

    我想跑grades https github com apache beam tree master sdks go examples gradesapache beam go sdk 提出的示例 在一个主服务器和两个从服务器 spark2

随机推荐

  • C语言---离散数学实验--集合及二元关系的应用

    目录 集合的运算 题目要求 代码 等价关系的判定 题目要求 代码 N元关系 题目描述 代码 集合的运算 题目要求 一 集合的运算 1 用数组A B C E表示集合 输入数组A B E 全集 输入数据时要求检查数据是否重复 集合中的数据要求不
  • 网络安全和黑客技能:15本必读书籍推荐

    前言 网络安全和黑客技能紧密相连 想要有效地防范黑客攻击 了解黑客的技能和思维方式非常重要 而要想成为一名合格的白帽黑客 也需要深入理解网络安全的基本原理和最佳实践 本文将介绍15本网络安全和黑客书籍 既包括了防范黑客攻击的指南书籍 也包括
  • ubuntu配置VLAN的方法

    目录 前言 一 VLAN是什么 二 Ubuntu如何配置VLAN IP 1 依赖安装 2 创建VLAN 总结 前言 在做someip相关开发的时候需要使用到VLAN 这里介绍如何在ubuntu上创建VLAN 一 VLAN是什么 VLAN V
  • RFID技术的优势

    什么是RFID技术 RFID射频识别是一种非接触式的自动识别技术 它通过射频信号自动识别目标对象并获取相关数据 识别工作无须人工干预 可工作于各种恶劣环境 EFID技术可识别高速运动物体并可同时识别多个标签 操作快捷方便 短距离射频产品不怕
  • 性能测试总结

    性能调优是什么 我们为什么要进行性能调优 主要是由以下几个点来考虑 1 编写的新应用上线前在性能上无法满足需求 这个时候需要对系统进行性能调优 2 应用系统在线上运行后随着系统数据量的不断增长 访问量的不断上升 系统的响应速度通常越来越慢
  • object-fit和object-position实现图片原比例裁剪不拉伸适应

    img标签的图片设置width 100 height 211px 默认图片拉伸或压缩以适应此宽高 原有 但是这样太丑了 所以我们需要把图片裁剪一下 让它不拉伸以原有比例填充屏幕 首先使用到object fit这个属性 objtct fit
  • 【统计模拟及其R实现】逆变换 / 筛选法 / 合成法 上机习题答案(超详细)

    课本 统计模拟及其R实现 肖枝红 朱强 武汉大学出版社 参考课件 第三章 随机数 浙江大学数学科学学院 目录 1 逆变换法 2 筛选法 3 合成法 1 逆变换法 题目1 用逆变换方法生成如下密度函数的随机变量 要求写出R程序 Cauchy概
  • 基于python的端口扫描(升级版)

    今天给大家带来一个用python写的端口扫描小程序 需要借助一个python的库 Scapy是一个强大的Python库 用于构建和发送网络数据包 以及对网络进行各种类型的分析和操作 pip install scapy 通过Scapy 您可以
  • modbus详尽中文资料、软件、代码

    modbus详尽中文资料 软件 代码
  • linux bootarg 数组,Linux启动bootargs参数分析

    Linux启动bootargs参数分析 Written by leeming 这几天刚好在看linux c语言启动 现在就顺便把内核在启动时解析bootargs这一块单独拎出来讲解下 内核对于bootargs的解析分为几块 1 setup
  • linux下使用C语言操作MYSQL数据库(API使用libmysqlclient-dev)

    文章目录 运行环境 一 准备工作 1 在Ubuntu上准备mysql开发环境 2 创建测试数据库与表 二 建立与mysql的连接 1 在C文件中引入头文件 2 初始化mysql与数据库的通道 3 与mysql建立真实连接 三 添加操作 CR
  • java - 锁粒度

    最近工作有个需求 需要加锁保证操作的原子性 但在一定程度上我想着可以根据业务类型对锁进行细化 于是简单的写了一个demo进行验证 先来看看synchronized的demo import java util concurrent Concu
  • 光敏传感器实验报告_光敏传感器光电特性研究实验报告.docx

    光敏传感器光电特性研究实验报告 光敏电阻光敏特性的研究 一 实验设计方案 实验目的 1 了解光敏电阻的基本特性 测出它的光照特性曲线 2 学习使用电脑实测 3 学习使用DataStudio软件 4 学习了解设计性实验的基本方法 实验原理 光
  • tkinter美化窗口

    今天 小编给大家带来一个很常见的问题 如何美化tkinter窗口 相信用过IDLE的小伙伴都深有感受 IDLE同样使用Tcl Tk写的 别人写的是这样 我们写的却是这样 大家对比一下 tkinter写英文还算可以 但是一写中文 他的问题就凸
  • 速通AOSP,成功编译调试Android源码

    今日科技快讯 近日据不少网友反馈 爱奇艺App开始对投屏功能作出限制 之前黄金VIP会员支持最高4K清晰度投屏 现在只能选最低的480P清晰度 要想进行4K投屏必须购买白金VIP会员 不少网友表示 480P清晰度太低 几乎无法观看 作者简介
  • 初代AIGC明星独角兽,停摆在大模型元年

    唏嘘 AIGC方兴未艾 但国内AIGC领域的昔日龙头独角兽 正站在风雨飘摇的悬崖边 影谱科技 初代目AIGC明星公司 被爆已经面临经营不善 运营停摆的窘境 这家成立于2009年的AI影像公司 一直专注大文娱产业 曾在D轮融资时以13 6亿人
  • 计算机网络(六)-传输介质

    一 传输介质 1 1 传输介质也称传输媒体 传输媒介 它就是数据传输系统中在发送设备和接收设备之间的物理通路 1 2 传输媒体并不是物理层 传输媒体在物理层的下面 因为物理层是体系结构的第一层 因此有时称传输媒体为第0层 1 3 传输媒体中
  • Unity3d目录Resources与StreamingAssets文件夹的区别

    1 Resources文件夹 Resources文件夹是一个只读的文件夹 通过Resources Load 来读取对象 因为这个文件夹下的所有资源都可以运行时来加载 所以Resources文件夹下的所有东西都会被无条件的打到发布包中 建议这
  • 炸裂了!3分钟用GPT4做一个PPT!

    GPT4有多强了 相信体验过的同学都知道 一个字爽 无论是速度 还是数据集还是功能都比3 5要强大很多 现在越来越多的人开始用GPT4了 可以大幅的提高我们的工作和学习的效率 今天小编就用GPT4快速做一个PPT 分享给大家 分分钟搞定 1
  • cobra 开启自动补全功能

    cobra 开启自动补全功能 因工作原因 需要将一个由 cobra 写的命令行工具 支持在 bash 和 zsh 环境开启命令行自动补全功能 网上搜了一圈 大部分都是把 cobra github 的介绍翻译一下就完了 而且没有对命令行补全的