【问题标题】:How to define whole line comment syntax in Emacs?如何在 Emacs 中定义整行注释语法?
【发布时间】:2014-08-11 14:16:45
【问题描述】:

我希望序列// 在行首时开始注释。但在一行内它不应该启动任何 cmets。

// this is a comment
This is a URL: http://example.com

有可能吗?

【问题讨论】:

  • 嗨,它是什么语言的?
  • 为什么不可能?要检查一行的开头,有正则表达式^//
  • @Ehvince Emacs 使用 syntax tables 来处理 cmets(尤其是突出显示)。那里不可能使用正则表达式。有没有其他方法可以在 Emacs 中指定注释语法?

标签: emacs comments elisp


【解决方案1】:

你可以通过写syntax-propertize-function来做到这一点

我编写了一个示例主模式,如下所示。 内置解析的 Emacs 将调用您的 syntax-propertize-function,以便它可以在以 // 开头的行上手动设置 syntax-table 文本属性。

(define-derived-mode my-syntax-test-mode fundamental-mode
  "A major mode where // denotes a comment but only if it is at the beginning of a line."
  :syntax-table (make-syntax-table) 
  (setq mode-name "my syntax test")
  ;; our mode will use `apply-my-custom-syntax-table-appropriately' to manually set
  ;; the syntax-table text property on lines starting with //"
  (setq syntax-propertize-function 'apply-my-custom-syntax-table-appropriately)
  ;; change `comment-dwim` to handle this type of comments correctly
  (local-set-key [remap comment-dwim] 'my-comment-dwim))

(defvar my-custom-syntax-table
  ;; syntax table where // starts a comment and \n ends it
  (let ((table (make-syntax-table)))
    (modify-syntax-entry ?/ "< 1" table)
    (modify-syntax-entry ?/ "< 2" table)
    (modify-syntax-entry ?\n "> " table)
    table))

(defun apply-my-custom-syntax-table-appropriately (beg end)
  (save-excursion
    (save-restriction
      (widen)
      (goto-char beg)
      ;; for every line between points BEG and END
      (while (and (not (eobp)) (< (point) end))
        (beginning-of-line)
        ;; if it starts with a //
        (when (looking-at "^//")
          ;; remove current syntax-table property
          (remove-text-properties (1- (line-beginning-position))
                                  (1+ (line-end-position))
                                  '(syntax-table))
          ;; set syntax-table property to our custom one
          ;; for the whole line including the beginning and ending newlines
          (add-text-properties (1- (line-beginning-position))
                               (1+ (line-end-position))
                               (list 'syntax-table my-custom-syntax-table)))
        (forward-line 1)))))

(defun my-comment-dwim (arg)
  (interactive "*P")
  (require 'newcomment)
  (save-excursion
    (let ((comment-start "//") (comment-end "")
          (comment-column 0)
          ;; don't indent comments
          (comment-style 'plain))
      ;; create the region containing current line if there is no active region
      (unless (use-region-p)
        (end-of-line)
        (push-mark (line-beginning-position))
        (setq mark-active t))
      (comment-dwim nil))))

【讨论】:

  • 我不确定这里是否使用 font-lock,因为它的语法表也定义了高亮规则。
  • 不确定用于突出显示的语法表,如果您将字体锁定行从那里取出,您将不会在该模式下获得注释突出显示。但是,也许有更正确的方法来做到这一点。
  • 我已经删除了这一行,模式仍然提供突出显示(Emacs 24.3.1)。
  • 嗯,似乎我可能遇到了其他干扰,没有我将突出显示的行,但只有在我禁用并重新启用字体锁定模式之后。看起来你可能不需要它,非常酷。
【解决方案2】:

我会这样做:

(defvar my-foo-mode-syntax-table
  (let ((st (make-syntax-table)))
    ;; Add other entries appropriate for my-foo-mode.
    (modify-syntax-entry ?/ ". 12" st)
    (modify-syntax-entry ?\n "> " st)
    st))

(defvar my-foo-font-lock-keywords
  ;; Add other rules appropriate for my-foo-mode.
  ())

(define-derived-mode my-foo-mode nil "My-Foo"
  (setq-local font-lock-keywords '(my-foo-font-lock-keywords))
  ;; Add other settings appropriate for my-foo-mode.
  (setq-local syntax-propertize-function
              (syntax-propertize-rules ("./\\(/+\\)" (1 ".")))))

注意:不需要任何特殊的字体锁定规则,因为字体锁定会根据语法表自动为您突出显示 cmets。

【讨论】:

  • 好主意,但它不适合我。突出显示的评论消失了。
  • 我的水晶球告诉我你没有使用 Emacs-24.4,所以你一定收到了一些关于 setq-local 不存在的错误消息。
  • 对不起,这只是我的错误。
  • 我建议将正则表达式更改为[^/]\\(//\\) 以允许以多个/ 开头的cmets。
  • @Menschenkindlein:很好,虽然我的修复方式略有不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
相关资源
最近更新 更多