我是一位emacs的新手蟒蛇壓痕,我想Emacs的能夠縮進這樣多線對emacs的
egg = spam.foooooo('vivivivivivivivivi')\
.foooooo('emacs', 'emacs', 'emacs', 'emacs')
這是不可能的默認自動做到這一點我的代碼(無需手動插入空格或Cc>),因爲emacs總是縮進4個空格(除非我在多行上分割多個參數)。
最好的做法是什麼?
PS:如果這是一個壞主意(PEP對8或東西)請你告訴我
我是一位emacs的新手蟒蛇壓痕,我想Emacs的能夠縮進這樣多線對emacs的
egg = spam.foooooo('vivivivivivivivivi')\
.foooooo('emacs', 'emacs', 'emacs', 'emacs')
這是不可能的默認自動做到這一點我的代碼(無需手動插入空格或Cc>),因爲emacs總是縮進4個空格(除非我在多行上分割多個參數)。
最好的做法是什麼?
PS:如果這是一個壞主意(PEP對8或東西)請你告訴我
我同意Aaron關於你的文體選擇的合意性,但是因爲我也同意他說Emacs Lisp很有趣,我會描述你如何去實現這個。
Emacs python-mode
計算函數python-calculate-indentation
中一行的縮進,處理繼續行的相關部分深埋在函數內部,沒有簡單的方法來配置它。
因此,我們有兩種選擇:
python-calculate-indentation
與我們自己的版本(維護的噩夢,每當python-mode
的變化);或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功能:advice,excursions,narrowing,moving over sexps,error handling,blocks and exits。請享用!
+1。 +10,如果可以的話,這絕對值得一個'不錯的答案'徽章。 – aaronasterling 2010-11-11 01:41:47
謝謝。我擔心Emacs有點少數味道。現在,如果它已經被Eclipse ... – 2010-11-11 15:10:30
巨大的答案在這裏。良好的書面教程與良好的聯繫。我不認爲我會盡快嘗試,但很多。應該被投得更多。對不起aaronasterling,我改變了它,所以這是答案。我雖然投了你 – kusut 2010-11-28 13:49:54
這是相當醜陋,並會要求你口齒不清寫一些emacs的。我需要學習emacs lisp,所以如果它不那麼難看,我可能會爲此做好準備。但它是,我不是。看起來你要學習emacs lisp :)(如果你真的想這樣做)。我有點嫉妒。無論如何,你說通知你這是一個糟糕的主意是一個可以接受的答案,所以在這裏:
這是一個可怕的風格選擇。是不是
egg = spam.foo('viviviv')
egg = egg.foo('emacs', 'emacs', 'emacs')
更容易閱讀?
雖然沒有特別針對PEP 8,但提到使用連續字符應該保持最小。另外,這個最肯定客觀地違背了PEP 8的精神。我只是不確定如何;)
認爲最好將'spam.fooooo(...)'放在圓括號內:'egg =(spam.fooo ...)'。這樣,你不需要延續標記(以及其他優點)。 – EOL 2010-10-30 10:13:34
這是不好的風格。一般來說,第二種foooooo方法與垃圾郵件無關,正如隊列中的建議,而是與第一個foooooo返回的內容無關。在'('之後或者在其中一個','之後打破它(或者在任何一種情況下,由於自動括號的延續你都不必使用'\'),我更加習慣於這樣做。 – asmeurer 2012-09-15 02:14:26