2012-06-21 32 views

Respuesta

23

Si habilita CUA modo de selección:

M-xcua-selection-modeRET

o permanentemente en el fichero init:

(cua-selection-mode 1) 

A continuación, puede utilizar sus funciones de edición rectángulo avanzadas.

(o si usted es un usuario cua-mode, entonces usted no necesita hacer eso.)

  • C-RET para marcar una esquina.
  • Mueva el punto a la esquina opuesta.
  • M-r hacer una expresión regular reemplazar dentro del rectángulo marcado.
  • C-RET para desmarcar/salir de la edición de rectángulo.

Para la documentación, buscar el "apoyo rectángulo CUA" la partida en el comentario en Mxfind-libraryRET RETcua-base

Si no desea utilizar las instalaciones para cua rectángulo alguna razón (tal vez si realmente necesita replace-string específicamente), una función personalizada usando apply-on-rectangle sería muy fácil de armar.

Editar: En realidad, un poco más compleja de lo que esperaba, pero la mayor parte del código es la especificación interactiva y el apoyo para el comportamiento argumento prefijo 'delimitado' (ambos basados ​​en replace-string).

Editar 2: decidí que valía la pena hacerlo de una manera más plenamente las funciones de:

A continuación se proporciona CxrM-% y CxrCM -%, que (con suerte) actúa de la manera esperada.

(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

¡Gracias! Desafortunadamente, parece que solo puedo marcar una esquina con 'C-RET' en la GUI de emacs, no en modo terminal. – user545424

+0

Eso se debe a que su terminal no envía esa secuencia. Puede encontrar un xterm más exitoso (vea también http://stackoverflow.com/questions/4337837/send-c-to-emacs-in-vt100-xterm-terminal-mac-os-xs-terminal). También actualicé mi respuesta con un código más completo para el enfoque sin CUA. – phils

+0

Solicitud de elemento: busca en el rectángulo. Tengo una gran columna y necesito verificar si tiene algo más que 'DPP'. Uso una expresión regular compleja, y si la columna es realmente grande, obtengo un desbordamiento de pila de regexp. – Adobe

0

Si está en el modo CUA, puede utilizar cua-reemplazar-en-rectángulo con destino a 'M-r'.

+0

Pero esto solo reemplaza la primera aparición de la cosa (comportamiento vim replace-regexp predeterminado). – Adobe

0

Para usuarios malvados, puede usar mi paquete evil-visual-replace para obtener query-replace y replace-regexp dentro de bloques visuales malvados.

3

En reciente de Emacs (por ejemplo Emacs 25) Esto se puede hacer fuera de la caja usando M-% (query-replace) o C-M-% (query-replace-regexp).

Use M-x rectangle-mark-mode para crear la región rectangular. Use C-x C-x si es necesario, para poner el punto antes de la marca. Luego solo consulta-reemplaza.

No hicieron, sin embargo, el mismo cambio en Emacs 25 para replace-string. Puede hacerlo, si lo desea, simplemente agregando el argumento region-noncontiguous-p de la misma manera que en query-replace. El código es simple:

(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)) 

Como alternativa, puede simplemente descargar la biblioteca replace+.el y utilizar la versión de replace-string desde allí. Hace lo que quieres.

Fwiw, acabo presentó Emacs bug#27897 obtener esta característica añadida a replace-string y varios otros comandos en la misma biblioteca, replace.el.

+0

También hay un error anzu (que podría estar reemplazando su versión de 'query-replace') relacionado con esto: https://github.com/syohex/emacs-anzu/issues/69 –