join-line 中字符之间的分隔符

emacs 里 join-line 合并连续的两行的时候, 会调用 fixup-whitespace 在原来的行末字符前插入一个空格. 对于英文这些用空格做分隔符的语言来说是没问题, 但是对中文, 日文这些不需要分隔符的语言就不正确. vim 在这方面的处理也是不对的.

有没有什么方法来纠正呢?

:help gJ 或者

set formatoptions+=B 然后 vim 就能正确处理中英文了。

2 个赞

直接输入分隔符

  (evil-define-operator maple/evil-join (beg end)
    "Join the selected lines."
    :motion evil-line
    (let ((sep (read-string "Separator: "))
          (count (count-lines beg end)))
      (when (> count 1)
        (setq count (1- count)))
      (goto-char beg)
      (dotimes (_ count)
        (join-line 1)
        (delete-horizontal-space)
        (insert sep))))

嗯,是一个思路。我本来考虑根据周围字符所属字符集来判断,但是似乎不太好实现。

其实正则[[:multibyte:]]就可以判断CJK字符了

1 个赞

说起正则了,正好请教一下。我想清除两个汉字,或者一个汉字和一个英文之间的空格,但是两个英文之间的空格不删除。这能用一个正则写出来不?

多个字节未必就是cjk字符吧?我尝试的是 char-charset,不过除了ascii字符之外,其他的字符基本都给的unicode.

一般multibyte够用,准确匹配CJK用"\\cc\\|\\cj\\|\\ch"

等效

(rx (or (category chinese)
               (category japanese)
               (category korean)))
5 个赞

可以研究下rxreplace-regexp-in-string的docstring。我写了个,不过老是出问题,不知道为什么

(defun cm/cleanup-whitespace (s)
         (save-match-data
           (let ((cjk '(+? (or (category chinese) (category japanese) (category korean))))
                 (alnum '(+? (category latin))))
             (if (string-match (rx-to-string `(or (and ,cjk (group " ") ,cjk)
                                                  (and ,cjk (group " ") ,alnum)
                                                  (and ,alnum (group " ") ,cjk)))
                               s)
                 (replace-match "" nil t s 1)
                 s))))

是啊,我现在就是用了3和正则替换实现的,不知道有没有更简单的方法

或者按空格split之后再手动join

(define-advice fixup-whitespace (:override ())
  (interactive "*")
  (save-excursion
    (delete-horizontal-space)
    (if (or (looking-at "^\\|$\\|\\s)\\|\\cc\\|\\cj\\|\\ch")
	    (save-excursion (forward-char -1)
			    (looking-at "$\\|\\s(\\|\\s'\\|\\cc\\|\\cj\\|\\ch")))
	nil
      (insert ?\s))))

若 point 兩端有 CJK 字符,則取消空格,這個做法比較粗糙,可以自己細化一下。Emoji 之類的亦應考慮,可能 [[:multibyte:]] 是較好的選擇。

UPDATE:改用 advice。

1 个赞