简体   繁体   English

Emacs将一致的缩进规则添加到generic-x模式

[英]Emacs add consistent indent rule to generic-x mode

I wrote a very simple Emacs mode for Standard ML: 我为Standard ML写了一个非常简单的Emacs模式:

;; sml syntax
(require 'generic-x)

(define-generic-mode
    'sml-mode                          ;; name of the mode
  '(("(*" . "*)"))                           ;; comments delimiter
  '("fun" "fn" "let" "val" "datatype" "type" "case" "of" "end" "structure" "struct" "signature" "sig")
  '(("=" . 'font-lock-builtin-face)
    ("|" . 'font-lock-builtin-face)
    (">" . 'font-lock-builtin-face)
    ("<" . 'font-lock-builtin-face)
    ("-" . 'font-lock-builtin-face)
    ("+" . 'font-lock-builtin-face)
    (";" . 'font-lock-builtin-face)
    ("," . 'font-lock-builtin-face)
    ("{" . 'font-lock-builtin-face)
    ("}" . 'font-lock-builtin-face)
    ("(" . 'font-lock-builtin-face)
    (")" . 'font-lock-builtin-face)
    (":" . 'font-lock-builtin-face)
    ("[" . 'font-lock-builtin-face)
    ("]" . 'font-lock-builtin-face))     ;; a built-in
  '("\\.sml$")                    ;; files that trigger this mode
  nil                              ;; any other functions to call
  "SML highlighting mode"     ;; doc string
  )

However, it will not indent consistently. 但是,它不会一致地缩进。 I can't describe exactly how it indents, but it switches inconsistently between tabs and spaces and length of the spaces. 我无法确切描述它是如何缩进的,但是它在制表符和空格以及空格长度之间的切换不一致。 The simplest rule I can think of is to always start a new line on the same column and tabbing always takes you to the next column that is a multiple of 4. Tabs should be spaces. 我能想到的最简单的规则是,总是在同一列上开始新行,而制表键总是将您带到下一个4的倍数的列。制表符应为空格。 How can I do this using the generic mode? 如何使用通用模式执行此操作?

As a note on the mode definition, I am using the builtin-face incorrectly because the operator-face had no coloring. 作为有关模式定义的注释,我错误地使用了内置面,因为操作员面没有颜色。 It does look ugly now though. 现在看起来确实很丑。

First things first: I strongly recommend you start with define-derived-mode rather than with define-generic-mode because the former will seamlessly grow to accomodate a fully-featured major mode whereas define-generic-mode will quickly impose limits that are inconvenient to work around. 首先:我强烈建议您从define-derived-mode开始,而不是从define-generic-mode因为前者将无缝增长以适应功能齐全的主模式,而define-generic-mode将迅速施加不便的限制工作。

Eg you could rewrite your code as: 例如,您可以将代码重写为:

(defvar sml-mode-syntax-table
  (let ((st (make-syntax-table)))
    ;; Make (*...*) a comment.
    (modify-syntax-entry ?\( "()1" st)
    (modify-syntax-entry ?\) ")(4" st)
    (modify-syntax-entry ?\* ". 23n" st)
    st))

(defvar sml-font-lock-keywords
  `((,(concat "\\_<" 
              (regexp-opt '("fun" "fn" "let" "val" "datatype" "type" "case" "of" "end" "structure" "struct" "signature" "sig"))
              "\\_>")
     (0 font-lock-keyword-face))
    ("[][=|><-+;,{}():]" (0 font-lock-builtin-face))))

;;;###autoload
(define-derived-mode sml-mode prog-mode "SML"
  "SML major mode."
  (set (make-local-variable 'comment-start) "(* ")
  (set (make-local-variable 'comment-end) " *)")
  (set (make-local-variable 'font-lock-defaults)
       '(sml-font-lock-keywords)))

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.sml\\'" . sml-mode))

Wrt TABs and SPCs, "switching between them" is the default Emacs behavior (the attitude being that TAB is just an optimisation which we use when it's applicable). Wrt TAB和SPC,“在它们之间切换”是Emacs的默认行为(态度是TAB只是我们在适用时使用的一种优化)。 If you don't like it, then put (setq-default indent-tabs-mode nil) in your ~/.emacs and not in your major mode's definition since that is a personal choice unrelated to SML (which does not distinguish TABs and SPCs, contrary to, say, Haskell). 如果你不喜欢它,然后把(setq-default indent-tabs-mode nil)你的 ~/.emacs而不是在你的主要模式的定义,因为这是SML无关个人的选择(不区分标签和SPC与Haskell相反)。

As for the indentation you suggest, you could start by adding (set (make-local-variable 'indent-line-function) #'indent-relative) which should make sure that by default indentation is just the same as the previous line; 至于您建议的缩进,您可以先添加(set (make-local-variable 'indent-line-function) #'indent-relative) ,以确保默认情况下缩进与前一行相同; and for the "TAB should advance by 4 columns" maybe something like (set (make-local-variable 'tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64)) would do the trick (in more recent Emacsen, '(4 8) is sufficient because Emacs finally learned to "auto-extend the list". 对于“ TAB应该前进4列”,可能会像(set (make-local-variable 'tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64))这个技巧(在最近的Emacsen中, '(4 8)就足够了,因为Emacs最终学会了“自动扩展列表”。

But I'm curious: why not just use the existing sml-mode that's in GNU ELPA? 但是我很好奇:为什么不只使用GNU ELPA中现有的sml-mode

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM