首页
/ Fira Code 编程连字等宽字体:功能全景、兼容矩阵与本地定制构建实战

Fira Code 编程连字等宽字体:功能全景、兼容矩阵与本地定制构建实战

2026-09-04 14:01:26作者:卓炯娓

本文以 Fira Code 仓库中的葡萄牙语版说明文档 LEIAME.md 为主体,完整还原该字体“问题—方案—特性—兼容性—本地构建”的完整技术脉络,并结合仓库内的构建脚本(script/build.shMakefile)、OpenType 特性文件(features/)与 Clojure 生成管线(clojure/fira_code/calt.clj),深入讲解连字 calt 特征的自动生成原理、性能取舍,以及如何用 -f-n-w 参数构建带永久特性的定制字体。

问题与方案:为什么需要“编程连字”

LEIAME.md 开宗明义地提出了一个普遍痛点:程序员日常使用大量由多个 ASCII 字符编码的符号。对人类大脑而言,-><=:= 这类序列是单一的逻辑 token,尽管它们在屏幕上占据两到三个字符宽度;眼睛需要消耗能量去扫描、解析并把多个字符合并成一个逻辑单元。理想情况下,所有编程语言都应当为运算符设计完整的 Unicode 符号,但现实并非如此。

Fira Code 的解法是:一款免费等宽字体,内置针对编程中常见多字符组合的连字(ligatures)。这里有两个关键事实必须理解:

  1. 这只是字体的渲染层特性:底层源码保持 ASCII 兼容不变,连字只影响显示,不影响搜索、匹配、剪贴板或任何文本处理;
  2. 连字还能修正间距:对 ..// 这类高频序列,连字渲染允许对字距做更合理的校正,使这些序列视觉上更紧凑、更对齐。

下载与安装

仓库文档给出的官方发行版为 Fira_Code_v6.2.zip(2021 年 12 月 6 日,约 2.5 MB),可在 GitHub 项目的 Releases 页面获取;安装后的使用与排障参考项目 Wiki 中的安装指南和 Troubleshooting 章节(仓库文档以外部链接指向,此处不再重复外部地址)。

如果你拿到的是仓库源码而非发行版,也可以自行构建出全部字体文件——见后文“本地构建”一节。

Fira Code 连字渲染效果:左列为启用连字后的渲染结果,右列为相同字符序列未启用连字时的样子

上图左列是 Fira Code 中的连字渲染效果,右列是同样字符序列不启用连字时的原始状态——这正是“渲染层特性、源码不变”的直观体现。

字体特性全景:不只是连字

编程连字与箭头组合

Fira Code 自带大量连字,覆盖比较、赋值、箭头等常用符号序列。更灵活的是它的箭头系统:箭头长度可任意加长,且起点、中段、终点三段构件可以按喜好自由拼接组合,方便在注释或文档中画出任意长度的箭头。

标点与高频字母对的微调

Fira Code 不止于连字:对标点符号和出现频率高的字母对(如 fifl 组合)也做了排版级微调,这些微调规则就存放在 features/calt/fi_fl.fea 等特性文件中。

字符变体与样式集:cv / ss / zero / onum / calt

字体附带了多组可开关的特性,让每个使用者都能按个人偏好选择字形:

特性前缀 含义 仓库对应文件
cv01cv32 Character Variant,单字符变体(如 cv01 是备选小写 a) features/cv01.fea 等 32 个文件
ss01ss32 Stylistic Set,样式集(成组地改变多个字形) features/ss01.fea 等 32 个文件
zero 带斜杠/点的易区分零 features/zero.fea
onum 老式(不等高)数字 features/onum.fea
calt 上下文连字,本文档的核心 features/calt/ 目录

features/cv01.fea 为例,其内容就是标准的 OpenType 替换规则:

### Alternate lowercase a

sub a by a.cv01;
sub aacute by aacute.cv01;
sub abreve by abreve.cv01;
sub acircumflex by acircumflex.cv01;

即:把基本 a 及其所有带音标变体(aacuteabreve……)替换为对应的 .cv01 备选字形——这正是开启 cv01 后小写 a 外观改变的底层机制。

部分连字本身也可以被样式集或字符变体改变/启用(例如直角弯折风格的箭头变体),这使“同一序列、多种画法”成为可能。

控制台 UI 支持:box drawing 与 powerline

作为编程字体,Fira Code 对 ASCII/box drawing 制表符、powerline 符号以及其他控制台 UI 图形(▀▄█─│┌┐ 等)提供了完整的字形覆盖,终端里的表格、分隔线、powerline 状态栏都能正确对齐渲染。

Fira Code 对 box drawing、powerline 等控制台 UI 图形的支持

进度条专用字形 U+EE00

