2014-03-04 31 views
7

我不喜歡如何在Elisp中縮進plists定製Elisp plist indentation

;; current desired Python (for comparison) 
;; '(a 1  '(a 1  {'a': 1, 
;;  b 2  b 2  'b': 2, 
;;  c 3) c 3)  'c': 3} 

試戴M-X的emacs版本 24.3.1,跑emacs -Q,鍵入的plist中並壓C-x高C-M- \

這凹痕是有道理的,當它不是一個列表:

(mapcar (lambda (x) (x + 1)) 
     '(1 2 3 4)) 

如何更改格式設置,以便唯一的Plist(或者,如果這是不可能的,所有報價列表)具有所需的矩形縮進,但縮進的一切保持不變?我需要將它存儲在.el文件的本地文件中,這樣,當我編輯此文件時,它會根據需要進行縮進,但此行爲不會在其他任何地方結束。

+0

由於這個原因和其他許多原因,我建議使用alist而不是plists。 – Stefan

回答

6

發現:

(setq lisp-indent-function 'common-lisp-indent-function) 

下面是一個示例文件:

(setq x '(a 1 
      b 2 
      c 3)) 

;;; Local Variables: 
;;; lisp-indent-function: common-lisp-indent-function 
;;; End: 

我就甩我的整個縮進配置在這裏:

(setq lisp-indent-function 'common-lisp-indent-function) 
(put 'cl-flet 'common-lisp-indent-function 
    (get 'flet 'common-lisp-indent-function)) 
(put 'cl-labels 'common-lisp-indent-function 
    (get 'labels 'common-lisp-indent-function)) 
(put 'if 'common-lisp-indent-function 2) 
(put 'dotimes-protect 'common-lisp-indent-function 
    (get 'when 'common-lisp-indent-function)) 
+0

爲什麼你需要它的文件本地?該文件說它可能有風險:) –

+1

因此,用戶從你那裏得到的文件,並希望編輯它? –

+0

我仍然不明白用戶應該如何編輯一個庫。他們是否將這些變化傳回給你? –

1

可以解決這個問題(在我的意見)通過覆蓋lisp-indent-function錯誤。破解的最初來源是this Github Gist,這是從this Emacs Stack Exchange answer引用一些更多的解釋。

但是,我很不自在地重寫這樣的核心功能。首先,它是非常不透明的 - 讀者應該怎麼說出改變了什麼?更糟糕的是,如果將來的lisp-indent-function的官方定義發生了變化,該怎麼辦?我怎麼知道我需要更新我的黑客?

作爲迴應,我創建了專門用於解決此問題的庫el-patch。安裝軟件包後,您可以覆蓋lisp-indent-function,如下所示:

(el-patch-defun lisp-indent-function (indent-point state) 
    "This function is the normal value of the variable `lisp-indent-function'. 
The function `calculate-lisp-indent' calls this to determine 
if the arguments of a Lisp function call should be indented specially. 

INDENT-POINT is the position at which the line being indented begins. 
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 that has a non-nil 
property `lisp-indent-function' (or the deprecated `lisp-indent-hook'), 
it specifies how to indent. The property value can be: 

* `defun', meaning indent `defun'-style 
    (this is also the case if there is no property and the function 
    has a name that begins with \"def\", and three or more arguments); 

* 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 that returns the indentation (or nil). 
    `lisp-indent-function' calls this function with the same two arguments 
    that it itself received. 

This function returns either the indentation to use, or nil if the 
Lisp function does not specify a special indentation." 
    (el-patch-let (($cond (and (elt state 2) 
          (el-patch-wrap 1 1 
           (or (not (looking-at "\\sw\\|\\s_")) 
            (looking-at ":"))))) 
       ($then (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))) 
       ($else (let ((function (buffer-substring (point) 
                  (progn (forward-sexp 1) (point)))) 
           method) 
          (setq method (or (function-get (intern-soft function) 
                 'lisp-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)))))) 
    (let ((normal-indent (current-column)) 
      (el-patch-add 
      (orig-point (point)))) 
     (goto-char (1+ (elt state 1))) 
     (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t) 
     (el-patch-swap 
     (if $cond 
      ;; car of form doesn't seem to be a symbol 
      $then 
      $else) 
     (cond 
     ;; car of form doesn't seem to be a symbol, or is a keyword 
     ($cond $then) 
     ((and (save-excursion 
       (goto-char indent-point) 
       (skip-syntax-forward " ") 
       (not (looking-at ":"))) 
       (save-excursion 
       (goto-char orig-point) 
       (looking-at ":"))) 
      (save-excursion 
      (goto-char (+ 2 (elt state 1))) 
      (current-column))) 
     (t $else))))))