抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

五个字母,一次回车,终端里落下一场恰到好处的雨。tenki

起因

终端天气工具是一个存在了很久的品类。curl wttr.in 可能是每个人接触终端时最早学会的”有趣的命令”之一。后来陆续出现了各种本地客户端——Go写的、Rust写的、Python写的,有的走极简路线,有的走全屏动画路线。

它们都能用。但我始终觉得这个品类里缺少一个东西:设计感

不是那种”加更多功能”的完善,而是”认真想过每一个字符放在哪里”的完善。ASCII art的每一笔是否经过推敲?配色是随手挑的还是作为一个体系设计的?信息的排布有没有层次感?这些问题,在功能层面不重要,但在”每天要看一眼”的工具层面,很重要。

于是我做了tenki。

demo

产品设计

名字

tenki。天気。日语里”天气”的意思。

五个字母,好打。一个清晰的语义指向。发音轻快,像敲击键盘时两个手指的交替落下。

设计原则

我给这个项目定了四条原则。它们不是口号,而是每一个决策通过的滤网:

信息优先于装饰。 天气工具首先是工具。用户打开它,三秒内获取关键信息,然后关掉。如果一个设计元素不服务于信息传达,它就不应该存在。

有灵魂的ASCII。 如果值得用字符画来表现天气,就值得把每一个字符放到正确的位置上。云的轮廓该圆润就圆润,雨的斜线该细腻就细腻。

色彩即情绪。 晴天应该是暖的,雨天应该是冷的。不是通过文字告诉用户”现在是晴天”,而是通过颜色让用户感受到晴天。

开箱即用。 不需要API key,不需要配置文件,不需要注册账号。tenki 回车,天气就来了。

五种模式

一个天气工具在不同的使用场景下需要不同的形态。这不是功能堆砌,而是对真实需求的诚实回应。

Card模式 是默认形态。一张带圆角边框的信息卡片,左侧ASCII图,右侧数据,底部24小时温度趋势。它适合在终端间隙瞥一眼天气的场景——信息完整,视觉克制。

Compact模式 去掉了边框和趋势图,只留ASCII图和一行关键数据。适合终端空间紧张的时候。

Oneline模式 压缩到单行输出。它是给脚本和状态栏准备的——tmux的状态栏、shell的prompt、i3bar的自定义模块。

Fullscreen模式 把整个终端变成一幅天气场景——动态的雨丝、飘落的雪花、闪烁的星星。按Q退出。说实话它没有什么实用价值。但有时候你就是想看一会儿雨落下来的样子。

Showcase模式 是Fullscreen的克制版本,全屏展示5秒后自动退出。适合录屏和截图。

modes

六套主题

颜色是tenki的灵魂。每套主题不只是一组色号的替换,而是一种完整的视觉氛围。

default 是深色终端的默认主题。暖金色的温度数值,天空蓝的城市名,银灰色的辅助信息。它像一个设计良好的仪表盘——每个元素的颜色都在暗示它的层级。

default

light 为浅色终端设计。深色描边的ASCII art,高对比度的数据文字。

light

mono 是纯灰度主题。没有色相,只有明暗。它像黑白摄影——去掉颜色之后,你会更注意构图和层次。

mono

ocean 是深海色调。青蓝色的主体,深蓝的暗部。

ocean

forest 是森林色调。墨绿与棕褐交织。

forest

sunset 是日落色调。橙红渐变到深紫。它可能是六套主题里最不实用但最好看的一套。

sunset

主题系统的底层设计是语义色彩映射:ASCII art中的每个元素——太阳芯体、光线、云体、雨滴、雪花、闪电——不直接绑定具体颜色,而是绑定一个语义标记。主题负责将语义映射到具体的ANSI 256色值。同一幅字符画在不同主题下自动适配,不需要为每个主题重画一遍。添加一套新主题,只需要定义一组新的映射关系。

技术方案

选型

Rust。 原因很朴素:编译成单个二进制文件。用户下载一个文件,放到PATH里,完事。没有运行时依赖,没有虚拟环境。启动时间 < 100ms,整个查询流程含网络请求 < 500ms。

Open-Meteo。 免费的天气API,不需要注册,不需要API key。数据来源于各国国家气象局,精度高,全球覆盖,JSON格式。它是这个项目能做到”开箱即用”的关键——如果用户还得先去注册账号申请key,那”零配置”就是一句空话。

crossterm。 Rust生态中最成熟的跨平台终端库。所有的彩色输出、光标控制、全屏渲染都通过它完成。

不使用async。 这是一个快进快出的CLI工具,同步IO完全够用。用 ureq 做HTTP客户端,轻量、简单、没有tokio运行时的额外开销。

