separedit.el: 在单独的缓冲区编辑注释、docstring 或其中的代码块

的确。选中区域编辑有问题,自动探测区域正常。我稍后看看怎么回事。

好的,麻烦大佬了,时间也不早了,大佬早点休息


ps:我是把 expand-region 这个插件提供的功能绑定在 C-c " 键上,没想到意外测出了这个问题。。。

另外,我一直以为 C-c <key> 默认是留给用户定义的,结果有天发现 C-c " 键在 org-mode 里不起作用,发现是 org-mode 占用了 C-c " 键,然后我就把用的插件都绑到 C-c [a-z] 这些键上了 :joy:

编辑选中区域的问题应该解决了。


C-c <key> 应该是留给用户自定义的,我印象中以前如果包里绑定了这些按键 package-lint 会警告,现在好多了[1],可能不遵循的人太多了吧。

[1] Don't warn on legitimate C-c key sequences (fixes #81) · purcell/package-lint@d9b18fa · GitHub

多谢大佬,我这边使用功能正常;但如果我想给 elixir 添加支持的话,该怎么做?

我试着给 separedit-string-quotes-alist 添加上 elixir-ts-mode 后,在 """ ... """ 区域内调用 separedit 时,编辑 buffer 的 major-mode 还是 separedit-double-quote-string-mode

(defcustom separedit-string-quotes-alist
  '((python-mode     . ("\"\"\"" "'''" "\"" "'"))
+   (elixir-ts-mode  . ("\"\"\"" "\"" "'"))
    (js-mode         . ("\"" "'" "`"))
    (lua-mode        . ("\"" "'" (or (seq "[" (zero-or-more "=") "[")
                                     (seq "]" (zero-or-more "=") "]"))))
    (nix-mode        . ("''" "\""))
    (typescript-mode . ("\"" "'" "`"))
    (separedit-double-quote-string-mode . t)
    ...)

如果我把这一行加上 elixir-ts-mode,调用 separedit 倒是会用 separedit-default-mode 但应该不是正确添加 elixir 支持的做法吧?

