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

可以把 @swagger 当作一个 code block 来处理:

(add-to-list 'separedit-block-regexp-plists
             '(:header "@swagger$"
               :body nil
               :footer ".*\\'"
               :mode yaml-mode))

这样就不用手动选区域和 mode 了,直接在 yaml 内容上按 C-c '

EDIT1:由于目前 separedit--code-block-end 在找到 block 末尾之后会自动退回一行,所以以上方法得到的可编辑内容会缺少一行,稍后我将提供一个更完善的解决方案。

EDIT2:已添加对 swagger-jsdoc 的支持,直接拉取最新的代码或等待 melpa 更新。

十分感谢,使用下来一切正常。 :smiley:

除了上述的 swagger-jsdoc 之外,自 v0.3.0 以来的新功能:

  • 支持无窗口模式(separedit-inhibit-edit-window-p)。
  • 允许用 heredoc 标记指定编辑模式(忽然觉得支持 heredoc 的语言都很可爱):
# example.rb            -- C-c ' ->  # edit buffer (sql-mode)
query = <<-SQL
SELECT * FROM #{table}               SELECT * FROM #{table} 
WHERE #{type} = true                 WHERE #{type} = true
SQL
1 个赞

如果 heredoc 也支持了,那是否意味着编辑 C 的宏也是原生就支持的?

例如这样的宏定义:

#define FOO(a, b)                               \
    do {                                        \
        auto _a = (a);                          \
        auto _b = (b);                          \
    } while (false)

在这个宏上调用 separedit-dwim 的话会变成

do {
    auto _a = (a);
    auto _b = (b);
} while (false)

现在我的作法是使用 edit-indirect-region,需要:

  1. edit-indirect-before-commit-hook 里给每一行末尾添加一个 \
  2. edit-indirect-after-creation-hook 里把 \ 给去掉

但是我感觉和 separedit 的功能有点像。另外还有个问题是 edit-indirect 默认用 normal-mode 来猜 mode,太卡了

@twlz0ne JS/TS 中常用的块注释不能正常解析,是 melpa 上的最新版本:

  /**
   * Renders instance on a given context
   * @param {CanvasRenderingContext2D} ctx context to render instance on
   */
  transform(ctx: CanvasRenderingContext2D) {
    // .....
  }

最好能提供截图、复现代码或条件,否则单凭“不能正常解析”我想象不出结果。

以下是我的测试代码 (emacsq.sh 来自 GitHub - twlz0ne/emacsq-sh: Helper script to run `emacs -Q`):

$ emacs --batch --eval "(with-temp-buffer (emacs-version 'here) (message (buffer-string)))"
GNU Emacs 28.0.50 (build 6, x86_64-apple-darwin17.7.0, NS appkit-1561.61 Version 10.13.6 (Build 17G14033))
 of 2021-09-13