架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
src/
├── main.rs # 入口:参数解析 → 位置 → 天气 → 渲染
├── config.rs # TOML配置
├── location.rs # 位置解析链:CLI参数 > 配置 > IP定位
├── weather.rs # Open-Meteo客户端
├── model.rs # 数据结构 + WMO天气代码映射
├── units.rs # 公制/英制换算
├── art/ # ASCII字符画
│ ├── pieces.rs # 12种天气 × 日/夜变体
│ └── colors.rs # 语义色枚举
├── theme/ # 主题系统
│ └── [6个主题].rs # 语义色 → ANSI 256色映射
└── render/ # 渲染引擎
├── card.rs # 卡片模式
├── compact.rs # 紧凑模式
├── oneline.rs # 单行模式
├── fullscreen.rs # 全屏动态模式
└── chart.rs # 温度趋势mini-chart

数据流是一条直线:解析参数 → 确定位置 → 获取天气 → 选择主题 → 渲染输出。没有缓存层,没有后台服务,没有状态管理。每次运行都是一次完整的、无状态的查询。CLI工具应该像一个纯函数——相同的输入,相同的输出(天气变了不算)。

位置解析

位置解析是一个四级回退链:

  1. --lat/--lon 直接指定坐标——最精确
  2. 城市名参数 tenki beijing → Open-Meteo Geocoding API转坐标
  3. 配置文件中的坐标或城市名
  4. 以上都没有 → ip-api.com自动定位

四级覆盖了从精确控制到完全不配置的全部场景。用户永远不会看到”请先配置您的位置”这种提示。总有一个兜底。

WMO天气代码

Open-Meteo返回的天气状态是WMO标准代码——一个0到99之间的整数。tenki需要把这个数字映射到一段文字描述和一幅ASCII art。

映射的关键在于合理的合并粒度。WMO定义了几十种天气状态,但在字符画的表现力范围内,很多区分是没有意义的——用户不需要在终端里区分”阵雨”和”持续降雨”,他们需要知道的是”要不要带伞”。tenki把WMO代码合并为10种内部状态,每种状态有日间和夜间两个视觉变体,由API返回的 is_day 字段驱动切换。

ASCII Art

这是整个项目中最不”工程”的部分,也是我花时间最多的部分。

每幅字符画大约7-10行高、20-30列宽。这个尺寸经过反复调试——太小则细节丢失,太大则在小终端里溢出。所有art保持相同尺寸,以便在布局中精确对齐。

字符的选择是有讲究的。云的轮廓用 .-( ). 这样的圆润字符——圆润暗示柔软和蓬松。雨丝用 而不是 /——Unicode斜线比ASCII斜线更细腻,更接近雨水滑落的质感。雪用 *,雾用 _ - _ - 的水平层叠,闪电用 。每个选择都在尝试用有限的像素传达准确的意象。

着色方案是分层的。art定义中只包含语义标记——SunCoreCloudDarkRainDrop——由主题系统在渲染时填入具体颜色。这让art和颜色彻底解耦:添加一个新主题不需要重画任何字符画,添加一幅新字符画不需要为每个主题逐一指定颜色。

温度趋势图

卡片底部有一行24小时温度趋势,用Unicode block elements绘制:▁ ▂ ▃ ▄ ▅ ▆ ▇ █,八级高度,线性映射当日温度范围。一行字符的空间,传达”温度在一天中如何变化”这个信息——比一串数字直观得多。

全屏模式

全屏模式是技术上最复杂的部分。它通过crossterm的alternate screen和raw mode接管整个终端画布,逐帧刷新动画。

动画元素根据天气状态生成:雨天有从上方落下的雨滴粒子,雪天有飘落的雪花,晴夜有闪烁的星星。每个粒子有自己的位置、速度和生命周期。渲染循环以固定帧率运行,每帧更新粒子状态并重绘画面。

这个模式的存在,某种意义上是一种技术上的”顺势而为”——当你已经有了天气数据、ASCII渲染引擎和终端控制能力,不做一个全屏动态场景,就像有了望远镜却不看星星。

安装与使用

一行安装:

1
curl -fsSL https://raw.githubusercontent.com/keyork/tenki/main/install.sh | sh

安装脚本会先尝试下载预编译二进制,如果对应平台没有预编译版本,自动回退到源码编译。

然后:

1
2
3
4
tenki                                      # 自动定位
tenki beijing # 查北京
tenki --mode fullscreen --theme ocean # 全屏 + 海洋主题
tenki --mode oneline # 单行输出,塞进状态栏

配置文件在 ~/.config/tenki/config.toml,可以固定默认城市、主题、单位制。但它是完全可选的——不写也什么都不影响。

尾声

tenki是一个关于”恰到好处”的项目。

恰到好处的信息量——不多不少,看一眼就够。恰到好处的视觉表现——不是素到无聊,也不是炫到分神。恰到好处的使用门槛——一行命令安装,四个字母启动,不问你任何问题就给出答案。

它解决的问题很小:在终端里查天气。但如果一个工具每天都要用,哪怕只用三秒钟,那这三秒钟值得被认真对待。


GitHub: github.com/keyork/tenki
License: Apache 2.0

评论