惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
U
Unit 42
H
Help Net Security
博客园_首页
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Recorded Future
Recorded Future
aimingoo的专栏
aimingoo的专栏
爱范儿
爱范儿
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
S
Security @ Cisco Blogs
M
MIT News - Artificial intelligence
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
Spread Privacy
Spread Privacy
The GitHub Blog
The GitHub Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
K
Kaspersky official blog
MyScale Blog
MyScale Blog
阮一峰的网络日志
阮一峰的网络日志
C
CERT Recently Published Vulnerability Notes
V
Vulnerabilities – Threatpost
WordPress大学
WordPress大学
C
Cisco Blogs
G
Google Developers Blog
N
News and Events Feed by Topic
P
Palo Alto Networks Blog
Apple Machine Learning Research
Apple Machine Learning Research
Schneier on Security
Schneier on Security
博客园 - 聂微东
Security Latest
Security Latest
Security Archives - TechRepublic
Security Archives - TechRepublic
O
OpenAI News
云风的 BLOG
云风的 BLOG
IT之家
IT之家
PCI Perspectives
PCI Perspectives
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
小众软件
小众软件
Scott Helme
Scott Helme
大猫的无限游戏
大猫的无限游戏
L
LINUX DO - 最新话题
Microsoft Azure Blog
Microsoft Azure Blog
Simon Willison's Weblog
Simon Willison's Weblog
N
News and Events Feed by Topic
F
Fortinet All Blogs
The Last Watchdog
The Last Watchdog

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
App+1 | 跨平台且开源的文本扩展器:Espanso - 少数派
2022-12-13 · via 少数派

不论是在手机还是电脑上,我们在与人交流的过程中常常会形成或用到一些重复性的表述,这些表述的内容长度可多可少,但由于它们被用到频率十分之高,所以我们通常会更喜欢用类似于缩写的方式来代替我们一字一句输入的过程,例如说「yyds」(永远滴神)、「dddd」(懂的都懂)、「nbnhhsh」(能不能好好说话)等。

这些缩写或缩略语通常也可以被看作是用户自定义词典,我们不仅可以在操作设备上自定义,也可以在输入法上自定义。不过它们也仅限于定义一些纯文字性质的内容且长度有限,同时这些自定义设置可能会和特定的操作系统相绑定又或是无法完全导出,迁移成本存在过高的情况。

但有这么一类应用和自定义词典类似,它们为了用户自定义输入的缩写内容而生,不仅能定义纯文字性质的内容,还具备较强的扩展性,也被称为是文本扩展器(Text Expander)。

文本扩展器的作用表现和我们在使用自定义词典时的方式别无二致,都是输入一个特定的表达式,然后就会被替换成我们事先定义好的内容,比如:

--------------------------------->
[input]     #42
----------------------------------
[output]    意大利面拌 42 号混凝土
<---------------------------------

当我们在文本扩展器中事先设置完整内容之后,只要输入 #42 后就会转换成「意大利面拌 42 号混凝土」完整的句子。

知名的文本扩展器有 TextExpander,不过它属于付费应用也不是我们此次讨论的主角;而本文我们所介绍的则是另外一款免费、开源、跨平台且基于 Rust 语言编写的文本扩展器——Espanso,它不仅简单易用、体积小巧,且可配置性强,用户不但可以基于命令行配置扩展内容,而且还可以安装来自于社区的第三方扩展包。

boxcnEEZRbFYITVMbERmtA5skXf

快速上手

因为 Espanso 是一个开箱即用的工具,其安装步骤简单到可以一笔带过:打开 Espanso 官网,点击推荐的系统版本,下载并安装。

注:安装完成并启动 Espanso 时需要额外的操作授权,否则 Espanso 可能无法正确运行。

当然我们主要是看看如何使用 Espanso。毕竟安装完毕后启动 Espanso 是不会直接显示什么华丽的界面,因为它本质可以算是一个名不见经传的后台程序,只不过以应用的方式活跃在系统后台。

