Remplacer le texte à l'intérieur de divers délimiteurs (par exemple: crochets, guillemets)

9

Je fais souvent des tests d'implémentation avec des valeurs codées en dur que je veux changer plus tard. Comme

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

Que je voudrais changer en

ref = open(fname)

Je suis habitué à vim et là je peux taper en ci(fnamesupposant que le point est à l'intérieur des crochets. ( ci(signifie remplacer les supports intérieurs).

Comment puis-je réaliser quelque chose comme «remplacer l'intérieur» dans emacs?

kain88
la source

Réponses:

9

En utilisant expand-region

Je recommanderais d'installer le expand-regionpackage (également disponible sur Melpa). Il serait utile pour éditer les situations mentionnées dans votre exemple et bien plus encore.

expand-regionest intelligent. Basé sur le mode principal, il essaiera de comprendre ce que vous essayez de sélectionner. Je ne sais pas de quelle langue vous avez l'exemple d'extrait, je vais donc utiliser votre exemple d'extrait de code et le modifier légèrement pour Python (supprimer;). Donc mon explication ci-dessous est avec l'extrait de code ci-dessous dans un python-modetampon.

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

Si le point est à côté d'un guillemet simple

Les rectangles verticaux noirs ci-dessous indiquent à quoi ressemblera le curseur.

# 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'▮

Dans les deux cas, lorsque vous le ferez M-x er/expand-region, 'specific-file-name'sera sélectionné et vous pouvez ensuite appuyer sur DEL(ou revenir en arrière) pour supprimer la sélection.

Si vous avez delete-selection-modeactivé (j'aime que cela soit activé personnellement), vous pouvez commencer à taper après avoir fait la sélection et cela écrasera la sélection.

Bien sûr, si vous en utilisez er/expand-regionbeaucoup, vous le lieriez à un raccourci clavier. J'aime le lier à C-\. Donc, avec le point à côté d'une seule citation: C-\fnameme donneraref = open(fname);

entrez la description de l'image ici

Si le point est quelque part à l'intérieur des guillemets

En utilisant expand-region, le point n'a pas besoin d'être près des guillemets. Mais dans ce cas, vous aurez besoin de quelques touches de plus (généralement un ou deux de plus).

Disons que la position du curseur est comme ci-dessous maintenant:

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

En utilisant la même liaison que celle utilisée ci-dessus:

  • La première fois que je frappe, C-\je sélectionnerai specific.
  • Maintenant, je dois juste frapper \pour étendre la sélection ( expand-regionfonctionnalité). Cela sélectionnera specific-file-name.

    Si vous aviez lié er/expand-regionà C-=, frapper à =nouveau fera l'expansion progressive. Lisez sa documentation sur la façon de lier des clés pour une expansion / contraction incrémentielle de la sélection.

  • Frapper \une fois de plus sélectionnera 'specific-file-name'.
  • Maintenant, vous devez appuyer sur DELpour supprimer la sélection, puis taper fname. Si delete-selection-modeest activé, vous pouvez ignorer le DELtrait.

En résumé, avec delete-selection-modepermis, les frappes ressemblent: C-\\\fname.

entrez la description de l'image ici


En utilisant change-inner

Je suis également tombé sur le change-innerpackage de l' expand-regionauteur magnars (qui l'utilise expand-regioncomme back-end) pour faire exactement ce que fait le Vim ci(et aussi changer externe ).

À partir du package README:

change-innervous donne le cicommandement de vim , en s'appuyant sur expand-region. Cela s'explique plus facilement par l'exemple:

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

Avec un point après le mot sémantique

change-inner "tuerait le contenu de la chaîne
change-outer "tuerait la chaîne entière
change-inner {tuerait la déclaration de retour
change-outer {tuerait le bloc entier

Kaushal Modi
la source
3

Avec une région

Pour ce faire avec une région, à partir de:

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

appuyez sur C-SPC C-b C-M-n C-b C-w.

Un moyen plus rapide

À partir du point avant le paren, comme dans Vim:

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

C-M-k( kill-sexp) entraînera:

ref = open|;

Si vous avez electric-pair-modeactivé, vous pouvez réinsérer ()avec uniquement (. Ainsi, la séquence de touches complète est C-M-k (- pas beaucoup plus longue que ci(.

abo-abo
la source
1
En outre, si le point est avant la citation à gauche, ref = open(|'specific-file-name');, C-M-kdonnera ref = open(|);. Les citations sont également des sexps équilibrés .
Kaushal Modi
Je pensais à une delete-everything-inside-parenssorte de chose, non delete-first-sexp-inside-parens.
abo-abo
Belle solution mais il me faut déplacer le point avant l'expression que je veux remplacer. Le package 'change inner' fonctionne quand le point est n'importe où dans l'expression (comme vi).
kain88
1

evil émule la plupart de Vim, et il fait des objets texte hors de la boîte.

En d'autres termes, avec evilactivé et en utilisant les raccourcis clavier par défaut, ci(fera exactement ce que vous demandez: changer ce qui est à l'intérieur des parenthèses englobantes.

Plus précisément, ci(sera enchaîné evil-changeà evil-inner-paren. Vous pouvez également créer vos propres objets texte arbitraires à votre guise.

Dan
la source
Je connais le mal (je l'utilise depuis un moment maintenant). Je voudrais savoir comment cela peut être fait dans des emacs «purs».
kain88
@ kain88: assez bien: je pense qu'il y aura plusieurs réponses à cette question. Par curiosité, cependant, si vous l'utilisez déjà evil, pourquoi voudriez-vous la non evilalternative?
Dan
(commentaire non sérieux) @Dan Il se prépare probablement à venir du côté obscur.
Kaushal Modi
J'ai remarqué que le mal ne joue pas toujours bien avec d'autres modes. De plus, je suis curieux de voir comment l'édition utiliserait simplement emacs
kain88
1

Utilisation de smartparens

Tuer

1) Utilisez C-M-u( sp-backward-up-sexp) pour sortir des 'délimiteurs.

2) Utilisez C-0 C-M-k( 0préfixe + sp-kill-sexp) pour tuer des choses dans sexp actuel ou C-k( sp-kill-hybrid-sexp). Ce dernier ne fonctionne que lorsqu'il smartparens-strict-modeest activé et que le sexp actuel tient sur une seule ligne.

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

Marquer et supprimer / tuer / copier

1) Trouvez votre chemin vers le début de sexp (dans cet exemple C-M-u sp-backward-up-sexpsuffit), marquez C-SPCet allez à la fin de sexp avec sp-end-of-sexp.

2) Ensuite, vous pouvez faire tout ce que vous voulez: C-wtuer la région, M-wtuer la zone de sauvegarde (copier), la backspacesupprimer sans encombrer le kill ring (uniquement avec 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(|)

Fonction Mark-inside-sexp

smartparensle paquet a une sp-mark-sexpfonction qui marque tout le prochain sexp, c'est-à-dire des délimiteurs et des trucs entre eux.

Vous pouvez utiliser une fonction comme celle-ci pour supprimer les délimiteurs de la sélection:

(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

Sortez de votre sexp en utilisant à C-M-uplusieurs reprises et lancez mark-inside-sexp-using-sp, puis décidez quoi faire avec la région active.

mmajcher
la source