如何检测当前字符是否是该主要模式的注释字符?


12

我正在研究将下一行拉到当前行的这个小功能。我想添加一个功能,以便如果当前行是行注释,而下一行也是行注释,则在“上拉”操作后将删除注释字符。

例:

之前

;; comment 1▮
;; comment 2

呼唤 M-x modi/pull-up-line

;; comment 1▮comment 2

请注意,;;删除了以前的字符comment 2

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      (while (looking-at "/\\|;\\|#")
        (delete-forward-char 1))
      (when (looking-at "\\s-")
        (delete-forward-char 1)))))

上述功能的作品,但就目前而言,无论是主要模式,它将考虑/;#作为注释字符:(looking-at "/\\|;\\|#")

我想使这条线更聪明;特定于主要模式。

感谢@ericstokes的解决方案,我相信以下内容可以涵盖我的所有使用案例:)

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      ;; Delete all comment-start or space characters
      (while (looking-at (concat "\\s<" ; comment-start char as per syntax table
                                 "\\|" (substring comment-start 0 1) ; first char of `comment-start'
                                 "\\|" "\\s-")) ; extra spaces
        (delete-forward-char 1)))))

您是否希望它足够聪明以处理不同的注释开始和结束字符以及多字符注释(例如C /* ... */)?
erikstokes

不,那是我所需要的。谢谢!
Kaushal Modi 2015年

@erikstokes出于好奇,您将如何处理C样式的注释?
Pradhan

该解决方案可立即处理多行注释,无需执行任何特殊操作,因为加入多行注释时无需删除任何字符。
Kaushal Modi 2015年

2
@Pradhan有comment-startcomment-end字符串在中c-mode(但不是c++-mode)设置为“ / *”和“ * /” 。而且这c-comment-start-regexp两种风格都匹配。加入后,先删除结尾字符,然后删除开头。但我认为我的解决办法是uncomment-regionjoin-linecomment-region让什么注释符是什么Emacs的担心。
erikstokes

Answers:


12

您可以使用语法表检查当前字符是否为注释字符:(looking-at "\\s<")。regexp \\s<将使用“ comment start”语法匹配任何字符;\\s>将与使用“注释结束”语法的内容匹配。

另一个选择是变量comment-start,它是comment-dwimand friends 插入的字符串。通常将其设置为注释开始字符加一些空格。


2

有一个更简单的解决方案,请在https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el上研究我的代码。

我不会在此处复制/粘贴所有代码。但这是关键点:

  • 注释具有自己的字体,在我的代码中搜索font-lock-comment-face和font-lock-comment-delimiter-face

  • 使用Emacs自己的API取消注释第二行,然后将其与第一行连接

它应该适用于任何明智的主要模式。

这个把戏不是我发明的。它实际上来自Emacs自己的代码(更具体地说,是flyspell)。因此,该解决方案应支持任何主要模式的flyspell支持


3
为了突出显示某些内容作为注释,它要求正确设置语法表,因此我怀疑这比查看语法的方法聪明。
wasamasa 2015年

正如我在代码中所记录的那样,我通过阅读Emacs自己的代码(实际上是flyspell)来学习了这一技巧。
chen bin

0

如果您正在为lisp代码(Elisp,Clojure,Scheme和Common Lisp)寻找此功能,那么您应该尝试lispy,一个叫做的函数可以lispy-fill完成这种事情。

如果您正在寻找其他语言的功能,那么您应该rebox2(已针对C和验证Python),一个名为的函数rebox-fill或另一个名为的函数来rebox-dwim执行这种操作。

它们都是很好的程序包,并且彼此不冲突,因为它们用于不同的主模式,并且它们(lispy-fillrebox-dwim)都绑定到M-q,非常简洁。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.