讨论一下 Emacs 中的 UTF-8 编码设置

挺奇怪的,只有一个文件有这个问题,而且每次设置完 utf-8-dos 后,kill掉buffer再打开,就会多一个^M

不管了,我直接git恢复了。编码问题是真的奇怪,我发现有的buffer是 prefer-utf-8-dos, 有的是 utf-8-dos

这个是真的怪,可能是因为你这个 buffer 默认没有指定编码类型。

可见版本控制是多么重要。:smile:

总结一下:
在 Windows 系统下尝试了以下两种配置:

(set-locale-environment "en_US.UTF-8") 
(set-language-environment "UTF-8")

大部分情况下正常,但都没法解决在 M-x shell 出现乱码的问题。

所以目前我还是用回以前一直使用的配置:

这个配置其实是从 Purcell 的配置中来的,用了几年了。

至于个人Emacs 配置的跨平台分享,目前 Git 设置如下,保证Github 中都是 LF换行符:
在 macOS 和 Linx 系统中

 git config --global core.autocrlf input # 只有在 pull 的时候转为 Unix 编码的 LF 换行

在 Windows 中自动转为 dos 编码的 CRLF 换行

 git config --global core.autocrlf true # 在 clone 和 pull 的时候转为 `CRLF`,在 push 时转为` LF`

对于有的项目,如果只用于 Windows 平台,就在项目中加入.gitattributes 文件,设置需要的回车换行风格为 CRLF,不需要自动转换。这个文件的设置会忽略 Git 的全局设置。

参考Github 文档 :

2 个赞

describe-current-coding-system比较两种方案的区别,发现只用set-language-environment其实是可以的

