2012-06-21 40 views

回答

23

如果啓用CUA選擇模式:

M-Xcua-selection-modeRET在init文件

或永久:

(cua-selection-mode 1) 

然後可以使用其先進的矩形的編輯功能。

(或者如果你是一個cua-mode用戶,那麼你就不需要做。)

  • C-RET標記一個角落。
  • 將點移動到對角。
  • M-r做一個10正則表達式替換在標記的矩形內。
  • C-RET取消標記/退出矩形編輯。

有關文檔,查找 「CUA矩形支持」 MX在評論中標題find-libraryRETcua-baseRET

如果你不想使用的CUA矩形設施某種原因(也許如果你確實需要replace-string),使用apply-on-rectangle的自定義函數將非常簡單地放在一起。

編輯:其實,稍微複雜一點比我預想的,但大部分代碼是交互規範,對於「分隔」 prefix參數的行爲支持(包括基於replace-string)。

編輯2:我決定,這是值得做的一個功能更全面的方式:

下面提供CX[RM-%CX[RCM - %,(希望)按照您的預期行事。

(require 'rect) 

(defun my-search-replace-in-rectangle 
    (start end search-pattern replacement search-function literal) 
    "Replace all instances of SEARCH-PATTERN (as found by SEARCH-FUNCTION) 
with REPLACEMENT, in each line of the rectangle established by the START 
and END buffer positions. 

SEARCH-FUNCTION should take the same BOUND and NOERROR arguments as 
`search-forward' and `re-search-forward'. 

The LITERAL argument is passed to `replace-match' during replacement. 

If `case-replace' is nil, do not alter case of replacement text." 
    (apply-on-rectangle 
    (lambda (start-col end-col search-function search-pattern replacement) 
    (move-to-column start-col) 
    (let ((bound (min (+ (point) (- end-col start-col)) 
         (line-end-position))) 
      (fixedcase (not case-replace))) 
     (while (funcall search-function search-pattern bound t) 
     (replace-match replacement fixedcase literal)))) 
    start end search-function search-pattern replacement)) 

(defun my-replace-regexp-rectangle-read-args (regexp-flag) 
    "Interactively read arguments for `my-replace-regexp-rectangle' 
or `my-replace-string-rectangle' (depending upon REGEXP-FLAG)." 
    (let ((args (query-replace-read-args 
       (concat "Replace" 
         (if current-prefix-arg " word" "") 
         (if regexp-flag " regexp" " string")) 
       regexp-flag))) 
    (list (region-beginning) (region-end) 
      (nth 0 args) (nth 1 args) (nth 2 args)))) 

(defun my-replace-regexp-rectangle 
    (start end regexp to-string &optional delimited) 
    "Perform a regexp search and replace on each line of a rectangle 
established by START and END (interactively, the marked region), 
similar to `replace-regexp'. 

Optional arg DELIMITED (prefix arg if interactive), if non-nil, means 
replace only matches surrounded by word boundaries. 

If `case-replace' is nil, do not alter case of replacement text." 
    (interactive (my-replace-regexp-rectangle-read-args t)) 
    (when delimited 
    (setq regexp (concat "\\b" regexp "\\b"))) 
    (my-search-replace-in-rectangle 
    start end regexp to-string 're-search-forward nil)) 

(defun my-replace-string-rectangle 
    (start end from-string to-string &optional delimited) 
    "Perform a string search and replace on each line of a rectangle 
established by START and END (interactively, the marked region), 
similar to `replace-string'. 

Optional arg DELIMITED (prefix arg if interactive), if non-nil, means 
replace only matches surrounded by word boundaries. 

If `case-replace' is nil, do not alter case of replacement text." 
    (interactive (my-replace-regexp-rectangle-read-args nil)) 
    (let ((search-function 'search-forward)) 
    (when delimited 
     (setq search-function 're-search-forward 
      from-string (concat "\\b" (regexp-quote from-string) "\\b"))) 
    (my-search-replace-in-rectangle 
    start end from-string to-string search-function t))) 

(global-set-key (kbd "C-x r M-%") 'my-replace-string-rectangle) 
(global-set-key (kbd "C-x r C-M-%") 'my-replace-regexp-rectangle) 
+0

謝謝!不幸的是,我似乎只能在emacs GUI中用'C-RET'標記一個角落,而不是終端模式。 – user545424

+0

這將是由於您的終端不發送該序列。您可能會發現xterm更成功(另請參閱http://stackoverflow.com/questions/4337837/send-c-to-emacs-in-vt100-xterm-terminal-mac-os-xs-terminal)。我還用非CUA方法的更全面的代碼更新了我的答案。 – phils

+0

功能請求:搜索矩形。我有一個巨大的專欄,我需要檢查它是否有別的,但'DPP'。我使用了一些複雜的正則表達式 - 如果列很大 - 我得到正則表達式堆棧溢出。 – Adobe

0

如果您處於CUA模式,可以使用綁定到'M-r'的cua-replace-in-rectangle。

+0

但是這隻會替換事件的第一次出現(默認vim replace-regexp行爲)。 – Adobe

3

在最近的Emacs(例如Emacs的25),你可以做到這一點,利用M-%query-replace)或C-M-%query-replace-regexp)的開箱。使用M-x rectangle-mark-mode創建矩形區域。必要時使用C-x C-x,在標記之前放置點。然後只是查詢替換。

但是,他們沒有在Emacs 25中對replace-string進行相同的更改。你可以這樣做,如果你喜歡,只需要以query-replace的方式添加參數region-noncontiguous-p即可。代碼很簡單:

(defun replace-string (from-string to-string &optional delimited start end backward 
         region-noncontiguous-p) 
    "..." 
    (declare (interactive-only 
      "use `search-forward' and `replace-match' instead.")) 
    (interactive 
    (let ((common 
      (query-replace-read-args 
      (concat "Replace" 
        (if current-prefix-arg 
         (if (eq current-prefix-arg '-) " backward" " word") 
        "") 
        " string" 
        (if (use-region-p) " in region" "")) 
      nil))) 
    (list (nth 0 common) (nth 1 common) (nth 2 common) 
      (if (use-region-p) (region-beginning)) 
      (if (use-region-p) (region-end)) 
      (nth 3 common) 
      (if (use-region-p) (region-noncontiguous-p))))) 
    (perform-replace 
    from-string to-string nil nil delimited nil nil start end backward region-noncontiguous-p)) 

或者,你可以下載庫replace+.el並從那裏使用的replace-string版本。它做你想要的。

FWIW,我剛剛提交Emacs bug#27897以將此功能添加到replace-string和其他幾個命令在同一個庫中,replace.el

+0

還有一個anzu bug(可能會替代你的'query-replace'版本):https://github.com/syohex/emacs-anzu/issues/69 –