elisp对字符串的unicode支持的疑惑

elisp

#1

我相信这是一个重要的问题。 目前的各种编码方式乱七八糟,语言对它的支持也各式各样,像python用起来就很省心不要太操心编码问题,而C语言就要折腾各式各样的编码问题了。

我查了emacs-lisp的文档,发现有三个概念: string , unibytemultibyte。 我英语不好,读了半天也没能理解到底是什么意思。 我还找到了一篇文章:http://www.tuicool.com/articles/BZzENf 很尴尬,我又没看懂:joy:

在我浅薄的知识里,我觉得字符串应该有以下几种可能的形式:

  1. 由一个个的单字节构成,是字节串。类似python的bytes,需要结合一种具体的编码才能确定里面的内容。
  2. 构成元素是一个个的多字节。每一个多字节代表实际上的一个字符,类似python的str类型。

还希望有大神具体讲解下emacs-lisp对unicode的具体支持。:grin:


#2

。。。。 String,字符串,基本上大部分语言都有的概念。emacs-lisp的字符串概念和别的语言没有什么区别。 现在 emacs 默认支持 unicode(UTF-8),不需要什么额外配置。el文件里面直接可以上。 倒是以前用GBK的需要另外指定编码。


看了下URL里的文章,首先就提到现在Emacs内部的所有字符都是UTF-8,其他编码都是先转换然后再处理的。

Proper string comparison requires normalization.

然后一些UTF-8的字符可以用不同的编码表述,Emacs并不会自动识别,比较的时候要先转换。

(string= "nai\u0308ve" "na\u00EFve")
;; => nil
(string= (ucs-normalize-NFD-string "nai\u0308ve")
         (ucs-normalize-NFD-string "na\u00EFve"))
;; => t

不过如果不处理欧洲的一些语言的话似乎用不到这些。。


#3

楼主对编码不了解的话可以看看这篇: https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/


#4

编码问题我是清楚的,只是不了解emacs-lisp这门语言对其支持的具体细节。


#5

感谢回复 。主要问题在于我在使用emacs-lisp进行编写扩展的时候,发现关于字符串对中文支持的一些奇怪的行为。

比如说,我在使用web-server这个插件时,如果将GET请求的数据(带中文)回显给浏览器,一切正常显示。 但是如果我用emacs-lisp的print函数将其输出,则会发现输出的是一串乱码。 这迫使我将搞清楚emacs-lisp具体是如何区分这些东西的。

比如说,我找到了几个函数string-to-multibyte,string-to-unibyte等等,这不免让人疑惑,unibyte和multibyte是什么?它们底层是如何表示字符串的?而emacs-lisp又是如何理解它们的?


#6

根据你的问题我继续讲那篇文章。 Emacs ,如你所说,有那两种数据类型,unibyte multibyte 。 简单来说,unibyte 是原始码,在内部用整数来表示,比如a就是1,b就是2(只是比如,实际大概不是这样。),这样不管有多少种字都不怕(似乎这种编码是动态分配的)。这是用来定义数据的(我发的图片中白色的“中文”),因为Emacs自己不需要知道这是什么意思。字节前用反斜杠区分。实际上这类数据几乎不用处理。离开Emacs后就自动转化成对应的字符编码。

multibyte 就是直接用UTF-8了,用在String里,做些文字处理,比如统计字数。 但是有些字符不在Unicode 里面呢!比如一些生僻字。Emacs在UTF8 中额外加了些字符,利用unibyte 表示。

至于你提到的print问题,大概是没指定好对应的编码而已。其实解决这问题用不到这些知识。


#7

我的那个问题找到答案了,使用的decode-coding-string函数。 上一段demo:

(let (s1 s2 s3)
  (setq s1 "测试")
  (setq s2 (encode-coding-string s1 'utf-8))
  (setq s3 (decode-coding-string s2 'utf-8))

  (print (length s1))
  (print (length s2))
  (print (length s3))
  
  (print (string= s1 s2))
  (print (string= s1 s3))
)
2
6
2
nil
t

可以看见,还真的和python3挺像的。没encoding的长度为2,说明把每一个汉字作为一个基本的字符单元。encoding后长度为6,说明储存的是其utf8编码后的字节串。

最后弱弱的吐槽一句,作为一个 Emacs 论坛,为什么不能用org格式写帖子。


#8

org的一部分功能在Emacs以外的地方没有什么用。然后org的默认行为对于中文支持不是很好。


#9

After I pasted "λ" into my emacs(from my grandpa’s os):

enter image description here

More:

I realized my emacs have some problems with Unicode(other editors like sublime3 display them correctly), esp for lowercase greek symbols. Ditto for emacs -Q. In xah lee’s site, I found

(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8

But still, don’t work. What’s strange is on my laptop, these symbols always work fine with or without -Q.

Then I found this thread:

(require 'unicode-fonts)
(unicode-fonts-setup)

profile: image

problem solved. I went to project page:

As the manual warns, the choice of font actually displayed for a non-ASCII character is “somewhat random”.

IIUC, vanilla emacs’s support for Unicode is not good enough and sometimes some more configurations is necessary, that’s why the package unicode-fonts exists.