(set-language-environment "UTF-8")
(prefer-coding-system 'gbk)
(prefer-coding-system 'utf-8)

如上设置,shell 不会出现乱码在windows上

1 个赞

看了下 set-locale-environment 的代码,实际上就是多修改了几个变量,同时根据输入的参数来合适地调用set-language-environment 。而且还对各系统做了一些特殊处理貌似,对于windows也就是一些变量保持windows默认,其他的就是多设置一点这样。

比如(set-locale-environment "en_US.UTF-8")实际上会执行

(set-language-environment "English")

这跟(set-language-environment "UTF-8")效果应该会不一样。(charset-priority-list)就会不一样,其他的由set-language-environment设置的变量都可能变化。

(set-locale-environment "UTF-8")除了多设置了几个变量以外,应该跟(set-language-environment "UTF-8")效果是一样的,因为前者就是直接调用了后者。

这带来了问题,实际上set-locale-environment并没有比set-language-environment多做多少工作,reddit原文上也只是理解成不推荐set-locale-environment而推荐set-language-environment,这就让人很费解。我觉得如果有问题,当然实际上也存在问题,set-language-environment也应该也有才正确。

Windows 上的编码问题很头痛,实在搞不清楚。

最近重装了 Windows 10 系统, 还是用下面的编码设置,但 M-x shell 没乱码了。系统用的默认区域设置。

最近又研究了下 Emacs 在 Windows平台 下的编码问题。

为了使不同平台共享方便,我要统一使用 UTF-8 编码。只在 early-init.el 中加入下面的代码:

(set-charset-priority 'unicode)
(prefer-coding-system 'utf-8)
(setq system-time-locale "C")

上面的设置可以解决的问题:

  • 解决 Haskell-mode 的 REPL 无法启动,或者 putStrLn 没法在 REPL 打印中文的问题。
  • 新建文件时默认使用的是 UTF-8 编码,而不是 GBK 编码
  • 保存 Buffer 时不会经常提示选择编码

但也产生了新的问题:

  • M-x run-python 中没法通过 print 打印中文,因为 python 默认使用的不是 UTF-8 编码。可以在参数中加入 -X utf-8 ,或者设置环境变量 PYTHONIOENCODING 的值为 utf-8, 就可以解决。

    (setq python-shell-interpreter-args "-i -X utf-8")
    ;; 或者在系统中创建,或者在 Emacs 中设置下面的环境变量
    (setenv "PYTHONIOENCODING" "utf-8")
    
  • 在右键菜单中设置 Open with Emacs (Emacsclient) 打开有中文名称的文件时,文件名会乱码。可以通过下面的设置解决

(when (eq system-type 'windows-nt)
  (setq file-name-coding-system 'gbk))
  • 默认输入法 default-input-method 人值由 nil 变为了 chinese-py-punct。我个人不用 C-\切换输入法,这个对我没影响。

如果其他地方还有问题的话,可以单独进行设置编码。这也是 Emacs 维护者 Eli 比较推荐的方式。 比如 sdcv 这个本地翻译程序比较老,输出内容还是 GBK 编译的,可以用以下设置进行针对性更改。

(add-to-list 'process-coding-system-alist '("sdcv" . (utf-8-dos . chinese-gbk-dos)))

平时遇到编码问题可以通过 M-x escribe-current-coding-system 查看当前 Buffer 的编码设置情况。

9 个赞

大佬,我在windows系统中dired下使用7z压缩中文名称的目录会报错。这个应该怎样设置编码啊? 在终端下使用7z是正常的

我都不知道在dired中怎么用7Z。你是怎么操作的?

@noalias 你试试这个设置?

(when (eq system-type 'windows-nt)
  (setq file-name-coding-system 'gbk))

我的配置如下:

(set-charset-priority 'unicode)
(prefer-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)
(setq system-time-locale "C")
(when base:win-p
    (set-file-name-coding-system 'gbk)))

(use-package dired-aux
  :defer
  :custom
  (dired-compress-directory-default-suffix ".7z")
  :config
  (add-to-list 'dired-compress-files-alist '("\\.7z\\'" . "7z a %o -r %i")))

对于纯英文文件名可以正常解/压缩。对于中文文件名会报错“系统找不到指定的文件”,此时文件名是乱码。

你试试这样设置行不行:

(add-to-list 'process-coding-system-alist '("7z" . (utf-8-dos . chinese-gbk-dos)))

我这边用你的配置按 Z 时还是用的 gzip 进行压缩。不过确实是有编码问题。我解压缩一般直接在 Windows 文件浏览器中进行,不习惯在 Dired中操作。

@noalias 这样设置应该就可以解决问题。我只测试了默认的 gzip 的情况,7z 的你试试看。

(add-to-list 'process-coding-system-alist '("cmd" . (gbk . gbk)))
(add-to-list 'process-coding-system-alist '("gzip" . (gbk . gbk)))
(add-to-list 'process-coding-system-alist '("7z" . (gbk . gbk)))
1 个赞

好的,感谢🙏

你好 有试过在dired中使用gpg4win吗,我加密英文文件时候正常,加密中文名字的文件就乱码,按照上面的设置

(setq file-name-coding-system 'gbk)

(add-to-list 'process-coding-system-alist '(“cmd” . (gbk . gbk)))

(add-to-list 'process-coding-system-alist '(“gpg” . (gbk . gbk)))

依然还是中文乱码。

我没在 dired 用过 gpg,我用gpg4win主要是用于 git 的签名验证时读取 signingkey。不知道在 dired中你是怎么操作的?能否给一个重现的步骤?

Windows下Emacs使用的shell应该是cmdproxy。 试下这个:

 (set-file-name-coding-system 'gbk)
 (modify-coding-system-alist 'process
                              (rx (or (and (or ?c ?C)
                                           (or ?m ?M)
                                           (or ?d ?D)
                                           (or ?p ?P)
                                           (or ?r ?R)
                                           (or ?o ?O)
                                           (or ?x ?X)
                                           (or ?y ?Y))
                                       "gm" "7z" "es" "fd" "rg"))
                               '(utf-8-auto . chinese-gbk-dos))))

gpg添加到rg后面。

遗憾 还是不行,但是谢谢

如果是已有文件打开是乱码,那就要已此文件生成时的编码格式重新打开,或者转换下Emacs设置的编码格式。

如果是设置为utf8了,打开utf8的文件中文还是乱码,尝试下这么设置:

;; Contrary to what many Emacs users have in their configs, you don't need more
;; than this to make UTF-8 the default coding system:
(defun init-coding-system-h ()
  (set-language-environment "UTF-8")
  ;; (set-locale-environment "en_US.UTF-8")
  ;; ...but `set-language-environment' also sets `default-input-method', which is
  ;; a step too opinionated.
  (setq default-input-method nil)
  ;; ...And the clipboard on Windows could be in a wider encoding (UTF-16), so
  ;; leave Emacs to its own devices.
  (eval-when! IS-WINDOWS
    ;;(setq selection-coding-system 'utf-8)
    (set-clipboard-coding-system 'utf-16-le)
    (set-selection-coding-system 'utf-16-le))
  ;; Treat clipboard input as UTF-8 string first; compound text next, etc.
  (if (display-graphic-p)
      (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))))
(add-hook 'before-init-hook #'init-coding-system-h 'append)

感谢费心写代码,其实是dired中使用epa加密文件时提示中文字符乱码,我觉得是读取文件名称时候哪里出错了,但是用了各种大哥的设置,还是不行