$ emacsq.sh -P separedit --eval \
          "(progn
             (define-key prog-mode-map (kbd \"C-c '\") #'separedit)
             (switch-to-buffer \"*.js\")
             (js-mode)
             (insert \"/**
            * Renders instance on a given context
            * @param {CanvasRenderingContext2D} ctx context to render instance on
            */
           transform(ctx: CanvasRenderingContext2D) {
             // .....
           }\"))" -nw

在我的电脑上并未发现问题:

你的 major mode 是什么?separedit 是根据 face 来提取编辑范围的,在 c-mode 下应该无法这样使用才对。

这我倒是没注意到,最然我用的是 2011 年的破电脑。

这里少了一个假设,假设这个结果是通过 edit-indirect 来实现的,或者是提供一种 C-u separedit-dwim 的方式来自定义是想要选择哪种样式:

  1. 在注释里写代码,从 uncomment-region 编辑 → comment-region 返回
  2. 编辑 C 的宏,从去掉尾部 \ 开始编辑 → 给每行加 \ 再返回
  3. heredoc 的形式,从 <<-IDID 的 region 开始编辑 → 再把前缀给加回去
  4. 其他的暂时没想到,不知这种通用性是否已经存在于 separedit 中了

个人感觉是存在这种相关性的

抱歉,昨天急着出去没描述清楚

出现问题的环境是 typescript-mode,但 js-mode 是没有问题的,下面是我真实操作的截图:

下面是关于这张图的说明:

  1. 图片的 1 是明确指示 typescript-mode
  2. 图片的 2 是指示错误的地方,多了注释的引导符号;
  3. 可以发现注释的部分少了一部分内容,也就是注释中以 @param 开头的那一行;
  4. 如果把注释引导符号更改为 /*,那注释编辑的部分就正常了,但是语法高亮就不对了,请参考下面截图;

解释一下第二张图:

  1. 图片中的 1 是更改了注释引导符号,更改后的引导符号是 /*:只有一个 * 了:但是不能这么改,会导致注释生成出现异常;
  2. 图片中的 2 是语法高亮异常了,但注释编辑好了:我怀疑是 typescript-mode 对注释有语法解析,导致不能正常解析注释中的全部文案了;

以上,就是我在这次 Bug 调试过程中得到的全部信息了。

想问下怎么给 separedit-comment-encloser-alist 这个变量添加新的配置呢?我需要添加一个 web-mode 的支持,因为目前写前端使用 web-mode 比较多。小白请求,如有不适请忽略 :joy:

  1. typescript 的问题比较简单,加几个 face 就改好了。
  2. web-mode 比较麻烦,目前有 40 种 engines,最少有 40 种以上的注释形式。如果全部揉成一个正则表达式,有可能会出问题。应该针对每一种 engine,给相对应的注释匹配正则。我可能要挑其中比较常用的几种,其余的等有人用到了再说吧。

EDIT: web-mode 的注释有点错乱:

$ emacsq.sh -P web-mode --eval \
  "(dolist (buf '(\"*.js\" \"*.jsx\" \"*.css\"))
   (switch-to-buffer buf)
   (web-mode)
   (print (list :content-type web-mode-content-type
                :comment-start comment-start)))" -nw --batch
;; => (:content-type "javascript" :comment-start "<!--")
;;    (:content-type "jsx"        :comment-start "<!--")
;;    (:content-type "css"        :comment-start "<!--")

不应该都是 /* 吗?

C-u separedit-dwim 目前用于选择 major mode,以编辑字符串/其它无法自动探明语言的代码。

主要问题在于,从一开始我的目标就只管北西南三面围栏的注释,不考虑四面包围和只有东面的情况。但是现在 separedit-dwim 已经很丑了,如果单独写一个东面围栏的还比较容易,让我想想怎么处理。

另外,这种用续行符 \ 连成块的宏是不是只存在于 c/c++?

了解了

应该是的

@Lenic @Youmu 获取最新代码试试。

  1. typescript 应该没问题。
  2. web-mode 是照着 web-mode.el - html template editing for emacs 的截图实现了常见 types 和 engines 下的注释编辑,不知道对不对。
  3. c/c++ 宏编辑的时候,因为需要在完成之后重新对齐 \,把 #define 也放入了编辑缓冲。主要功能已实现,还有些小问题:1. 不能在 #define 这行按 C-c '; 2. 进入编辑窗口后的光标位置飘了。
  1. typescript-mode 已经没问题了;
  2. web-mode 我试了下,还是不对,执行报错 Wrong type argument: listp, "/\\*+\\(?:!\\)?"

web-mode 报错的文件如下:

/**
 * abc<光标位置>
 */
const App = () => {
  // ..
};

文件扩展名是什么?web-mode-content-typeweb-mode-engine 是什么?

找到问题所在了。临 push 之前忽然想起要改一个地方,简单得不能再简单了,结果改漏了,没写测试就是不靠谱。

删除本地代码,重新获取,我刚刚强推了。

Excellent work! 虽然格式没有对齐,但是已经非常有用了!大写的赞!

完美 :+1:

缩进变了,还是行尾的 \ 没对齐?

行尾的 \ 不同于每一行开头的的 //,在行首只需插入固定长度,行尾需要对齐到最长的那一行。我用目前的方法是用 c-indent-region,它默认对齐到 72。而且该函数有可能会改变缩进,如果你是手动控制缩进(而不是按 TAB 缩进)就需要注意了。

另外 c-indent-region 需要 (setq c-auto-align-backslashes t),否则它不对齐 \


改为 (align-regexp (point-min) (point-max) "\\(\\s-*\\)\\\\$") 应该就可以避免上述的两个问题。

不过不能简单这样改,还是应该遵循 cc-mode 的设定。默认对齐到 72 (c-backslash-max-column),有超长行时对齐到最长行,如果 c-auto-align-backslashesnil 就不对齐?

我是在这个 commit 提交前测试的,现在已经完美缩进了。 :+1:

有个建议:

如果提交的内容与修改前一样,在使用 separedit-commit 提交时,还是会改变文件(会在退出emacs时提示是否要保存)。是否可以改成,如果提交的内容与之前一致,就不修改文件?或者添加一个选项让用户选择行为?

org-mode 在这种情况下是不修改文件的。

separedit-version: 0a2dc1a master origin/master fix(sh-mode): correct region detection of single quoted string (close #26)
emacs version: "GNU Emacs 29.0.50 (build 4, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2021-11-25"
org-version: 9.5