emacs tui在遇到文件里有emoji的时候在主流terminal都有渲染错误

nvim helix打开相同文件都没有问题,emacs tui有问题. 在不同的terminal问题还不同

wezterm: 看着一个emoji变小了 只占用一个char宽度,对于零宽的unicode也有占用一个char宽,evil移动能看到,忍一忍还能用

ghosrtty kitty 这两个terminal里现象就导致有些行残留 或者消失,几乎不可用

将内容复制十几份到scrach buffer, 会出现更多奇怪的现象

录屏已经准备好, 还没搞清楚怎么上传


目前自用的缓解措施, 让emoji显示为问号

;; TUI: 不显示 emoji,避免 Kitty/WezTerm 的光标错位与重绘花屏。
;; 说明:只改显示,不改 buffer/file 内容。
(when (not (display-graphic-p))
  (setq-default bidi-display-reordering nil)
  (setq bidi-inhibit-bpa t)

  (defun my/make-tui-no-emoji-display-table ()
    "Return a display table that masks emoji-like chars in terminal Emacs."
    (let ((dt (make-display-table)))
      ;; Fall back to any existing standard display behavior.
      (set-char-table-parent dt standard-display-table)
      ;; Flags (regional indicators)
      (set-char-table-range dt (cons #x1F1E6 #x1F1FF) (vector ??))
      ;; Emoji blocks
      (set-char-table-range dt (cons #x1F300 #x1FAFF) (vector ??))
      ;; Misc symbols / dingbats where emoji presentation often appears (e.g. U+2695)
      (set-char-table-range dt (cons #x2600 #x27BF) (vector ??))
      ;; Zero-width joiners/selectors/modifiers: hide them completely.
      (set-char-table-range dt (cons #x200D #x200D) (vector))
      (set-char-table-range dt (cons #xFE0E #xFE0F) (vector))
      (set-char-table-range dt (cons #x1F3FB #x1F3FF) (vector))
      dt))

  (defvar my/tui-no-emoji-display-table nil)
  (setq my/tui-no-emoji-display-table (my/make-tui-no-emoji-display-table))

  ;; Global default + per-buffer reinforcement (some major modes set buffer-display-table).
  (setq standard-display-table my/tui-no-emoji-display-table)
  (setq-default buffer-display-table my/tui-no-emoji-display-table)
  (when (fboundp 'global-auto-composition-mode)
    (global-auto-composition-mode -1))
  (add-hook 'after-change-major-mode-hook
            (lambda ()
              (setq-local buffer-display-table my/tui-no-emoji-display-table))))


我的环境是macos 15.7.2 (24G325), emacs plus install by homebrew 截图文件是 https://raw.githubusercontent.com/badlogic/pi-mono/f129ac93c508c2cbe45e8342bbf59ce4ba04acdc/README.md

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**


将此内容放到scrach buffer后, 也不会


感谢 lgfang 提醒, 已经增加截图说明.

你是纯抱怨还是来找解决办法?如果是后者,你应该上传几张截图和测试样本,否则我们很难帮忙啊。

下面是我以前处理ZWJ的办法,仅供参考。(-Emacs 30.1 上似乎已经不需要这个了- , 还是需要)。

Disable auto-composition-mode if running in a terminal as most terminal emulators cannot handle Emoji ZWJ. See ZWJ examples in my ZWJ test file.

NOTE: disabling it on the fly does not work very well, must restart Emacs.

  (use-package emacs
    :if (not (display-graphic-p))
    :config
    (setq-default auto-composition-mode nil)
    )
- 👩‍💻 ("\U01F469 \U01F4BB") :: Zero Width Joiner (ZWJ) example. Move cursor
  around, see if the cursor and chars are still shown correctly.
- 🤮 ("\U01F92E") :: UTF-8 char, Emoji example
- 您好 ("\u60A8\u597D") :: UTF-8 char, Chinese example

1 个赞

【求助】在 wsl2 中启动 Emacs,组合的 Emoji 会导致 buffer 渲染错误

有一个类似的帖子。

或许 @lgfang 的方案可行。

修改后 , scrach buffer 里显示 下面内容还是有问题


# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**


# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**

# 🏖️ OSS Vacation

**Issue tracker and PRs reopen March 2, 2026.**


emoji 还是有问题

>>> s = "🏖️"
... for ch in s:
...     print(hex(ord(ch)), ch)
...
0x1f3d6 🏖
0xfe0f

我有观察到这个emoji实际上是 U+1F3D6U+FE0F, 它后面跟了 个 Variation Selector 16

就是说这种组合emoji显示为一个,但是实际占位依旧是二。光标在这个emoji上运动的时候看的很清楚,得走两步。

甚至有些终端没办法组合还会直接显示两个完全不同的符号。

不支持组合的终端:

支持组合的终端:

Screenshot From 2026-03-04 13-30-01

我在这个帖子中发现了类似的问题

单个 emoji 不会错位,如果当前屏幕内容有某一行包含多个 emoji,又用了 C-n, C-p 这类按键,就会导致显示异常,得手动 C-l 刷新纠正

这种是通过vim打开的情况。

这种是helix在kitty中打开的情况。

这些都是异常的情况,大致可以分为三类,第一类,最开头的那部分看起来正常,用helix打开会看到光标在emoji的时候只显示一半;第二类和第三类都是二合一,但是第三类也是光标占占一半。

你把(setq-default auto-composition-mode nil)加到配置文件里后重启emacs了吗?

我用你的文本试了一下。下图左边含 (setq-default auto-composition-mode nil), 右边没有。

  • 左边能够“正常”显示buffer,只是含ZWJ的emoji(例如buffer中第一个emoji)没有合成一个字符,而是显示成3个字符。但至少可以正常查看编辑
  • 右边在我按了几次 C-l 后显示完全不正常。甚至前面几行都消失了。

  • GNU Emacs 30.1 (build 1, aarch64-apple-darwin21.6.0, NS appkit-2113.65 Version 12.7.6 (Build 21H1320)) of 2025-02-25
  • wezterm 20240203-110809-5046fc22
  • macOS 26.3 (25D125)

有意思