前端切图的时候,你是不是经常在 HEX、RGB、HSL 之间来回换算?打开浏览器控制台、点开 ColorZilla,或者搜个在线工具——其实完全没必要。
今天用 OpenCode 花 4 分钟写一个命令行颜色格式互转工具。输入任意一种颜色格式,立刻输出全部三种格式,外加终端里的 ANSI 色块预览。纯 Python 实现,代码不到 90 行。
技术栈:Python 3 + argparse + colorsys(标准库,零依赖)。
打开终端,进入工作目录,对 OpenCode 说:
我的提示词:
> 帮我写一个 Python 命令行颜色格式互转工具,支持 HEX(如 #ff5733)、RGB(如 255 87 51)和 HSL(如 12 85 60)三种颜色格式。用 argparse 解析参数,如果是 HEX 输入就转成 RGB 和 HSL,如果是 RGB 输入就转成 HEX 和 HSL,以此类推。
OpenCode 做了什么:
OpenCode 自动创建了 color.py,引入了 argparse 和标准库的 colorsys 模块,用 add_mutually_exclusive_group 确保了用户一次只输入一种格式。核心转换逻辑不到 30 行就搞定了。
它甚至还写了输入校验——RGB 三个值如果超出 0-255 范围会报错。
关键要点:
colorsys.rgb_to_hls 是 Python 标准库自带的,不需要 pip 装任何东西。注意它的返回值顺序是 HLS 不是 HSL,S 和 L 刚好反了,这是个常见坑。argparse 的互斥组处理 --hex、--rgb、--hsl 三个互斥参数是最干净的方案。运行 python color.py --hex ff0 发现报错了,因为工具只支持 6 位 HEX。但 CSS 里 #RGB 是合法的简写形式(#ff0 等于 #ffff00)。
我的提示词:
> #RGB 这种 3 位短格式的 HEX 现在不能识别,帮我加上对短格式的支持。#f0f 应该等价于 #ff00ff。
OpenCode 的响应:
OpenCode 在 hex_to_rgb 函数里加了三行代码:检测输入长度为 3 时,把每个字符复制一份变成 6 位。比如 f0f → ff00ff,然后再走原来的 6 位解析逻辑。
改动很小但很关键——这就是用 OpenCode 的体验:你发现一个边界情况,一句话告诉它,它立刻修,不需要自己翻文档查正则。
关键要点:
hex_to_rgb 函数里的 3 行,没有动其他逻辑。跑了几次感觉不错,但每次都得查 teal 的 HEX 是多少,不如直接支持颜色名。
我的提示词:
> 帮我加上对 CSS 颜色名的支持,比如 --css orange 就能直接转换。内置十几个常用颜色就行:red、green、blue、yellow、cyan、magenta、white、black、gray、orange、purple、pink、lime、navy、teal、maroon、olive、silver。
OpenCode 做了什么:
OpenCode 在文件顶部加了一个 CSS_COLORS 字典,把颜色名映射到 HEX 值。然后在 argparse 里加了一个 --css 参数,choices 直接用字典的 keys。这样 argparse 会自动校验输入是否在列表里,不在就直接报错并提示可用值。
$ python color.py --css orange
HEX: #ffa500
RGB: rgb(255, 165, 0)
HSL: hsl(39°, 100%, 50%)
████████
关键要点:
choices 参数让 argparse 自带了输入校验和帮助信息,不需要手写 if-else。现在转换结果已经很完整了,但还缺一个杀手级体验——在终端里直接看到颜色长什么样。
我的提示词:
> 输出结果里能不能加上一个 ANSI True Color 的色块预览?就是在终端里用彩色背景块展示转换后的颜色。
OpenCode 做了什么:
OpenCode 加了一个 ansi_preview 函数,用 ANSI 转义码 \033[48;2;R;G;Bm 设置 24 位背景色,后面跟 7 个空格作为色块,最后 \033[0m 重置。
然后在 print_result 里调用,在转换结果下方打印色块。
效果非常直观:
$ python color.py --css teal
HEX: #008080
RGB: rgb(0, 128, 128)
HSL: hsl(180°, 100%, 25%)
████████ ← 这是青色!
关键要点:
\033[48;2;R;G;Bm 是现代终端都支持的 True Color ANSI 序列,用 24 位色值直接设置背景色,和 HTML 的 background-color 一样精确。#!/usr/bin/env python3
"""颜色格式互转工具 — 支持 HEX / RGB / HSL 互相转换"""
import argparse
import sys
import colorsys
CSS_COLORS = {
"red": "#ff0000", "green": "#008000", "blue": "#0000ff",
"yellow": "#ffff00", "cyan": "#00ffff", "magenta": "#ff00ff",
"white": "#ffffff", "black": "#000000", "gray": "#808080",
"orange": "#ffa500", "purple": "#800080", "pink": "#ffc0cb",
"lime": "#00ff00", "navy": "#000080", "teal": "#008080",
"maroon": "#800000", "olive": "#808000", "silver": "#c0c0c0",
}
def hex_to_rgb(h: str):
h = h.lstrip("#")
if len(h) == 3:
h = "".join(c * 2 for c in h)
if len(h) != 6:
raise ValueError(f"无效的 HEX 值: #{h}")
return tuple(int(h[i : i + 2], 16) for i in (0, 2, 4))
def rgb_to_hex(r: int, g: int, b: int):
return f"#{r:02x}{g:02x}{b:02x}"
def rgb_to_hsl(r: int, g: int, b: int):
h, l, s = colorsys.rgb_to_hls(r / 255, g / 255, b / 255)
return round(h * 360), round(s * 100), round(l * 100)
def hsl_to_rgb(h: int, s: int, l: int):
r, g, b = colorsys.hls_to_rgb(h / 360, l / 100, s / 100)
return round(r * 255), round(g * 255), round(b * 255)
def ansi_preview(r: int, g: int, b: int):
return f"\033[48;2;{r};{g};{b}m \033[0m"
def print_result(r: int, g: int, b: int):
h, s, l = rgb_to_hsl(r, g, b)
hex_val = rgb_to_hex(r, g, b)
preview = ansi_preview(r, g, b)
print(f"\n HEX: {hex_val}")
print(f" RGB: rgb({r}, {g}, {b})")
print(f" HSL: hsl({h}°, {s}%, {l}%)")
print(f"\n {preview}\n")
def main():
parser = argparse.ArgumentParser(
description="颜色格式互转工具 — 输入任意格式,输出全部三种格式",
)
group = parser.add_mutually_exclusive_group()
group.add_argument("--hex", help="HEX 颜色值(支持 #RGB 和 #RRGGBB)")
group.add_argument(
"--rgb", nargs=3, type=int, metavar=("R", "G", "B"), help="RGB 值"
)
group.add_argument(
"--hsl", nargs=3, type=int, metavar=("H", "S", "L"), help="HSL 值"
)
group.add_argument(
"--css", choices=list(CSS_COLORS.keys()), help="CSS 颜色名称"
)
args = parser.parse_args()
if not any([args.hex, args.rgb, args.hsl, args.css]):
parser.print_help()
return
try:
if args.hex:
r, g, b = hex_to_rgb(args.hex)
elif args.rgb:
r, g, b = args.rgb
if not all(0 <= v <= 255 for v in (r, g, b)):
raise ValueError("RGB 值必须在 [0, 255] 范围内")
elif args.hsl:
h, s, l = args.hsl
if not (0 <= h <= 360 and 0 <= s <= 100 and 0 <= l <= 100):
raise ValueError("HSL: H∈[0,360], S∈[0,100], L∈[0,100]")
r, g, b = hsl_to_rgb(h, s, l)
elif args.css:
r, g, b = hex_to_rgb(CSS_COLORS[args.css])
print_result(r, g, b)
except ValueError as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
整个工具从无到有,用了 4 次对话、大约 4 分钟。最终代码 85 行,功能上覆盖了日常开发中 90% 的颜色转换需求。
对比传统开发方式:
colorsys 文档、确认 HLS 参数顺序——3 分钟手动写大概 20 分钟,用 OpenCode 省了 80% 的时间。而且中间加短 HEX 支持、CSS 颜色名、ANSI 预览这三个需求,在传统开发中都是"要不再开个 issue 下次再搞"的特性,但在 OpenCode 里就是一句话的事。
工具虽然小,但这个过程说明了 OpenCode 真正擅长的事:不是帮你写复杂的架构设计,而是把那些"想法一秒钟、实现十分钟"的小需求,变成真正的生产力工具。