Fira Code 是第一款为进度条提供专用字形的编程字体:它把私有区码位 U+EE00 一带映射为一组由细到粗的进度条片段,程序端只要按宽度输出相应码位序列即可渲染出漂亮的进度条。

Fira Code 进度条专用字形,由细到粗的进度条片段

仓库的英文说明(README.md)还补充了一个实现细节:程序无法探测某字体是否具备 U+EE00 处的进度条字形,因此项目建议引入环境变量约定 UNICODE_PROGRESS_BAR=true 作为启发式判断——若存在该变量,即可安全假设 U+EE00..EE0B 会被正确渲染,并呼吁更多编程字体采纳这一约定。

数学排版

凭借完整的 Unicode 覆盖,Fira Code 同样适用于数学公式书写场景,数学符号、花体与关系符均有配套字形。

纵深解析:calt 连字规则的自动生成与性能取舍

calt 是连字功能的载体,而 Fira Code 仓库中最值得细读的部分是它如何自动生成 calt 代码,以及为什么最终选择了当前的实现方式

.glyphs 到 calt lookup 的生成管线

LEIAME.md 提到构建时会处理 FiraCode.glyphs 源文件;从源码结构看,真正的管线入口是 clojure/fira_code/main.clj

  1. 加载 .glyphs 文件,收集所有以 .liga 结尾且导出的字形,把 dash_greater_greater.liga 这类名字解析为 [dash greater greater] 序列;
  2. 依次执行 calt/replace-calt(生成 calt 规则)、classes/fill-allfeatures/fill-allspacers/add-spacers(注入间距器)、not-space/regen-not-spacechecks/widths(宽度校验);
  3. 把结果写回新的 .glyphs 文件。

其中 clojure/fira_code/calt.cljliga->rule 函数会为每条 2~5 个字符的连字序列生成一个独立的 lookup,其模板长这样(以 3 字符连字为例):

lookup 1_2_3 {
  ignore sub 1 1' 2 3;
  ignore sub 1' 2 3 3;
  ...(ignore-prefixes 与特判 ignores)
  sub 1.spacer 2.spacer 3' by 1_2_3.liga;
  sub 1.spacer 2'       3  by 2.spacer;
  sub 1'       2        3  by 1.spacer;
} 1_2_3;

注意几个设计细节:

  • ignore sub 1 1' 2 3; 防止“三连字中间又触发二连字”之类的重叠替换;
  • ignore-prefixescalt.clj)专门保护正则前瞻/后顾写法:(?=...)(?!...)、PHP 的 <?= 等序列永远不会被连字吞掉;
  • priorities 控制替换顺序,例如 <<>>>||| 必须先于 --=== 被替换,否则 -> 中的 -> 会干扰 >>-> 之类的更长序列;
  • spacer 字形把“可参与连字的边界”显式编码进规则,这是性能优化的关键(见下)。

四种 calt 写法的性能基准

docs/calt_performance.md 记录了作者在四种 calt 实现方式下的 shaping 性能对比(环境:HarfBuzz 2.6.4,3.2 GHz 六核 i7,macOS 10.15.3,hb-shape -n 100000 测试串):

实现方式 思路 10 万次 shaping 耗时
Baseline 单条 sub 1 2 3 4 by 1_2_3_4.liga; 0.407 s
Spacers .spacer 辅助字形 + 多条子规则 1.415 s
Lookups Spacers + 每连字独立 lookup 2.080 s
Ignores Lookups + 显式 ignore sub 规则 2.656 s

从源码结构看,最终产物选择了 Spacers 风格calt.clj 生成的规则带 .spacer 标记、且被包裹进 lookup),在“规则精确可控”与“shaping 性能”之间取折中:显式 ignore 规则虽然最直白,但会拖慢近 6 倍,因此只保留必要的少量 ignore。这也解释了为什么 Fira Code 的字形表里有大量不直接显示的 .spacer 辅助字形。

手写 calt:十六进制与分辨率标注

自动生成之外,features/calt/ 目录还包含手写 lookup。例如 features/calt/cross.fea 中的 hexadecimal_x0xFF0x10 之类的 x 替换为乘号样式(x.multiply),还会处理 800x600 这类分辨率标注——规则通过 @Digit@HexDigit 等类匹配,这些类定义在 classes/ 目录(Digit.feaHexDigit.feaDigitTosf.feaOpeningBracket.feaClosingBracket.fea 等)。

编辑器兼容性列表

LEIAME.md 给出了详尽的编辑器兼容矩阵(支持情况以文档为准,版本号为最低要求;原文档中的“安装指令”外部链接此处省略):