-      (and (derived-mode-p 'python-mode 'python-ts-mode)
+      (and (derived-mode-p 'python-mode 'python-ts-mode 'elixir-ts-mode)

按键规范的话,Emacs 倒是有个文档,但我愣是没看懂说的啥,上面写着:

  • 只有 C-c letter 和 f5-f9 是留给用户自定义的

这里明确写了 letter 囊括大小写、ascii 和非 ascii 字符(按理说,punctuation 这种标点符号不也是 ascii 字符),然后下面来了条

  • C-c <punc> 是留给 minor mode 的

所以我最后干脆都改成 C-c [a-z]

添加对新语言的支持:

  1. 添加匹配注释头/尾的正则表达式 separedit-comment-encloser-alist.
  2. 添加匹配注释行(不包括头尾)的正则表达式 separedit-comment-delimiter-alist.
  3. 添加匹配字符串(包括 Docstring)引号的正则表达式 separedit-string-quotes-alist.
  4. 如果 Docstring 里边有缩进,应在 separedit-string-indent-offset-alist 定义
  5. 如果该语言没有 Docstring (例如c/c++)添加到 separedit-not-support-docstring-modes
  6. *-ts-mode 可以在 separedit-treesit-major-mode-alist 中映射

类似 python 的语言可以直接搜索关键字照着写。

我的主要问题是这里的处理(抱歉,俺太菜了)

看着像是对 python 专门的处理,如果加上 elixir,调用 separedit 就是 separedit-default-mode,不加的话就是 double-quote-mode:跟我昨晚问的问题一样。。

在添加 elixir 支持的时候发现一个问题

python-mode 和 python-ts-mode 是并存的,这两者都基于一个 python-base-mode

但是 elixir-ts-mode 是个独立的 mode(30.0.50 后 Emacs 内置),如果我这样放

(defcustom separedit-treesit-major-mode-alist
  '((c-mode             . c-ts-mode)
    (c++-mode           . c++-ts-mode)
    (cmake-mode         . cmake-ts-mode)
    (conf-toml-mode     . toml-ts-mode)
    (csharp-mode        . csharp-ts-mode)
    (css-mode           . css-ts-mode)
    (dockerfile-mode    . dockerfile-ts-mode)
+   (elixir-mode        . elixir-ts-mode)
    (go-mode            . go-ts-mode)
    (java-mode          . java-ts-mode)
    (json-mode          . json-ts-mode)
    (js-json-mode       . json-ts-mode)
    (js-mode            . js-ts-mode)
    (python-mode        . python-ts-mode)
    (rust-mode          . rust-ts-mode)
    (sh-mode            . bash-ts-mode)
    (typescript-mode    . typescript-ts-mode))
  "Alist maping major modes to corresponding treesit modes."
  :group 'separedit
  :type 'alist)

在把 elixir-mode 添加到 separedit-comment-delimiter-alist 中后,使用 separedit 就会报错,提示找不到 elixir-mode

啊,好复杂。。


已经推送到我的 fork 了,大佬抽空可以看下是什么原因吗

我运行了你的修改,elixir{,-ts}-mode 两个模式没发现问题:

$ git --no-pager diff -U0
diff --git a/separedit.el b/separedit.el
index 6fe531c..19e76cf 100644
--- a/separedit.el
+++ b/separedit.el
@@ -404 +404 @@ Taken from `markdown-code-lang-modes'."
-    ;;(elixir-mode        . elixir-ts-mode)
+    (elixir-mode        . elixir-ts-mode)


$ emacsq.sh -ud ~/.emacs.d -ed ~/.emacs.d/29.0.60/elpa -P elixir-ts-mode,separedit --eval "\
  (progn
    (setq separedit-preserve-string-indentation t)
    (global-set-key (kbd \"C-c '\") #'separedit)
    (switch-to-buffer \"*.elixir\")
    (elixir-ts-mode)
    (insert \"\
  defmodule Foo do
    @moduledoc \\\"\\\"\\\"
    Foo-related functions.

    ## Examples

        iex> Foo.sum(1, 2)
        3

    \\\"\\\"\\\"

    @doc \\\"\\\"\\\"
    Calculate the sum of two numbers.
    \\\"\\\"\\\"
    def sum(a, b), do: a + b
  end\")
    (goto-char 61))" -nw

步骤:

  1. C-c ' 编辑 docstring,提交。
  2. 选中一块 docstring,按 C-c ' 选 markdown-mode,编辑,提交。
  3. 插入一行 # comment,按 C-c ' 编辑,提交。

我电脑上是没有 elixir-mode 的,难道是这个原因吗

我的问题,忘记详细说明了问题出在什么地方了,不好意思

# abc <- 把光标放在这里
def foo do
  # ...
end

把光标放在箭头指的地方

如果是在 abc 这些字符上,在没有注释 (elixir-mode. elixir-ts-mode) 的情况下,我会报找不到 elixir-mode 的错,注释掉后可以正常编辑注释

如果是放在 c 后面的空格,无论是否注释 (elixir-mode . elixir-ts-mode) 会显示 Not inside a edit block

这个问题我刚才已经修复了,稍后更新。

好的

那这个问题大佬你那边可以复现吗?我现在 30.0.50 版本可以稳定复现,电脑上只有 elixir-ts-mode,没有 elixir-mode

我发现在 *-ts-mode 下,在形如 /* ... */ 这样的注释中调用 separedit 都会出现问题,而不是基于 tree-sitter 的 major-mode 就正常

例如在这样的注释下触发 separedit,会把前面的星号也带到编辑 buffer 中,如果不是 *-ts-mode 就能正常工作

因为我一开始就把 LANG-ts-mode 转成 LANG-mode 处理了,正确应该是必要的时候才转。

也是上边的原因。

一会我会把这个问题都修复了,顺便把对 elixir 的支持也加上,你看看哪里不对提个补丁。

另外吐槽一下 elixir-ts-mode,它的高亮行为跟 elixir-mode 差很大(虽然其它语言多少也存在些差异,但没这么离谱的),不知是 bug 还是它必需这么设计。首先在探测 docstring 的时候 (syntax-ppss) 根本不管用,然后选区的 overlay 也很迷惑:在移动 point 的时候它会整片刷新。

emacs-syntax-ppss-elixir-mode

emacs-syntax-ppss-elixir-ts-mode

emacs-retion-face-elixir-ts-mode

1 个赞

大佬辛苦了,我今天不在家,等明天试试新版本

高亮行为这个,我之前想在 elixir-ts-mode 里新添个功能,发了封邮件,作者说在写跟语法相关的东西,不知道这个后面会不会变,也不知道会不会影响现在 separedit 里的功能

https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-03/msg01862.html

刚刚试了一下,其他的都符合预期,但是 elixr-ts-mode 里的行为不对

# comment

对于这样的注释 separedit 可以正常工作


但对这种换行字符串,有新的问题

@doc """
  aaa
"""

把光标放在 aaa 上,调用 separedit,separedit 只会识别最外层的 ",然后把内层的都视为字符串,然后就调用了 double-quote-string 那个 mode

图片

并且对于像这种的语句,识别起来也有问题

图片

如果是 elixir-ts-mode 的问题,那大佬要不干脆把对 elixr-ts-mode 的支持去掉吧,我直接选中区域后再编辑也不是啥麻烦事 :joy:

你需要在配置文件中添加 (add-to-list 'major-mode-remap-alist '(elixir-mode . elixir-ts-mode))

目前还是采用 LANG-mode 作为 LANG-ts-mode 的后备,不过优先顺序校先前有做调整。

啊,这个样子果然可以了

但是像我这种没安装 LANG-mode 的人,用起来就会有些问题。比如说 typescript-mode,现在他们在 readme 里已经推荐用 Emacs29 内置的 typescript-ts-mode 了。如果我现在没有装 typescript-mode,而是使用 Emacs29 内置的 typescript-ts-mode 时,在编辑这种注释时就有问题

/*
 * aaa
 * bbb
 */

如果在配置里加上了 (add-to-list 'major-mode-remap-alist '(typescript-mode . typescript-ts-mode)) 就正常了

不需要安装 typescript-mode,只是需要添加 remap 即可。

我是这么考虑的,目前 LANG-mode 应该还是主流,而 LANG-ts-mode 还在完善当中。remap 可以快速支持尽可能多的 ts 模式,有问题的遇到再解决,没问题正好。

嗯,我知道。只是没装 LANG-mode,而是直接用 LANG-ts-mode 的用户,一般也不会在配置里添加相关的 remap 吧。我个人觉得 remap 这一步操作是不是在 separedit 里做更好一些:

在 separedit 里 defcustom 一个 remap 变量,继承用户 Emacs 配置中的 major-mode-remap-alist(如果有的话),之后在此基础上加上 separedit 默认支持的 major-mode,用户也可以自己去修改这个变量


ps:当然这主要是对我来说,Emacs 里没有 elixir-mode 和 typescript-mode,却要在 major-mode-remap-alist 里添加这两个 mode 的 remap,总感觉怪怪的。。

原先有一个 remap 变量的,我感觉重复了,又删了 Fix regexps for *-ts-mode · twlz0ne/separedit.el@d92e957 · GitHub

的确是个问题。可以考虑加回去。

1 个赞