2010-10-30 20 views
1

我是一位emacs的新手蟒蛇壓痕,我想Emacs的能夠縮進這樣多線對emacs的

egg = spam.foooooo('vivivivivivivivivi')\ 
      .foooooo('emacs', 'emacs', 'emacs', 'emacs') 

這是不可能的默認自動做到這一點我的代碼(無需手動插入空格或Cc>),因爲emacs總是縮進4個空格(除非我在多行上分割多個參數)。

最好的做法是什麼?

PS:如果這是一個壞主意(PEP對8或東西)請你告訴我

+2

認爲最好將'spam.fooooo(...)'放在圓括號內:'egg =(spam.fooo ...)'。這樣,你不需要延續標記(以及其他優點)。 – EOL 2010-10-30 10:13:34

+0

這是不好的風格。一般來說,第二種foooooo方法與垃圾郵件無關,正如隊列中的建議,而是與第一個foooooo返回的內容無關。在'('之後或者在其中一個','之後打破它(或者在任何一種情況下,由於自動括號的延續你都不必使用'\'),我更加習慣於這樣做。 – asmeurer 2012-09-15 02:14:26

回答

23

我同意Aaron關於你的文體選擇的合意性,但是因爲我也同意他說Emacs Lisp很有趣,我會描述你如何去實現這個。

Emacs python-mode計算函數python-calculate-indentation中一行的縮進,處理繼續行的相關部分深埋在函數內部,沒有簡單的方法來配置它。

因此,我們有兩種選擇:

  1. 更換整個python-calculate-indentation與我們自己的版本(維護的噩夢,每當python-mode的變化);或
  2. Advise」函數python-calculate-indentation:即將其包裝在我們自己的函數中,該函數處理我們感興趣的情況,否則按照原始方式進行處理。

在這種情況下,選項(2)似乎是可行的。所以讓我們開始吧!要做的第一件事是閱讀,這表明我們的建議應該是這樣的manual on advice

(defadvice python-calculate-indentation (around continuation-with-dot) 
    "Handle continuation lines that start with a dot and try to 
line them up with a dot in the line they continue from." 
    (unless 
     (this-line-is-a-dotted-continuation-line) ; (TODO) 
    ad-do-it)) 

這裏ad-do-it是一個神奇的令牌defadvice替代與原來的功能。來自Python的背景你可能會問,「爲什麼不做這個裝飾風格?」 Emacs建議機制的設計(1)將建議與原始建議保持很好的分離; (2)針對不需要合作的單個功能提供多條建議; (3)允許您單獨控制打開和關閉哪些建議。你當然可以想象用Python編寫類似的東西。

下面是如何判斷當前行是一個點續行:

(beginning-of-line) 
(when (and (python-continuation-line-p) 
      (looking-at "\\s-*\\.")) 
    ;; Yup, it's a dotted continuation line. (TODO) 
    ...) 

還有一個問題,這樣的:beginning-of-line該呼叫實際上point移到行的開頭。哎呀。我們不想僅僅在計算縮進時移動點。所以我們最好在打電話給save-excursion以確保這一點不會流浪。

我們可以通過向後跳過標記或括號表達式(Lisp稱之爲「S表達式」或「sexps」)找到需要與之對齊的點,直到找到該點爲止,否則我們得到聲明的開始。一個很好的Emacs的成語在緩衝區的限制部分進行搜索是narrow緩衝區只包含我們想要的部分:

(narrow-to-region (point) 
        (save-excursion 
        (end-of-line -1) 
        (python-beginning-of-statement) 
        (point))) 

,然後繼續向後跳躍sexps,直到我們找到了點,或直到backward-sexp停止進取:

(let ((p -1)) 
    (while (/= p (point)) 
    (setq p (point)) 
    (when (looking-back "\\.") 
     ;; Found the dot to line up with. 
     (setq ad-return-value (1- (current-column))) 
     ;; Stop searching backward and report success (TODO) 
     ...) 
    (backward-sexp))) 

這裏ad-return-value是一個神奇的變量defadvice使用從通知函數的返回值。醜陋但實用。

現在有兩個問題。首先是backward-sexp信號可以在某些情況下的錯誤,所以我們最好趕上這個錯誤:

(ignore-errors (backward-sexp)) 

的另一個問題是,打破循環,並指示成功的。我們可以通過聲明一個名爲block,然後致電return-from來立即執行這兩個操作。 Blocks and exits是Common Lisp的功能,因此我們需要(require 'cl)

讓我們把它放在一起:

(require 'cl) 

(defadvice python-calculate-indentation (around continuation-with-dot) 
    "Handle continuation lines that start with a dot and try to 
line them up with a dot in the line they continue from." 
    (unless 
     (block 'found-dot 
     (save-excursion 
      (beginning-of-line) 
      (when (and (python-continuation-line-p) 
        (looking-at "\\s-*\\.")) 
      (save-restriction 
       ;; Handle dotted continuation line. 
       (narrow-to-region (point) 
           (save-excursion 
            (end-of-line -1) 
            (python-beginning-of-statement) 
            (point))) 
       ;; Move backwards until we find a dot or can't move backwards 
       ;; any more (e.g. because we hit a containing bracket) 
       (let ((p -1)) 
       (while (/= p (point)) 
        (setq p (point)) 
        (when (looking-back "\\.") 
        (setq ad-return-value (1- (current-column))) 
        (return-from 'found-dot t)) 
        (ignore-errors (backward-sexp)))))))) 
    ;; Use original indentation. 
    ad-do-it)) 

(ad-activate 'python-calculate-indentation) 

我不會宣稱這是做到這一點的最好辦法,但它說明了一堆適度棘手的Emacs和Lisp功能:adviceexcursionsnarrowing,moving over sexps,error handling,blocks and exits。請享用!

+3

+1。 +10,如果可以的話,這絕對值得一個'不錯的答案'徽章。 – aaronasterling 2010-11-11 01:41:47

+0

謝謝。我擔心Emacs有點少數味道。現在,如果它已經被Eclipse ... – 2010-11-11 15:10:30

+0

巨大的答案在這裏。良好的書面教程與良好的聯繫。我不認爲我會盡快嘗試,但很多。應該被投得更多。對不起aaronasterling,我改變了它,所以這是答案。我雖然投了你 – kusut 2010-11-28 13:49:54

2

這是相當醜陋,並會要求你口齒不清寫一些emacs的。我需要學習emacs lisp,所以如果它不那麼難看,我可能會爲此做好準備。但它是,我不是。看起來你要學習emacs lisp :)(如果你真的想這樣做)。我有點嫉妒。無論如何,你說通知你這是一個糟糕的主意是一個可以接受的答案,所以在這裏:

這是一個可怕的風格選擇。是不是

egg = spam.foo('viviviv') 
egg = egg.foo('emacs', 'emacs', 'emacs') 

更容易閱讀?

雖然沒有特別針對PEP 8,但提到使用連續字符應該保持最小。另外,這個最肯定客觀地違背了PEP 8的精神。我只是不確定如何;)

+0

我同意這很可怕的風格: )。你的建議也已經過了我的想法。看起來像我必須更新我的問題來查詢關於造型 – kusut 2010-10-30 09:57:39

+0

忘記它的更多意見。物質超過風格。如果我想遵循PEP 8 – kusut 2010-10-30 10:02:50

+1

爲了您的愉悅(僅),我會解釋如何在Emacs中實現所需的縮進。任何人都不應該使用它。 – 2010-11-11 00:33:47