Ersetzen Sie Text in verschiedenen Trennzeichen (z. B. Klammern, Anführungszeichen).

9

Ich mache oft einige Testimplementierungen mit fest codierten Werten, die ich später ändern möchte. Mögen

ref = open('specific-file-name')

Was ich gerne ändern würde

ref = open(fname)

Ich bin es gewohnt zu vim und dort kann ich tippen, ci(fnamevorausgesetzt, der Punkt befindet sich in den Klammern. ( ci(steht für innere Klammern ersetzen).

Wie kann ich in Emacs so etwas wie "Inneres ersetzen" erreichen?

kain88
quelle

Antworten:

9

Verwenden von expand-region

Ich würde empfehlen, das expand-regionPaket zu installieren (auch auf Melpa verfügbar). Dies ist nützlich, um in Ihrem Beispiel erwähnte Situationen und vieles mehr zu bearbeiten.

expand-regionist intelligent. Basierend auf dem Hauptmodus wird versucht, herauszufinden, was Sie auswählen möchten. Ich weiß nicht, aus welcher Sprache Sie das Beispiel-Snippet haben, daher werde ich Ihr Beispiel-Code-Snippet verwenden und es für Python leicht ändern (remove;). Meine folgende Erklärung bezieht sich also auf das folgende Codefragment in einem python-modePuffer.

ref = open('specific-file-name') 

Wenn Punkt neben einem einfachen Anführungszeichen steht

Die schwarzen vertikalen Rechtecke unten zeigen an, wie der Cursor aussehen wird.

# point on left of left quote, the cursor is hiding the quote under it
ref = open(▮specific-file-name') 

# point on left of right parenthesis, the cursor is hiding the parenthesis under it       
ref = open('specific-file-name'▮

In jedem Fall, wenn Sie das tun M-x er/expand-region, 'specific-file-name'wird erhalten ausgewählt und Sie können dann getroffen DEL(oder Backspace) um die Auswahl zu löschen.

Wenn Sie delete-selection-modeaktiviert haben (ich möchte, dass dies persönlich aktiviert wird), können Sie nach der Auswahl mit dem Tippen beginnen. Dadurch wird die Auswahl überschrieben.

Wenn Sie er/expand-regionviel verwenden, würden Sie es natürlich an eine kurze Schlüsselbindung binden. Ich binde es gerne an C-\. Also mit Punkt neben einem einzigen Zitat: C-\fnamewerde ich gebenref = open(fname);

Geben Sie hier die Bildbeschreibung ein

Wenn der Punkt irgendwo in den Anführungszeichen steht

Bei Verwendung expand-regionmuss der Punkt nicht in der Nähe der Anführungszeichen liegen. In diesem Fall benötigen Sie jedoch nur noch wenige (normalerweise ein oder zwei weitere) Tastenanschläge.

Angenommen, die Cursorposition ist jetzt wie folgt:

# cursor shown below is hiding the i character under it
ref = open('specif▮c-file-name')

Verwenden Sie die gleiche Bindung wie oben:

  • Das erste Mal, wenn ich drücke, C-\wird ausgewählt specific.
  • Jetzt muss ich nur noch drücken \, um die Auswahl ( expand-regionFunktion) zu erweitern. Das wird auswählen specific-file-name.

    Wenn Sie gebunden haben er/expand-region, C-=führt ein erneutes Schlagen =die inkrementelle Erweiterung aus. Lesen Sie die Dokumentation zum Binden von Schlüsseln für die schrittweise Erweiterung / Kontraktion der Auswahl.

  • Durch erneutes Schlagen \wird ausgewählt 'specific-file-name'.
  • Nun drücken Sie, DELum die Auswahl zu löschen, und geben dann ein fname. Wenn delete-selection-modeaktiviert, können Sie den DELStrich überspringen .

Zusammenfassend sehen die delete-selection-modeaktivierten Tastenanschläge bei aktiviertem Status wie folgt aus : C-\\\fname.

Geben Sie hier die Bildbeschreibung ein


Verwenden von change-inner

Ich bin auch auf ein change-innerPaket des expand-regionAutors Magnars gestoßen (das expand-regionals Back-End verwendet wird), um genau das zu tun, was der Vim citut (und auch das Äußere zu ändern ).

Aus dem Paket README:

change-innergibt dir vims cibefehl und baut darauf auf expand-region. Es lässt sich am einfachsten anhand eines Beispiels erklären:

function test() {
  return "semantic kill";
}

Mit Punkt nach dem Wort Semantik

change-inner "würde den Inhalt des Strings
change-outer "töten würde den gesamten String
change-inner {töten würde die return-Anweisung
change-outer {töten würde den gesamten Block töten

Kaushal Modi
quelle
3

Mit einer Region

Um dies mit einer Region zu tun, beginnend mit:

ref = open(|'specific-file-name');

drücken Sie C-SPC C-b C-M-n C-b C-w.

Schneller

Ausgehend von dem Punkt vor dem Paren, genau wie in Vim:

ref = open|('specific-file-name');

C-M-k( kill-sexp) führt zu:

ref = open|;

Wenn Sie electric-pair-modeauf, können Sie wieder einsetzen ()mit nur (. Die vollständige Tastenfolge ist also C-M-k (- nicht viel länger als ci(.

abo-abo
quelle
1
Auch wenn der Punkt vor dem linken Zitat liegt ref = open(|'specific-file-name');, C-M-kwird geben ref = open(|);. Zitate sind auch ausgewogene Sexps .
Kaushal Modi
Ich dachte an delete-everything-inside-parensso etwas, nicht delete-first-sexp-inside-parens.
abo-abo
Gute Lösung, aber ich muss den Punkt vor dem Ausdruck verschieben, den ich ersetzen möchte. Das Paket 'change inner' funktioniert, wenn sich point irgendwo im Ausdruck befindet (wie vi).
Kain88
1

evil emuliert den größten Teil von Vim und erstellt sofort Textobjekte.

Mit anderen Worten, wenn evilaktiviert und die Standardtastenbindungen verwendet werden, ci(wird genau das getan, was Sie verlangen: Ändern Sie, was in den umschließenden Klammern steht.

Genauer gesagt ci(Willen Kette evil-changezu evil-inner-paren. Sie können auch beliebig eigene Textobjekte erstellen.

Dan
quelle
Ich weiß über das Böse Bescheid (ich habe es jetzt eine Weile benutzt). Ich würde gerne wissen, wie dies in "reinen" Emacs gemacht werden kann.
Kain88
@ kain88: fair genug: Ich denke, es wird mehrere Antworten auf diese Frage geben. Aus Neugier, wenn Sie bereits verwenden evil, warum sollten Sie dann die Nicht- evilAlternative wollen?
Dan
(nicht ernsthafter Kommentar) @Dan Er bereitet sich wahrscheinlich darauf vor, auf die dunkle Seite zu kommen.
Kaushal Modi
Mir ist aufgefallen, dass das Böse manchmal nicht gut mit anderen Modi spielt. Außerdem bin ich gespannt, wie die Bearbeitung nur Emacs verwenden würde
kain88
1

Smartparens verwenden

Töten

1) Verwenden Sie C-M-u( sp-backward-up-sexp), um 'Trennzeichen zu entfernen.

2) Verwenden Sie C-0 C-M-k( 0Präfix + sp-kill-sexp), um Dinge innerhalb des aktuellen Sexp oder C-k( sp-kill-hybrid-sexp) zu töten . Letzteres funktioniert nur, wenn smartparens-strict-modees aktiviert ist und das aktuelle Sexp in eine Zeile passt.

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-k
ref = open(|)

Markieren und löschen / töten / kopieren

1) Finde deinen Weg zum Anfang von sexp (in diesem Beispiel C-M-u sp-backward-up-sexpist genug), setze eine Markierung C-SPCund gehe zum Ende von sexp mit sp-end-of-sexp.

2) Dann können Sie tun, was Sie wollen: C-wRegion töten, Region M-wtöten, speichern (kopieren), backspacelöschen, ohne den Kill-Ring zu überladen (nur mit delete-selection-mode)

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-SPC - mark is now active
ref = open(|'specific-file-name')
// sp-end-of-sexp (my binding: M-e)
ref = open(<'specific-file-name'|)
// backspace
ref = open(|)

Mark-inside-Sexp-Funktion

smartparensDas Paket hat eine sp-mark-sexpFunktion, die den gesamten nächsten Sexp markiert, dh Trennzeichen und Dinge zwischen ihnen.

Mit einer solchen Funktion können Sie Trennzeichen aus der Auswahl entfernen:

(defun mark-inside-sexp-using-sp ()
  (interactive)
  (sp-mark-sexp)
  (exchange-point-and-mark) (backward-char)
  (exchange-point-and-mark) (forward-char)
  (message "MARK INSIDE SEXP (using sp)"))

(global-set-key (kbd "s-SPC") 'mark-inside-sexp-using-sp)
;; this is "super" modifier (win key) with space

Verlassen Sie Ihren Sexp C-M-uwiederholt und feuern Sie mark-inside-sexp-using-sp ab und entscheiden Sie dann, was mit der aktiven Region geschehen soll.

mmajcher
quelle