boxcnvkylAlfRHTF4cqSXxWljVf

使用 Espanso 的方式十分简单,我们只需在任意一个可以输入内容的地方,像输入代码一样先按下英文冒号「:」,然后再输入剩下的指令就可以神奇地看到 Espanso 已经为我们补全了内容。其中由 : 开始的一系列内容称为触发器(Trigger),而补全后的内容也被称为是匹配项(Match)。

比如我们现在输入 :date 的触发器指令那么 Espanso 直接会就帮我们将内容替换为表示当天日期的匹配项:

boxcn4z9bbRJj1XJMi8hI3LVT5e

就是这么简单!

不过你可能会好奇,我是怎么知道 :date 匹配项的呢?我们也可以在状态栏中找到 Espanso 的图表并点击「Open Search Bar」选项或是按下 Option+空格(Windows 上是 Alt+空格)就可以弹出相应的列表与搜索界面:

boxcnYRm0E57iPGjkPVIiJrsxAg

除此之外,因为我前面说了 Espanso 本质是一个后台程序,所以我们可以通过命令行来与之交互(可以在终端上通过 espanso --help 命令获取所有命令)。这里我们为了查看有哪些匹配项,可以直接使用 espanso match list 命令:

espanso match list
:espanso - Hi there!
:date - {{ date }}

可以看到 Espanso 并没有内置过多的匹配项,所以要想它能为我们更好地自动补全内容,就需要我们像自定义缩略语或短语一样事先进行人为配置。

Espanso 的配置主要有两部分,我们可以通过 espanso path 命令来找到配置文件路径:

espanso path
Config: /Users/Bobot/Library/Preferences/espanso
Packages: /Users/Bobot/Library/Preferences/espanso/match/packages
Runtime: /Users/Bobot/Library/Application Support/espanso

上述结果中的 Config 部分即为 Espanso 在当前操作系统中的配置存放路径。

当中主要包含了两部分配置:

$CONFIG/
  config/
    default.yml
  match/
    base.yml

其中:

  • config 部分的配置主要是针对 Espanso 程序本身,包括自定义补全的触发符号(比如将前面的英文冒号 : 更改为其他符号)、是否只在特定应用内 Espanso 才会生效等等;
  • match 部分的配置主要就是我们需要自定义补全的部分,也即 :date 这样的匹配项具体设置。

默认情况下 Espanso 是对所有应用都生效,因此当我们在应用中输入时很有可能就会极易触发匹配项弄巧成拙,为了避免冲突我们需要在后续在 config 部分进行配置以进行过滤。

不论是 Espanso 本身的配置还是自定义匹配项,Espanso 都采用了目前主流的 YAML 配置文件,我们可以直接通过系统自带的文本编辑器打开。

但是由于 YAML 的格式有些特殊,对于语法格式有严格要求,所以建议你使用 VS Code 这类编程专用的编辑器并在当中安装对应的 YAML 插件来进行编辑、配置;除此之外,可能你还需要简单学习一下 YAML 语法 才能更好地自定义相关配置内容。

现在就让我们来试着定义一组触发器与匹配项练习一番,这里我就使用 VS Code 来进行操作。

首先通过前面的命令我们找到了 Espanso 的配置文件夹后点击并拖拽至 VS Code,然后我们可以在 match/base.yml 默认匹配项的基础上进行设置,也可以像我一样新建一个名为 custom.yml 的匹配项进行设置:

boxcn1wNKUgX8quM615tvTAe6Ph

接着在当中填入如下内容(注意:如果你是在默认的 base.yml 文件中进行设置,由于已经存在了 matches 键就不需要重复填写):

# custom.yml

matches:
  - trigger: ":tomorrow"
    replace: "{{mytime}}"
    vars:
      - name: mytime
        type: date
        params:
          format: "%Y-%m-%d"
          offset: 86400

  - trigger: ":yesterday"
    replace: "{{mytime}}"
    vars:
      - name: mytime
        type: date
        params:
          format: "%Y-%m-%d"
          offset: -86400