可用(Works) 不可用(Doesn’t work)
Arduino IDE(2.0+,指令同 VS Code) Adobe Dreamweaver
Abricotine Delphi IDE
Android Studio(2.3+,IntelliJ 系指令) 独立 Emacs(有变通方案)
Anjuta(EOF 处除外) IDLE
AppCode(2016.2+,IntelliJ 系指令) KDevelop 4
Atom 1.1 或更新 Monkey Studio IDE
BBEdit(14.6+) UltraEdit(Windows)
Brackets(需安装插件)
Chocolat
CLion(2016.2+,IntelliJ 系指令)
Cloud9(需指令配置)
Coda 2
CodeLite
CodeRunner
Comma(Preferences > Editor > Font)
CotEditor
Eclipse
EditPad
elementary Code
Geany(1.37+)
gEdit / Pluma
GNOME Builder
Godot
GoormIDE(需指令配置)
gVim(Windows 与 GTK 平台各有指令)
IntelliJ IDEA(2016.2+,IntelliJ 系指令)
Kate, KWrite
KDevelop 5+
Komodo
Leafpad
LibreOffice
LightTable(需指令配置)
LINQPad
MacVim 7.4 或更新(需指令配置)
Mancy
MATLAB(Windows 需指令配置)
Meld
Mousepad
NeoVim-gtk
NetBeans
Notepad(Windows)
Notepad++(需指令配置)
Notepad3(需指令配置)
Nova
PhpStorm(2016.2+,IntelliJ 系指令)
PyCharm(2016.2+,IntelliJ 系指令)
QOwnNotes(21.16.6+)
QtCreator
Rider
RStudio(需指令配置)
RubyMine(2016.2+,IntelliJ 系指令)
Scratch
Scribus(1.5.3+)
SublimeText(3146+)
Spyder IDE(仅 Qt5)
SuperCollider 3
TeXShop
TextAdept(Linux, macOS)
TextEdit
TextMate 2
UltraEdit (UEX)(Linux)
VimR(需指令配置)
Visual Studio(2015+,需指令配置)
Visual Studio Code(需指令配置)
WebStorm(2016.2+,IntelliJ 系指令)
Xamarin Studio / Monodevelop
Xcode(8.0+,更早版本需插件)
Xi
可能可用:SmultronVico 存疑:Code::Blocks IDE

终端兼容性列表

终端侧的差异主要来自渲染引擎是否支持 calt

