2013-07-12 51 views
3

困境:可讀性還是可維護性?

讓我們看看下面的函數。 它並不真正的問題是什麼呢,最重要的是, 它使用兩倍的字符串"(let\\*?[ \t]*"Emacs是否可以實現elisp字符串常量?

(defun setq-expression-or-sexp() 
    "Return the smallest list that contains point. 
If inside VARLIST part of `let' form, 
return the corresponding `setq' expression." 
    (interactive) 
    (ignore-errors 
    (save-excursion 
     (up-list) 
     (let ((sexp (preceding-sexp))) 
     (backward-list 1) 
     (cond 
     ((looking-back "(let\\*?[ \t]*") 
      (cons 'setq 
       (if (= (length sexp) 1) 
        (car sexp) 
        (cl-mapcan 
        (lambda (x) (unless (listp x) (list x nil))) 
        sexp)))) 
     ((progn 
      (up-list) 
      (backward-list 1) 
      (looking-back "(let\\*?[ \t]*")) 
      (cons 'setq sexp)) 
     (t 
      sexp)))))) 

,因爲它具有兩個(或更多)的位置來更新串頭痛, 我倒是有defconst它像這樣:

(defconst regex-let-form "(let\\*?[ \t]*") 

雖然代碼變得更容易維護,它變得不那麼可讀性爲好, 因爲它很難一眼看到什麼regex-let-form真的是:

(defun setq-expression-or-sexp() 
    "Return the smallest list that contains point. 
If inside VARLIST part of `let' form, 
return the corresponding `setq' expression." 
    (interactive) 
    (ignore-errors 
    (save-excursion 
     (up-list) 
     (let ((sexp (preceding-sexp))) 
     (backward-list 1) 
     (cond 
     ((looking-back regex-let-form) 
      (cons 'setq 
       (if (= (length sexp) 1) 
        (car sexp) 
        (cl-mapcan 
        (lambda (x) (unless (listp x) (list x nil))) 
        sexp)))) 
     ((progn 
      (up-list) 
      (backward-list 1) 
      (looking-back regex-let-form)) 
      (cons 'setq sexp)) 
     (t 
      sexp)))))) 

這個想法:爲什麼不是兩個?

因爲它是一個常數,爲什麼不是font-lock它 和使regex-let-form看起來好像是"(let\\*?[ \t]*"? 這是一個feasable工作,因爲:

  1. 這是可能的字體鎖標識符,像這樣:http://www.emacswiki.org/emacs/PrettyLambda, 或即便如此:rainbow-mode

  2. 而且可以對字體鎖定常量。據我所知,它已經完成了C++模式, ,但尚未用於emacs-lisp模式。

然後,它仍然只是連接兩個。不幸的是,我不知道 足夠的font-lock內臟做到這一點,但也許別人呢? 或者是否已經有一個包?

回答

0

這似乎是工作(來源:http://www.emacswiki.org/emacs/PrettyLambda):

(font-lock-add-keywords 'emacs-lisp-mode 
    `(("\\<\\(regex-let-form\\)\\>" (0 (prog1 nil 
             (compose-region (match-beginning 1) 
                 (match-end 1) 
                 "\"(let\\\\*?[ \\t]*\"")))))) 

雖然我認爲加上regex-let-form到現有let塊將是一個清潔的解決方案:

(let ((sexp (preceding-sexp)) 
     (regex-let-form "(let\\*?[ \t]*")) 
    ... 
+0

我試過了,它給了我一個奇怪的unicode字符而不是正則表達式。 –

+0

這可能是一個版本問題。我正在使用v24.2。 – gbrener

+0

我有v24.3.1。 –

-1

也許你的例子不表示真正的問題,你真的想要做一些顯示替換或字體鎖定,如你所說。

但是我會回答你的例子,並提出可維護性與可讀性方面的問題:只需let - 綁定你的正則表達式。不同於defconst的綁定將在附近並與綁定變量的出現明確相關。

這通常是人們做的事情。再一次,你可能已經有了另一個用例 - 我只對狹義提出的問題做出反應。

+0

'let'-bind,是顯而易見的答案,它顯然是不足的。 正則表達式可以在函數中使用,也可以是常量 ,let不反映。最後也是最重要的是, 可讀性丟失。當我用「回頭看」的方式閱讀一行時,我真的很想看看我在/ there /裏看到的是什麼,而不是 高出10行。 –

1

this answer調整的代碼, 我已經解決了這個問題:

(font-lock-add-keywords 
'emacs-lisp-mode 
'((fl-string-constant . 'font-lock-constant-face)) 'append) 

(defun fl-string-constant (_limit) 
    (while (not 
      (ignore-errors 
      (save-excursion 
       (skip-chars-forward "'") 
       (let ((opoint (point)) 
        (obj (read (current-buffer))) 
        obj-val) 
       (and (symbolp obj) 
        (risky-local-variable-p obj) 
        (special-variable-p obj) 
        (stringp (setq obj-val (eval obj))) 
        (progn 
         (put-text-property 
         (1- (point)) (point) 'display 
         (format "%c\"%s\"" (char-before) obj-val)) 
         (set-match-data (list opoint (point))) 
         t)))))) 
    (if (looking-at "\\(\\sw\\|\\s_\\)") 
     (forward-sexp 1) 
     (forward-char 1))) 
    t) 

這將顯示的字符串常量右邊的常量名後的值。 它與工作字符串常量很好地工作。 速度有點問題 - 歡迎提出改進建議。

此外,我找不到比risky-local-variable-p更好的東西來確定 它是一個常數。該文件指出defconst將變量 標記爲特殊且有風險,但沒有別的。

+0

@Drew,我用另一個答案的代碼。謝謝。你能建議如何加快這個功能嗎? –

+0

還沒有真正看過它,但我的其他答案應該做你想要的。在上面的代碼中,您正在閱讀每個引用的Lisp對象等。如果您只是首先檢查您是否在查看符號,則不需要讀取每個對象,甚至不需要讀取任何對象 - 只需檢查符號值即可。但正如我所說,我沒有真正研究過你的代碼等。試試['hl-defined.el'](http://www.emacswiki.org/emacs-en/download/hl-defined.el) - 我認爲它會做你想做的。 – Drew

1

hl-defined.el(今天更新,2013-10-20)可以突出顯示常量Emacs-Lisp符號,也就是說,當前值爲符號本身的變量。如果您的defconst已被評估,那麼這將做你正在請求。

+0

它只是改變了臉,對吧?不替代常量的值? –

+0

對不起,我的壞。我今天恢復了我對'hl-defined.el'所做的更改。他們只是突出了*自我評估*常量,這是沒有用的。如果不是[Emacs bug#15666](http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15666),那麼處理使用'defconst'定義的常量將很容易。唉,這種迴歸意味着人們不能再建議特殊形式。我會刪除這個答案,如果你在這裏回覆你已經看到這個撤回評論。 – Drew

+0

太糟糕了。保持鏈接 - 修復bug的動力更強:) –

相關問題