用gum给IRedis增加数据源选择能力

用gum给IRedis增加数据源选择能力

gum 是一个很有趣的“胶水”工具,可以方便地为 shell 脚本提供交互能力,本文以整体IRedis为例展示其使用方法

·

2 min read

前言

gum 是一个命令行工具, 它可以方便地为脚本提供TUI 交互能力。 本文以扩展 IRedis 为例,展示了 gum 的使用方法。

问题

IRedis 是一个非常好用的 redis 命令行客户端, 它提供很多方便实用的功能(语法高亮,自动完成等)

要连接到指定数据源 , 只要执行以下命令:

iredis --url 'redis://usr:passwd@foo-bar.com:6379?db=0'

但工作中经常需要连接不同的数据源,每次都需要输入不同的地址很麻烦。得记住每个数据库的地址和密码。 如果不能为数据源设置别名,命令行历史也无助于缓解心智负担。

iredis --url 'redis://usr:passwd@server-1.com:6379/0'
iredis --url 'redis://usr:passwd@server-2.com:6379/2'
iredis --url 'redis://:auth@server-3.com:6379'
...

好在IRedis 支持把数据源保存到指定配置文件中( .iredisrc) 中,可以为数据指定别名, 其格式如下:

[alias_dsn]
dev=redis://localhost:6379/4
staging=redis://username:password@staging-redis.example.com:6379/1

有了 .iredisrc 文件之后, 就可以用 dsn 来连接不同的数据库了

iredis --dsn dev
iredis -d staging

虽然这样有助于降低心智负担,但还是有点不方便: 如果忘记了dsn 的准确名字, 还是无法快速完成连接。

如果能有从 iredisrc 读取数据源列表供用户选择, 无疑可以提高效率并降低心智负担。要达成这个目标, 可以分两个步骤:

  1. 解析别名

  2. 用 gum 提供列表选择并调用iredis

解决方案

先说解析别名

要解析.iredisrc 这个 ini 格式的文件, 最简单的办法是使用python 脚本:

import configparser
import os
config = configparser.ConfigParser()
config.read(os.path.expanduser('~/.iredisrc')) # read ini file
for key, _ in config.items('alias_dsn'):
  print(key) # print all key in alias_dsn

上述脚本解析ini 文件,并打印出 alias_dsn 下的所有别名。

执行此脚本即可打印所有别名:

> python3 iredis.py
dev
staging

用gum提供选择能力

这时 gum 就可以出场了。结合前面写好的python脚本, 先读取别名列表, 用 gum filter 作选择, 然后用iredis打开选取的dsn

#!/usr/bin/env sh
DSN=$(python3 iredis.py | gum filter) # choose alias
iredis -d $DSN

最终效果如下:

更多思考

其实这个模式可以应用到所有类似场景。

例如,usql 这个数据库 cli 几乎支持所有RDBMS, 在日常使用中也存在同样的问题。 而 usql 又不像 iredis, 它不支持在配置文件中保存数据源。

这时需要以某种形式来表达别名与数据源的对应关系, 然后传递给gum 进行选择。 遗憾的是 gum 目前不支持传入map 进行选择(虽然很久以前就有用户提出过这个需求, 但被开发团队拒绝掉了)。

不过我们可以用其中提到的思路,用shell 来达成目标:

#!/usr/bin/env sh

# define db alias map
DBMAP=$(cat <<END
dev => pg://user:pass@localhost/dbname?sslmode=disable
staging => mysql:/var/run/mysqld/mysqld.sock
prod => sqlserver://user:pass@remote-host.com/dbname
END)

# choose alias
ALIAS=$(echo "$DBMAP" | awk -F ' => ' '{print $1}' | gum filter)

# grep dsn
DSN=$(echo "$DBMAP" | grep "$ALIAS =>" | awk -F ' => ' '{print $2}')

# open db
usql $DSN

这样,我们就拥行了一个可以连接任何RDBMS的统一cli 客户端,如需连接其它数据库,只需要在脚本中增加一行即可

结论

有了 gum 的帮助, 我们可以方便地为任何 cli 程序增加 TUI 交互能力,增加其易用性。本文只是展示了 gum 的多项强大功能中的一项, 如有兴趣, 可以到 gum 官网了解更多。