2012-06-21 11 views

Antwort

23

Wenn Sie CUA-Auswahlmodus zu aktivieren:

M-xcua-selection-modeRET

oder dauerhaft in Ihrer init-Datei:

(cua-selection-mode 1) 

Sie können dann seine erweiterten Rechteck Bearbeitungsmöglichkeiten nutzen.

(oder, wenn Sie einen cua-mode-Benutzer sind, dann brauchen Sie nicht zu tun.)

  • C-RET eine Ecke zu markieren.
  • Verschieben Sie den Punkt in die gegenüberliegende Ecke.
  • M-r zu tun regexp innerhalb des markierten Rechtecks ​​ersetzen.
  • C-RET zum Aufheben der Markierung/zum Beenden der Bearbeitung des Rechtecks.

Zur Dokumentation, suchen Sie nach der "CUA Rechteck Unterstützung" in im Kommentar Rubrik Mxfind-libraryRETcua-baseRET

Wenn Sie nicht möchten, dass die cua Rechteck Einrichtungen nutzen für etwas Grund (vielleicht, wenn Sie wirklich replace-string spezifisch benötigen), würde eine kundenspezifische Funktion, die verwendet, ziemlich einfach zusammengebaut werden.

bearbeiten: Eigentlich etwas komplexer, als ich erwartet hatte, aber die meisten der Code ist die interaktive Spezifikation und die Unterstützung für das Verhalten ‚begrenzt‘ Präfix Argument (beide basierend auf replace-string).

Edit 2: Ich beschloss, diese voll funktionsfähige Art und Weise tun, in einer mehr wert war:

Im Folgenden CxrM-% und CxrCM -%, die (hoffentlich) so funktionieren, wie Sie es erwarten würden.

(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

Vielen Dank! Leider scheint es, dass ich in der Emacs-GUI nur mit "C-RET" eine Ecke markieren kann, nicht im Terminal-Modus. – user545424

+0

Das liegt daran, dass Ihr Terminal diese Sequenz nicht sendet. Sie können einen xterm erfolgreicher finden (siehe auch http://stackoverflow.com/questions/4337837/send-c-to-emacs-in-vt100-xterm-terminal-mac-os-xs-terminal). Ich habe auch meine Antwort mit besser funktionierendem Code für den Nicht-CUA-Ansatz aktualisiert. – phils

+0

Feature-Anfrage: Suche das Rechteck. Ich habe eine riesige Spalte und ich muss überprüfen, ob es etwas anderes als "DPP" hat. Ich benutze einige komplexe Regexp - und wenn die Spalte wirklich groß ist - bekomme ich Regexp Stack Overflow. – Adobe

0

Wenn Sie in CUA-Modus sind, können Sie CUA-ersetzen-in-Rechteck gebunden zu 'M-r' verwenden können.

+0

Aber dies ersetzt nur das erste Vorkommen der Sache (Standard-vim-replace-regexp-Verhalten). – Adobe

0

Für böse Benutzer können Sie mein Paket evil-visual-replace verwenden, um query-replace und replace-regexp in bösen visuellen Blöcken zu bekommen.

3

In der letzten Emacs (zum Beispiel Emacs 25) Sie können dies tun, aus der Box mit M-% (query-replace) oder C-M-% (query-replace-regexp).

Verwenden Sie M-x rectangle-mark-mode, um den rechteckigen Bereich zu erstellen. Verwenden Sie ggf. C-x C-x, um Punkt vor Markierung zu setzen. Dann nur Abfrage ersetzen.

Sie haben jedoch die gleiche Änderung in Emacs 25 für replace-string nicht vorgenommen. Sie können das tun, wenn Sie möchten, indem Sie einfach das Argument region-noncontiguous-p auf die gleiche Weise hinzufügen wie in query-replace. Der Code ist einfach:

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

Alternativ können Sie nur Bibliothek herunterladen replace+.el und die Version von replace-string von dort verwenden. Es macht was du willst.

FWIW, ich habe gerade Emacs bug#27897 abgelegt, um diese Funktion zu replace-string und mehreren anderen Befehlen in derselben Bibliothek, replace.el, hinzuzufügen.

+0

Es gibt auch einen anzu Bug (der Ihre Version von 'query-replace ersetzen könnte), die damit zusammenhängt: https://github.com/syohex/emacs-anzu/issues/69 –