当中的内容是由 YAML 语法构成的配置内容,其中每一组由「-」符号并紧接着 trigger 开始到下一个 trigger 前的一整块内容都表示定义一个匹配项,里面包括了触发器以及对应的替换内容等等,关于这部分配置我们在后续深入展开,现在暂时按下不表。

检测到有文件修改或保存后 Espanso 会自动重新加载配置文件,之后当我们输入 :tomorrow:yesterday 时,就会看到 Espanso 帮我们进行了自动补全:

boxcnPYVSOsu0php55cV9f9dAFg

以上仅是对 Espanso 管中窥豹一番,虽然它用法简单,但如果我们想要最大程度地发挥它的作用,可能还有更多用法有待我们进一步探索,所以接下来就让我们再深入了解一下 Espanso 的相关细节。

Espanso 相关配置

Espanso 的设置默认会作用到所有应用,但这通常可能会导致一些意想不到地冲突,所以我们最好需要对其进行调整。

只在特定应用中生效

Espanso 的默认配置为 config/default.yml 文件,但我们也可以针对不同应用在同一层级下添加不同的配置文件,比如 config/vscode.yml。之后我们可以在 vscode.yml 文件中添加过滤选项,即不让 Espanso 在使用 VS Code 时生效:

# vscode.yml

filter_class: "com.microsoft.VSCode"
enable: false

当我写入这短短地两行内容并保存之后,Espanso 就不会在我使用 VS Code 时生效从而避免了冲突。

Espanso 提供了三种过滤应用的方式,包括上述示例即 filter_titlefilter_exec 以及 filter_class,它们也分别对应了按当前活跃窗口的文本标题过滤、按应用的可执行路径过滤以及按当前活跃窗口的类名(编程概念)过滤。

这三种方式默认使用正则表达式,倘若你不清楚具体的内容,那你就可以填写正则表达式:

filter_exec: "Chrome$"
enable: false

当然你也可能会好奇我前面的例子是如何找到 VS Code 对应的类名 com.microsoft.VSCode

因为 Espanso 内置了一个探测指令可以一次性帮我们生成对应三种过滤方式的内容。在未屏蔽 Espanso 的情况下,我们可以像使用匹配项那样输入 #detect# 来进行触发,比如我在 macOS 的微信随便选择一个对话框,然后输入该指令即可弹出如下界面。

boxcn7sN0WGrytICEEDUfdfLb2b

之后我们只需要点击拷贝到剪切板再自行粘贴选择即可。

建议你在配置时侧重选择除 filter_title 之外的另外两种方式,因为当前活跃窗口的标题文本内容变化幅度较大并不是很稳定。

但除了像上述示例那样直接使用 enable: false 这样简单粗暴的屏蔽方式之外,Espanso 也提供了另外一种模式,让你可以自主选择在特定应用中只屏蔽(exclude)掉对应的匹配项。比如我现在排除掉我前面自定义的 custom.yml 文件:

filter_class: "com.microsoft.VSCode"
extra_excludes:
  - "../match/custom.yml"

默认情况下的路径为当前的 config 路径,而匹配项则是在与 config 同级的路径中,所以我们需要通过 ../match 的方式返回到同级目录然后再选择 match 目录。

保存之后在 VS Code 中即便使用 :tomorrow:yesterday 都不会得到相应的匹配项。

如果要屏蔽的内容过多,你既可以使用 glob 模式来设置路径,也可以换一种思路,即只让某些匹配项——比如代码片段(Snippets)——在特定应用中生效,比如我现在有一个 match/pycode.yml 配置,当中准备了一些 Python 相关的代码片段,现在我只想这些片段只在 VS Code 中生效,那么此时就应该这样做:

filter_class: "com.microsoft.VSCode"
extra_includes:
  - "../match/pycode.yml"

