2016-02-06 55 views
2

我知道有幾個不同的軟件包用於在gnu emacs中選擇多個區域。我正在尋找的是一種方法來選擇多個區域,對它們進行操作,然後選擇之前標記的區域的反轉,然後對其進行操作。Emacs:選擇多個區域並切換到反向

舉個例子,假設我有一個緩衝以下數據:

Line A 
Line B 
Line C 
Line D 
Line E 
Line F 

我想要做的是以下幾點:

  1. 馬克線A,C和E爲多個區域
  2. 對這些標記區域內的文本應用一些elisp
  3. 告訴emacs切換標記區域和未標記區域。現在,線B,d,和F應是被標記爲多個區域
  4. 應用一些其它的elisp到文本這些其他區域內的那些

步驟1,2和4是微不足道的,並它們僅取決於我決定使用的多區域標記代碼的選擇。

但是步驟3呢?是否有任何多區域標記包可以讓我切換到之前標記的內容?

回答

4

你的問題是一般性的。我的答案可能適合其中的一部分,但也許並非全部。

  1. zones.el(見Zones)允許您定義和操作多個區域(實際上,多個區域)的文字,跨越多個緩衝區。你可以用它們做這些事情:

    • 對它們進行排序。
    • 聯合(合併)相鄰或重疊區域(包括對它們進行排序)。
    • 補充他們,如果他們已經團結。
    • 相交它們。
    • 將緩衝區縮小到列表中的區域 - 請參閱MultipleNarrowings。
    • 選擇列表中的區域作爲活動區域。在區域之間循環。
    • 搜索它們(它們會自動聯合)。爲此,您需要庫isearch-prop.el(請參閱Isearch+)。
    • 突出顯示並忽略它們。(對於這一點,你需要Highlight庫(highlight.el)或庫facemenu+.el(見Facemenu+)。
    • 活性區域添加到區域列表。
    • 的區域添加到區域列表,然後團結(聚結)的區域。
    • 從區域的列表中刪除的區域。
    • 克隆一個區域變量到另一個,所以克隆具有相同的區域。
    • 克隆一個區域變量,然後團結克隆的區域。
    • 使區域列表變量持久化,在書籤。使用書籤在隨後的Emacs會話中恢復它。爲此,您需要圖書館Bookmark+
  2. 圖書館Isearch+(包括[isearch-prop.elhttps://www.emacswiki.org/emacs/isearch-prop.el)),可以搜索兩個區域由zones.el和區域通過文本或覆蓋屬性(任何屬性)定義爲定義,它有利於將屬性應用到文本的區域。

    • 您也可以搜索一組區域,我認爲這是你的問題是什麼真正關心的補充。在搜索過程中,未搜索的區域可以選擇性地變暗。
    • 您可以搜索各種「THINGS」作爲區域。事物可以是任何你可以在句法上定義的東西。它們包括通常的Emacs「東西」,如果你使用庫thingatpt+.el那麼你可以很容易地定義其他的東西。
  3. 如果使用Icicles那麼你可以在一組搜索的使用冰柱搜索語境中的緩衝區或文件。您可以用各種方式定義搜索上下文,包括使用正則表達式。您也可以搜索一組搜索上下文的補充。您可以使用漸進式縮小匹配的搜索上下文,並在執行此操作時還可以使用補充來減去匹配組。


您的言論之後更新 -

你顯然想補充的 - 基本區列表(我稱之爲 「izones」),這是每一個數字作爲標識符,然後是兩個區域限制。 (基本區唯一的限制和沒有標識,功能zz-zones-complement返回基本區的列表。)

這是我會怎麼定義的補充功能:

(defun zz-complement-izones (izones &optional beg end) 
    "Complement IZONES, which is a list like `zz-izones'. 
Such a list is also returned, that is, zones that have identifiers." 
    (zz-izones-from-zones 
    (zz-zones-complement (zz-zone-union (zz-izone-limits izones nil t))))) 

這只是使用預定義功能zz-zones-complement剝離區域標識符併合並區域之後。預定義的功能zz-izones-from-zones給出了區域標識符,使結果成爲一個列表。

而且你需要一個將函數映射到區域列表的函數,將它應用到列表中的每個區域 - 你的函數traverse-zones是做什麼的。

這是一個這樣的map函數的版本(未經測試),它需要您正在使用的窗體的區域,即izones(具有數字標識符的區域)並將3元函數映射到它們上面。它類似於您traverse-zones(但看到評論):

(defun map-izones (function &optional izones) 
    "Map 3-ary FUNCTION over IZONES. 
FUNCTION is applied to the first three elements of each zone. 
IZONES is a list like `zz-izones', that is, zones with identifiers." 
    ;; Do you really want this? It prohibits mapping over an empty list of zones. 
    ;; (unless izones) (setq izones zz-izones) 
    (when (and (functionp function) (zz-izones-p izones)) 
    (setq izones (zz-unite-zones izones)) 
    (dolist (izone izones) (funcall function (car izone) (cadr izone) (caddr izone))))) 

這裏是(未經測試)版本,在區列表的二元函數映射。列表中的區域可以是全部基本區域或全部區域。這對我來說似乎更有用,因爲標識符在這種情況下通常不是非常有用。

(defun map-zones (function &optional zones) 
    "Map binary FUNCTION over ZONES, applying it to the limits of each zone. 
ZONES can be a list of basic zones or a list like `zz-izones', that 
is, zones that have identifiers." 
    (when (functionp function) 
    (when (zz-izones-p zones) 
     (setq zones (zz-izone-limits zones nil 'ONLY-THIS-BUFFER))) 
    (setq zones (zz-zone-union zones)) 
    (dolist (zone zones) (funcall function (car zone) (cadr zone))))) 

希望這會有所幫助。

+0

我們的帖子交叉了 - 您在輸入我的信息時發佈了關於['zones.el'](http://www.emacswiki.org/emacs/zones.el)的答案。 ;-) – Drew

+0

謝謝你的這一切。但是,我仍然有另一個問題。你寫道:「基本區域只有限制,而不是標識符,函數zz-zones-complement返回一個基本區域列表」。我明白那個。那麼,如果不是zz-izones結構本身,我應該通過zz-zone來補充什麼?換句話說,在給定當前zz-izones結構的情況下,如何獲得「基本區域」列表?同樣,我的目標是這樣的:我想使用「正常」區域的結構和同構的補充區域。 – HippoMan

+0

請參閱下面我剛添加的我的「其他信息」部分。 – HippoMan

0

我剛剛發現了一個初步的答案。我說「初步」,因爲我還沒有做過任何深入的測試。但是,"zones.el" package正式提供了我正在尋找的功能。

它創建一個選定區域的列表,它被稱爲「區域」。它提供了一個稱爲zz-zones-complement的函數,它將返回當前區域的「合併」列表的補碼,可以按如下方式得到:(zz-zones-complement (zz-zone-union zz-izones))

我相信,這會給我所有我正在尋找的功能。但是,如果我遇到任何問題,我會再回來再發布一次。

0

謝謝,德魯。

事實證明,區域最接近我所需要的,雖然冰柱和isearch +也是有用的。

至於區域,事實證明它的zz-zones-complement函數似乎沒有返回正確的信息。

但是,我寫了自己的函數,我可以使用它的位置。

我現在這樣做是爲了運行在所有先前通過zones.el添加的區域的補任意Lisp代碼...

(defun my-complement-zones (&optional zones) 
    (unless zones 
    (setq zones zz-izones)) 
    (zz-unite-zones 'zones) 
    (let ((result()) 
     (end (copy-marker (point-min))) 
     (n 0) 
     (a nil) 
     (b nil)) 
    (dolist (item (reverse zones)) 
     (setq n (1+ n)) 
     (setq a (cadr item)) 
     (setq b (caddr item)) 
     (setq result (append (list (list n end a)) result)) 
     (setq end b)) 
    (when (< (marker-position end) (point-max)) 
     (setq result (append (list (list (1+ n) end (copy-marker (point-max)))) result))) 
    result)) 

;; Each element has three values: an index followed by the start 
;; and end markers for each region. To traverse this structure, 
;; do the following ... 
(dolist (region (my-complement-zones)) 
    (let ((idx (car region)) 
     (start (cadr region)) 
     (end (caddr region))) 
    ;; At this point, "start" is a marker pointing to the 
    ;; beginning of the given zone, and "end" is a marker pointing 
    ;; its endpoint. I can use these for inputs to any region-aware 
    ;; elisp commands, or for any functions that I might want to 
    ;; write which operate on each given region. 
    ;; 
    ;; ... etc. ... 
)) 

...這是我寫這將穿越功能一個區域列表並將lambda應用於每個區域。它的工作原理等同,無論我們使用原來的ZZ-izones或它的互補與我的函數生成:

;; Helper function 
(defun funcallable (func) 
    (and func 
     (or (functionp func) 
      (and (symbolp func) 
       (fboundp func))))) 

;; Traverse a list of zones such as zz-izones, and apply a lambda 
;; to each zone in the list. Works equivalently with the output of 
;; `my-complement-zones'. 
(defun traverse-zones (func &optional zones) 
    (when (funcallable func) 
    (unless zones 
     (setq zones zz-izones)) 
    (zz-unite-zones 'zones) ;; not sure if this is really necessary 
    (dolist (zone zones) 
     (let ((i (car zone)) 
      (s (cadr zone)) 
      (e (caddr zone))) 
     (funcall func i s e))))) 

爲了說明ZZ-izones和ZZ-區補的輸出之間結構上的差異,這裏有一個ZZ-izones結構我在一個名爲「foo」的緩衝區中創建的例子:

((4 #<marker at 1202 in foo> #<marker at 1266 in foo>) (3 #<marker at 689 in foo> #<marker at 1132 in foo>) (2 #<marker at 506 in foo> #<marker at 530 in foo>) (1 #<marker at 3 in foo> #<marker at 446 in foo>)) 

這裏是(ZZ-區補ZZ-izones)看起來像這個一樣ZZ-izones列表...

((1 4) (#<marker at 1202 in foo> 3) (#<marker at 689 in foo> 2) (#<marker at 506 in foo> 1) (#<marker at 3 in foo> 1266) 

請注意,zz-izones中的每個條目都包含一個索引和兩個標記。但是,在補充中,每個條目是兩個整數或一個標記和一個整數。這些結構不是同構的。

附加信息

對於(zz-zone-union (zz-izone-limits zz-izones nil t)) ...

((#<marker at 3 in foo> #<marker at 446 in foo>) (#<marker at 506 in foo> #<marker at 530 in foo>) (#<marker at 689 in foo> #<marker at 1132 in foo>) (#<marker at 1202 in foo> #<marker at 1266 in foo>) 

對於(zz-zones-complement (zz-zone-union (zz-izone-limits zz-izones nil t)))

((1 #<marker at 3 in foo>) (#<marker at 446 in foo> #<marker at 506 in foo>) (#<marker at 530 in foo> #<marker at 689 in foo>) (#<marker at 1132 in foo> #<marker at 1202 in foo>) (#<marker at 1266 in foo> 1266)) 

我想,如果我轉換 「1」 中的第一個條目我可以用這個補(copy-marker (point-min))和最終項目中的「1266」到(copy-marker (point-max)) ......除非我正在處理一個具體的案例,無論我是否d用標記或點來標記。

標記是理想的,因爲然後我可以在生成補碼後更改緩衝區,並且我不必擔心補語結構中的數字點值不再指向它最初指向的位置。

+0

你不會說'zz-zones-complement'有什麼問題。考慮提交錯誤報告或增強請求(再次下載文件,獲取聯繫信息)。謝謝。 – Drew

+0

zz-zones-complement返回的結構不是有效的「zz-izones」結構。這個返回值不能用在許多標準「zz-izones」工作的地方。我自己的結構(來自我的補充區)確實在各處都有「zz-izones」的功能。我確實會向作者報告。 – HippoMan

+0

謝謝。期待這份報告。先驗的我並不認爲這是一個問題。請參閱['isearch-prop.el'](http://www.emacswiki.org/emacs/download/isearch-prop.el),瞭解如何將它與'zz-izones'或任意區域變量一起使用。例如, '(let *((zones(zz-zone-union(zz-izone-limits(symbol-value variable)nil'ONLY-THIS-BUFFER))) (comp-zones(zz-zones-complement zones )) (dolist(區域(如果isearchp-complement-domain-p comp-zones區域)) ......) – Drew