Reemplazar texto dentro de varios delimitadores (por ejemplo, corchetes, comillas)

9

A menudo hago algunas implementaciones de prueba con valores codificados que luego quiero cambiar. Me gusta

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

Que me gustaría cambiar a

ref = open(fname)

Estoy acostumbrado a vim y allí puedo escribir ci(fnameasumiendo que ese punto está dentro de los corchetes. ( ci(significa reemplazar los soportes internos).

¿Cómo puedo lograr algo como 'reemplazar interno' en emacs?

kain88
fuente

Respuestas:

9

Utilizando expand-region

Recomendaría instalar el expand-regionpaquete (también disponible en Melpa). Sería útil para editar situaciones mencionadas en su ejemplo y mucho más.

expand-regiones inteligente. Según el modo principal, intentará descubrir qué está intentando seleccionar. No sé de qué idioma tiene el fragmento de ejemplo, por lo que utilizaré su fragmento de código de ejemplo y lo modificaré ligeramente para Python (eliminar;). Entonces, mi explicación a continuación es con el fragmento de código a continuación en un python-modebúfer.

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

Si el punto está al lado de una comilla simple

Los rectángulos verticales negros a continuación indican cómo se verá el cursor.

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

En cualquier caso, cuando lo haga M-x er/expand-region, 'specific-file-name'se seleccionará y luego podrá presionar DEL(o retroceder) para eliminar la selección.

Si ha delete-selection-modehabilitado (me gusta habilitarlo personalmente), puede comenzar a escribir después de hacer la selección y eso sobrescribirá la selección.

Por supuesto, si usa er/expand-regionmucho, lo vincularía a una combinación de teclas corta. Me gusta vincularlo C-\. Entonces, con un punto al lado de una sola cita: C-\fnameme daráref = open(fname);

ingrese la descripción de la imagen aquí

Si el punto está en algún lugar dentro de las comillas

Usando expand-region, el punto no necesita estar cerca de las comillas. Pero en este caso, necesitará unas pocas pulsaciones de teclas más (generalmente una o dos más).

Digamos que la posición del cursor es la siguiente ahora:

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

Usando el mismo enlace que usé anteriormente:

  • La primera vez que golpee C-\seleccionaré specific.
  • Ahora solo necesito presionar \para expandir la selección ( expand-regionfunción). Eso lo seleccionará specific-file-name.

    Si tenía que er/expand-regionhacerlo C-=, golpear =nuevamente hará la expansión incremental. Lea su documentación sobre cómo vincular teclas para la expansión / contracción incremental de la selección.

  • Golpear \una vez más seleccionará 'specific-file-name'.
  • Ahora continúa presionando DELpara eliminar la selección y luego escribe fname. Si delete-selection-modeestá habilitado, puede omitir el DELtrazo.

En resumen, la delete-selection-modehabilita, las pulsaciones de teclas se ven como: C-\\\fname.

ingrese la descripción de la imagen aquí


Utilizando change-inner

También me encontré con el change-innerpaquete del expand-regionautor Magnars (que usa expand-regioncomo back-end) para hacer exactamente lo que hace el Vim ci(y también cambiarlo externamente ).

Del paquete README:

change-innerda de que vim cicomando, sobre la base expand-region. Se explica más fácilmente con un ejemplo:

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

Con punto después de la palabra semántica

change-inner "mataría el contenido de la cadena
change-outer "mataría toda la cadena
change-inner {mataría la declaración de retorno
change-outer {mataría todo el bloque

Kaushal Modi
fuente
3

Con una region

Para hacer esto con una región, a partir de:

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

presione C-SPC C-b C-M-n C-b C-w.

Manera más rápida

Comenzando desde el punto anterior a paren, al igual que en Vim:

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

C-M-k( kill-sexp) dará como resultado:

ref = open|;

Si tiene electric-pair-modeactivado, puede volver a insertarlo ()solo (. Entonces, la secuencia de teclas completa es C-M-k (, no mucho más larga que ci(.

abo-abo
fuente
1
Además, si el punto está antes de la cita a la izquierda ref = open(|'specific-file-name');, C-M-kdará ref = open(|);. Las citas también son sexps equilibrados .
Kaushal Modi
Estaba pensando en delete-everything-inside-parensalgo así, no delete-first-sexp-inside-parens.
abo-abo
Buena solución pero requiere que mueva el punto antes de la expresión que quiero reemplazar. El paquete 'cambiar interno' funciona cuando el punto está en cualquier lugar dentro de la expresión (igual que vi).
kain88
1

evil emula la mayoría de Vim, y hace objetos de texto fuera de la caja.

En otras palabras, con la evilactivación y el uso de las combinaciones de teclas predeterminadas, ci(hará exactamente lo que está pidiendo: cambiar lo que está dentro de los paréntesis.

Más precisamente, ci(se encadenará evil-changea evil-inner-paren. También puede crear sus propios objetos de texto arbitrarios como desee.

Dan
fuente
Sé sobre el mal (lo he usado por un tiempo ahora). Me gustaría saber cómo se puede hacer esto en emacs 'puros'.
kain88
@ kain88: bastante justo: calculo que habrá múltiples respuestas a esta pregunta. Sin embargo, por curiosidad, si ya lo usa evil, ¿por qué querría la no evilalternativa?
Dan
(comentario no serio) @Dan Probablemente se está preparando para venir al lado oscuro.
Kaushal Modi
Noté que el mal a veces no juega bien con otros modos. Además, tengo curiosidad por ver cómo la edición usaría solo emacs
kain88
1

Usando smartparens

Matar

1) Use C-M-u( sp-backward-up-sexp) para salir de los 'delimitadores.

2) Use C-0 C-M-k( 0prefijo + sp-kill-sexp) para matar cosas dentro del sexp actual o C-k( sp-kill-hybrid-sexp). Este último solo funciona cuando smartparens-strict-modeestá habilitado y el sexp actual se ajusta en una línea.

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

Marcar y borrar / matar / copiar

1) Encuentra tu camino al comienzo de sexp (en este ejemplo C-M-u sp-backward-up-sexpes suficiente), marca C-SPCy ve al final de sexp con sp-end-of-sexp.

2) Luego puede hacer lo que desee: C-wmatar a la región, matar a la región M-wde guardar el anillo (copiar), backspaceeliminarla sin saturar el anillo de matar (solo con 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(|)

Función Mark-inside-sexp

smartparensEl paquete tiene una sp-mark-sexpfunción que marca el próximo sexp completo, es decir, delimitadores y cosas entre ellos.

Puede usar una función como esta para eliminar delimitadores de la selección:

(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

Sal de tu sexp usando C-M-urepetidamente y dispara mark-inside-sexp-using-sp y luego decide qué hacer con la región activa.

mmajcher
fuente