可用(Works) 不可用(Doesn’t work)
crosh(ChromeOS,需指令配置) Alacritty
Ghostty Asbru Connection Manager
Hyper(见其 issue #3607) Cmder
iTerm 2 ConEmu
Kitty GNOME Terminal(受 VTE 上游 issue 影响)
Konsole gtkterm(受 VTE 上游 issue 影响)
Mintty guake(受 VTE 上游 issue 影响)
QTerminal LXTerminal(受 VTE 上游 issue 影响)
st(需打上 ligatures 补丁) mate-terminal
Tabby PuTTY
Terminal.app rxvt
Termux sakura(受 VTE 上游 issue 影响)
Token2Shell SecureCRT
Wez’s terminal Terminator(受 VTE 上游 issue 影响)
Windows Terminal terminology
ZOC(macOS) Tilix
Windows Console
xfce4-terminal(受 VTE 上游 issue 影响)
xterm
ZOC(Windows)

浏览器支持

LEIAME.md 给出的浏览器方案分三步:引入字体样式表(仓库内即 distr/fira_code.css,可部署到自有静态资源服务或第三方 CDN),然后在 CSS 中指定字体族,并对支持可变字体的浏览器做回退:

/* 在 CSS 中指定 */
code { font-family: 'Fira Code', monospace; }

@supports (font-variation-settings: normal) {
  code { font-family: 'Fira Code VF', monospace; }
}

浏览器支持矩阵与注意事项:

  • IE 10+、Edge Legacy:需要显式 font-feature-settings: "calt"; 开启连字;
  • Firefox、Safari、Chromium 系(Chrome、Opera):原生支持;
  • ACE、CodeMirror:可用,其中 CodeMirror 需设置 font-variant-ligatures: contextual;

本地构建 Fira Code

LEIAME.md 的“Construir o Fira Code localmente”一节完整保留了官方推荐的构建方式,以下按原文档骨架继承,并补充源码级说明。

方式一:macOS 本地构建

适用于希望修改 FiraCode.glyphs 源文件并自行产出 OTF/TTF/WOFF 的场景。作者使用的配置如下(script/bootstrap_macos.shrequirements.txt 为依赖清单):

# 安装所有构建所需工具
./script/bootstrap_macos.sh

# 构建字体文件
./script/build.sh

# 将 OTF 安装到 ~/Library/Fonts
cp distr/otf/*.otf ~/Library/Fonts

script/bootstrap_macos.sh 可见其实际动作:安装 Python 3.12 并创建 venv 虚拟环境、按 requirements.txt 安装 Python 依赖(fontmake 等)、安装 ttfautohintwoff2sfnt2woff-zopfli(后者需从 webfonttools tap 获取)。

方式二:Docker 构建

不想配置本地环境时可直接用容器(对应 Makefile 中的 build / package 两个目标):

# 在容器内安装依赖并构建字体文件(make 等价于 docker run --rm -v ${PWD}:/opt tonsky/firacode:latest ./script/build.sh)
make

# 将 dist/ 中的字体文件打包为 zip
make package

构建参数:-f / --features-n / --family-name-w / --weights

LEIAME.md 明确列出三个构建开关,这里结合 script/build.sh 的参数解析实现逐一说明:

参数 说明 默认值
-f / --features 以逗号分隔列表永久启用样式集/字符变体(适合编辑器不支持单独开关的场景);脚本会先排序去重,再调用 script/bake_in_features.sh 把这些特性“烘焙”进临时 .glyphs 文件
-n / --family-name 指定字体族名以便区分不同定制版本;特殊值 features 会把已启用特性按排序后的空格分隔列表追加到默认族名后 "Fira Code"
-w / --weights 限制要生成的字重 "Light,Regular,Retina,Medium,SemiBold,Bold"

默认字重列表在 script/build_otf.shdefault_weights 数组中定义,与文档一致。此外 script/build.sh 还提供了一个文档未强调的开关:-g / --generate-glyphs-only,只生成定制后的 .glyphs 文件即退出,不执行后续编译。

文档给出的三条典型命令(原文档保留):

# 在本地 shell 中
./script/build.sh --features "ss02,ss08,ss10,cv03,cv07,cv14" --family-name "Fira Code straight" --weights "Regular,Bold"

# 或通过 docker 容器(将生成族名 'Fira Code cv01 cv02 cv06 cv31 onum ss01 ss03 ss04 zero')
docker run --rm -v "${PWD}":/opt tonsky/firacode:latest ./script/build.sh -f "cv01,cv02,cv06,ss01,zero,onum,ss03,ss04,cv31" -n "features"

# 在 Git for Windows 的 Git Bash 或其他 MSYS2 shell 中,可能需禁用路径转换
MSYS2_ARG_CONV_EXCL="*" docker run --rm -v "${PWD}":/opt tonsky/firacode:latest ./script/build.sh -f "ss02,ss03,ss04,ss05,ss06,ss07"

script/build.sh 的执行流程看,一次完整构建的调用链为:

  1. FiraCode.glyphs 复制为临时文件(FIRACODE_GLYPHS_FILE 环境变量,可用 FIRACODE_FAMILY_NAME 覆盖族名);
  2. 若有 -f,先执行 ./bake_in_features.sh 烘焙特性,并在需要时改写临时 .glyphsfamilyName,随后把结果另存为 <族名>.glyphs
  3. 依次调用 script/build_otf.shfontmake -o otf,按字重逐个生成 distr/otf/<族名>/FiraCode-<字重>.otf)、script/build_ttf.shfontmake -o ttf 后追加 ttfautohint --no-info --ignore-restrictions 自动加 hint,输出至 distr/ttf/)、script/build_variable.sh(可变字体)、script/build_woff2.shscript/build_woff.sh(用 sfnt2woff-zopfli 压缩,注意它会 rm -f 掉 Retina 字重的 woff,输出至 distr/woff/)。

这套“OTF → TTF(加 hint) → 可变字体 → WOFF2 → WOFF”的多格式流水线,正是发行版 zip 包内容结构的来源。

谁在使用、以及替代选择

LEIAME.md 列出了公开采用 Fira Code 的项目:CodePen、Blink Shell、Klipse、IlyaBirman.net、EvilMartians.com、FromScratch、PEP20.org 等。

同类型的替代字体(原文档列出,此处仅作名称对照):

  • 免费带连字的等宽字体:Hasklig、Monoid、Fixedsys Excelsior、Iosevka、DejaVu Sans Code、Victor Mono、Cascadia Code、JetBrains Mono;
  • 付费带连字的等宽字体:PragmataPro、Mono Lisa。

致谢与来源

  • 作者:Nikita Prokopov(@nikitonsky);
  • 基于:Mozilla 的 Fira Mono 字体;
  • 灵感来源:Hasklig;
  • 葡萄牙语版本译者:Kauan Farias(@kau19an)。

本文全部技术事实均以 LEIAME.md 为准,源码佐证取自 script/build.shMakefileclojure/fira_code/calt.cljdocs/calt_performance.mdfeatures/calt/cross.fea 等仓库文件;各文件均可在仓库中直接查阅以深入细节。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384