修改 Espanso 默认设置

尽管说 Espanso 有提供了基本的 UI 界面并驻留在状态栏中,但 Espanso 的设置都是需要通过配置文件来修改,这样的方式缺点很明显,就是对于一般用户而言缺少图形化配置界面还需要额外的学习成本;不过对于喜欢折腾的玩家来说也好处颇多,一方面你可以随时随地同步配置文件在,在不同操作系统之间也能保持配置统一;另一方面,你可以根据自己直接手动快速修改。

比如 Espanso 默认的搜索框界面可以用 Option+空格(Windows 为 Alt+空格)打开,那么我们也可以直接修改为 Option+Shift+空格 打开:

search_shortcut: OPTION+SHIFT+SPACE

当然我们也可以禁用搜索框快捷键的同时,自定义快速弹出 Espanso 匹配项的搜索框界面的触发器:

# default.yml

search_shortcut: off
search_trigger: ">esp"

之后我们只要敲击 >esp 就能令搜索框直接弹出。

除此之外,如果你不喜欢每次修改配置文件时 Espanso 就自动重载,那么你也可以关闭该选项并在每次配置之后手动点击状态栏的驻留程序并选择「Reload config」选项:

auto_restart: false

如果你觉得 Espanso 在扩展文本时的速度有点慢,那么也可以直接选择将 pre_paste_delay 选项尽量调低一些(默认为毫秒 ms),以便快速替换而不是保留肉眼可见的延迟:

pre_paste_delay: 100

更多的匹配项用法

Espanso 相比于其他文本扩展器或用户自定义词典最为突出的地方在于它的匹配项是灵活且可配置的,并且还能搭配终端的命令行工具一起使用得到最后的匹配结果,当然这都需要我们进行配置。

静态匹配项

最简单的匹配项配置就是 Espanso 默认自带的例子,它们通常是由 triggerreplace 一组内容来组成:

- trigger: ":espanso"
  replace: "Hi, there!"

像这样内容既定的部分和我们自定义词典没有什么区别,也被称为静态匹配项(Static Matches)。借助于 YAML 语法我们也可以编写长串的替换文本,即:

- trigger: ":espanso"
  replace: "Hi,\nthere!"
- trigger: ":espanso"
  replace: |
    Hi,
    there!

两种方法是等价的方式,你既可以手动指定换行符 \n,也可以使用 YAML 支持的长文本语法在 replace 键后面空格之后紧接着一个 | 符号来开启多行模式。

需要注意的是,我们上面虽然设置了多个同名触发器的匹配项,但彼此并不会冲突且 Espanso 在替换时会主动弹出搜索框让我们自动去选择使用那一组匹配项来作为最终替换内容。

boxcnDO8vSgHWdSBlZzaydLYdJe

默认情况下 Espanso 会直接将 replace 的部分作为匹配项的描述内容,这当我们存在多个同名触发器且内容近似的匹配项时会很容易造成困惑,所以 Espanso 支持我们为匹配项加上对应的描述信息(label 标签),以便能更好地知道当前触发器所得到的内容是什么:

# custom.yml

- trigger: ":espanso"
  replace: "Hi, there!"
  label: "inline content"
- trigger: ":espanso"
  replace: "Hi,\nthere!"
  label: "content with newline(\\n)"
- trigger: ":espanso"
  replace: |
    Hi,
    there!
  label: "content with newline"

之后我们再次触发 :espanso 时就会能看到不同匹配项所对应的不同描述内容是什么。

boxcnUkmhmCpKCypqO306AJpOUU

类似地,我们也可以让一个匹配项拥有多个触发器,这里就需要用到 YAML 的数组语法来设置,例如:

- trigger: [":espanso", ":greet"]
  replace: "Hi, there!"
  label: "inline content"

