Как расширить режим emacs lisp с изменениями отступов и цветов - PullRequest
2 голосов
/ 02 сентября 2010

Я делаю DSL в lisp (в основном то, что я считаю более приятным синтаксисом), это то же самое, что lisp, за исключением разных «примитивов», нет вместо «as» вместо let. Таким образом, мне нужно изменитьи отступ, и цвет только в файлах, оканчивающихся на .goby (это не должно влиять на файлы, оканчивающиеся на .lisp). Поэтому я хотел бы создать файлы с расширением .goby и включить мой новый, вспомогательный / основной режим (но свсе остальное, кроме синтаксиса, унаследованного от lisp).

Однако, что бы я ни делал, это также влияет на файлы .lisp!Кто-нибудь?

Например, я попытался создать локальную переменную для уникального отступа lisp, которая бы делала отступ hi на 10 пробелов.но это также отразилось на всех файлах .lisp

;;in goby.el
(define-derived-mode
  goby-mode lisp-mode "Goby"
  "Major mode"
  (let ((func #'lisp-indent-function))
    (set (make-local-variable 'lisp-indent-function) func)
    (put 'hi 'lisp-indent-function 10)))


(provide 'goby)

;;in .emacs
(setq auto-mode-alist
      (append auto-mode-alist
          '(("\\.gy\\'" . goby-mode))))

1 Ответ

2 голосов
/ 02 сентября 2010

Возможно, есть более чистый способ, но способ, который работает, состоит в том, чтобы переписать 'lisp-indent-function, чтобы он стал 'goby-indent-function, и использовать собственную таблицу смещений, например, так:

(define-derived-mode
  goby-mode lisp-mode "Goby"
  "Major mode"
  (set (make-local-variable 'lisp-indent-function) 'goby-indent-function))

;; goby specific offsets here
(put 'hi 'goby-indent-function 10)
(put 'if 'goby-indent-function 4)

(defun goby-indent-function (indent-point state)
  "Same as 'lisp-indent-function but uses 'goby-indent-function symbol

This function is the normal value of the variable `goby-indent-function'.
It is used when indenting a line within a function call, to see if the
called function says anything special about how to indent the line.

INDENT-POINT is the position where the user typed TAB, or equivalent.
Point is located at the point to indent under (for default indentation);
STATE is the `parse-partial-sexp' state for that position.

If the current line is in a call to a Lisp function
which has a non-nil property `goby-indent-function',
that specifies how to do the indentation.  The property value can be
* `defun', meaning indent `defun'-style;
* an integer N, meaning indent the first N arguments specially
  like ordinary function arguments and then indent any further
  arguments like a body;
* a function to call just as this function was called.
  If that function returns nil, that means it doesn't specify
  the indentation.

This function also returns nil meaning don't specify the indentation."
  (let ((normal-indent (current-column)))
    (goto-char (1+ (elt state 1)))
    (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
    (if (and (elt state 2)
             (not (looking-at "\\sw\\|\\s_")))
        ;; car of form doesn't seem to be a symbol
        (progn
          (if (not (> (save-excursion (forward-line 1) (point))
                      calculate-lisp-indent-last-sexp))
              (progn (goto-char calculate-lisp-indent-last-sexp)
                     (beginning-of-line)
                     (parse-partial-sexp (point)
                                         calculate-lisp-indent-last-sexp 0 t)))
          ;; Indent under the list or under the first sexp on the same
          ;; line as calculate-lisp-indent-last-sexp.  Note that first
          ;; thing on that line has to be complete sexp since we are
          ;; inside the innermost containing sexp.
          (backward-prefix-chars)
          (current-column))
      (let ((function (buffer-substring (point)
                                        (progn (forward-sexp 1) (point))))
            method)
        (setq method (or (get (intern-soft function) 'goby-indent-function)
                         (get (intern-soft function) 'lisp-indent-hook)))
        (cond ((or (eq method 'defun)
                   (and (null method)
                        (> (length function) 3)
                        (string-match "\\`def" function)))
               (lisp-indent-defform state indent-point))
              ((integerp method)
               (lisp-indent-specform method state
                                     indent-point normal-indent))
              (method
               (funcall method indent-point state)))))))
...