2016-02-24 5 views
0

Я написал очень простой режим Emacs для 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 
) 

Однако, это не будет отступ последовательно. Я не могу точно описать, как он отступает, но он несовместим между вкладками и пробелами и длиной пробелов. Самое простое правило, о котором я могу думать, - всегда начинать новую строку в одном столбце, и табуляция всегда приводит вас к следующему столбцу, который кратен 4. Вкладки должны быть пробелами. Как это сделать, используя общий режим?

Как отметить определение режима, я неправильно использую встроенное лицо, потому что оператор-лицо не имеет цвета. Однако он выглядит уродливым.

+0

Что вы пробовали до сих пор, чтобы получить желаемое поведение отступа? – Thomas

ответ

1

Первые вещи сначала: я настоятельно рекомендую вам начать с define-derived-mode, а не с define-generic-mode, потому что первый будет плавно расти, чтобы приспособить полнофункциональный основной режим, тогда как define-generic-mode быстро накладывают ограничения, которые неудобно работать вокруг.

E.g. вы можете переписать код, как:

(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)) 

W.r.t ТКС и SPCs, «переключение между ними» является поведение Emacs по умолчанию (отношение в том, что TAB просто оптимизация, которую мы используем, когда это применимо). Если вам это не нравится, тогда введите (setq-default indent-tabs-mode nil) в ~/.emacs, а не в определение вашего основного режима, поскольку это личный выбор, не имеющий отношения к SML (который не отличает TAB и SPC, вопреки, скажем, Haskell).

Что касается отступов, которые вы предлагаете, вы можете начать с добавления (set (make-local-variable 'indent-line-function) #'indent-relative), который должен убедиться, что по умолчанию то же самое, что и предыдущая строка; и для «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, наконец, научился «автоматически расширить список».

Но мне очень интересно : почему бы просто не использовать существующий sml-mode, который находится в GNU ELPA?

+0

Спасибо за подробный ответ! Я прочитаю его более подробно , но я просто хотел ответить на ваш последний вопрос. Оба режима ocaml-mode (tuareg) и sml-mode имеют очень странные правила отступов, которые я нахожу достаточно расстраивающими, чтобы оправдать другой режим с более простыми правилами. – eatonphil

+0

Предлагаю вам попробовать параллельный подход, когда вы спрашиваете, как получить sml-режим, чтобы отступывать ваш код так, как вам нравится. – Stefan

+0

Учитывая информацию, которую вы предоставили об отступе, казалось бы, что-то отличное от конкретного режима, который я использую, параллельный подход, вероятно, имеет смысл. Тем не менее, я также рад возможности разработать режим. – eatonphil