但如果你要设置的匹配项其触发器虽然比较多但表达类似,那么 Espanso 也支持你使用正则表达式的方式来进行设置,我们只将 trigger 替换成 regex 并使用正则表达式即可。我们可以直接将上述示例稍作修改:

- regex: ":(espanso|greet)"
  replace: "Hi, there!"
  label: "inline content"

动态匹配项

除了静态匹配项之外,Espanso 也支持动态匹配项,这也是让 Espanso 灵活且强大之处,我前面给出的明天和昨天日期的示例就是如此。因为这两个匹配项有些重复,这里我就以明天时间日期为例:

- trigger: ":tomorrow"
  replace: "{{mytime}}"
  vars:
    - name: mytime
      type: date
      params:
        format: "%Y-%m-%d"
        offset: 86400

在当前的匹配项之下我们还可以自定义变量,也即对应着 vars 之下的内容。变量一词就是编程中经常用来保存内容的基本单位,而 Espanso 允许我们沿用这样的设定直接为匹配项设置一连串的变量,之后动态地生成内容,而不是像静态匹配项那样一成不变。

所以在设置 :tomorrow 所对应的匹配项时,我自定义了一个 mytime 变量,这个变量的类型(type)是日期类型,然后又分别表示有 format 用于表示日期展示样式和 offset 日期偏移两个参数。

像日期类型这样的变量设置在 Espanso 中又被称为扩展(Extension)。所以除了日期类型之外,Espanso 还支持多种类型以适应动态匹配项的需要,如多选类型、随机类型、脚本类型、Shell 命令类型等等。

其中脚本类型和 Shell 命令类型有些类似,只不过前者主要是针对于逻辑更为复杂的脚本文件,它们通常由某种编程语言来编写,而后者主要就是适用于我们所示的终端命令行工具:

# custom.yml

- trigger: ":pynow"
  replace: "{{now}}"
  vars:
    - name: now
      type: script
      params:
        args:
          - python3
          - -c 
          - |
            from datetime import datetime
            print(datetime.now())

- trigger: ":sspai_title"
  replace: "{{title}}"
  vars: 
    - name: title
      type: shell
      params: 
        cmd: "curl -s https://sspai.com | htmlq --text 'title'"
        shell: zsh

上述定义的 :pynow:sspai_title 两个动态匹配项里分别用到了脚本类型和 Shell 命令类型,前者是执行 Python 解释器及其来输出最终结果,而后者则是通过系统内的 curlhtmlq 两个命令行工具来访问少数派官方并通过 HTML 获得最终的标题内容。

除了脚本类型和 Shell 命令类型之外,Espanso 还有一种类型——Form 表单——适用于多处动态内容生成的情况,通常可以被作为模板来使用,比如邮件回复模板、问题反馈模板等等:

- trigger: ":reply"
  form: |
    Hey [[name]],
      Thank you for your email.
      We have already try to handle the [[number]] issue.

在上述匹配项中我们没有 replace 键,取而代之的是 form,并且当中的动态内容部分则是由之前的花括号变成了方括号。这是 Espanso 对于表单内容的一个简写方式,本质上等价于定义变量的方式:

- trigger: ":reply"
  replace: |
    Hey {{template.name}},

      Thank you for your email.
      We have already try to handle the {{template.number}} issue.
  vars:
    - name: template
      type: form
      params:
        layout: |
          Hey [[name]],

            Thank you for your email.
            We have already try to handle the [[number]] issue.

所以当我们配置完毕并保存后,输入 :reply 时会直接弹出 Espanso 为我们准备好的表单界面,我们只需填好其中的部分即可快速生成模板内容。

boxcn7rhNm2JgN8FykQcWXRtXOd

但 Espanso 也还支持某个匹配项在其他匹配项中被使用或引用,极大地提高了灵活性与复用性。比方说我们现在再为这个模板自动带上一个当前回复日期:

Hey 100gle,

  Thank you for your email.
  We have already try to handle the #314 issue.

  2022-12-12

那么我们就可以使用这种引用方式:

- trigger: ":today"
  replace: "{{today}}"
  vars:
    - name: today
      type: date
      params:
        format: "%Y-%m-%d"

- trigger: ":reply"
  replace: |
    Hey {{template.name}},

      Thank you for your email.
      We have already try to handle the {{template.number}} issue.
    
      {{today}}
  vars:
    - name: today
      type: match
      params:
        trigger: ":today"
    - name: template
      type: form
      params:
        layout: |
          Hey [[name]],

            Thank you for your email.
            We have already try to handle the [[number]] issue.

:reply 匹配项的变量中,我们会定义一个 today 变量,它的参数类型是特殊的 match 匹配项,然后当中的 trigger 参数与我们 :today 匹配项的触发器一致。

这样只要我们填写完姓名与问题 ID 之后就会在模板中还自动生成当前的回复日期。

安装社区第三方扩展包

自定义匹配项会是一个永无止境的过程,因为它会随着个人的需要而与日俱增。但人类知识是相通的,也有一些内容可能不仅个人会用到,在互联网某一隅的一群人也会用到,譬如说 Emoji

可你知道吗?在我们日常网络交流中经常使用的每一个 Emoji 表情,其实也都基本有一个相对应称呼(CLDR Short Name),这里我就直接引用 Unicode 官方给出的示例列表:

BrowserCLDR Short Name
😀grinning face
😃grinning face with big eyes
😄grinning face with smiling eyes

上述三个表情虽然都属于笑脸范畴,但是它们对应的 Unicode 编码不同,其文字称呼也不同;这也就意味着我们不仅能够通过 Unicode 编码来找到它们,同理文字称呼也适用。

所以你要是恰好知道某个 Emoji 的名称而又不像自己四处翻找,那么借助 Espanso 就可以直接类似 :grinning-face 以文字称呼得到 Emoji 表情。

Espanso 允许我们安装来自于社区其他人共享的第三方扩展包,它会类似于插件地形式来扩充我们的匹配项,可以让我们「站在巨人的肩膀」上去更好地使用 Espanso。我们可以直接到 Espanso 的官方 Hub 页面 去搜索。

比如我们直接就以前面提到的「Emoji」一词进行搜索就可以找到与之相关的扩展包:

boxcn0zHKrldbRpSPS1HT7CZOVf

但我们与扩展包相关的操作都需要通过命令行来完成:

espanso install all-emojis          # 安装 all-emojis 扩展包
espanso uninstall all-emojis        # 卸载 all-emojis 扩展包

espanso package list                # 查看 Espanso 中的所有扩展包
espanso package update all-emojis   # 更新 all-emojis 扩展包
espanso package update all          # 更新 Espanso 中的所有扩展包

安装完成之后我们就再次按照前面提到的查看匹配项的方式来检查是否安装成功。

boxcn0Knju2VM9rBWizJ5t197he

除上述方式之外 Espanso 还支持额外的安装方式,甚至你也可以自己去创建并分享一个扩展包,当然这些内容 Espanso 都在文档中找到详细说明,这里就不再额外赘述。

结尾

虽然 Espanso 在使用上直接了当并且功能强大,它不仅可以帮我们扩展静态的模板内容,也可以具备较强的扩展性,例如调用脚本或使用命令行来得到内容。

不过为了让它好用、易用可能还需要多花一点心思在配置上。受限于篇幅,本文仅介绍了 Espanso 中比较重要的一些配置内容;但像全局变量、导入外部配置、变量注入、如何分享自己的扩展包等等细节并没有一一涉及。

好在 Espanso 的官方文档已经给出了较为细致的说明,这些未提及的内容就留给你自行探索。

> 少数派请你做地图:城市声音收藏夹火热征集中,期待你创作的城市之声 🎧

> 下载少数派 2.0 客户端 、关注少数派公众号,解锁全新阅读体验 📰

> 实用、好用的正版软件,少数派为你呈现 🚀