Respuestas:
Fuera de la parte superior de mi cabeza, el comando más cercano es el M-z "
que elimina todo desde el punto hasta la próxima aparición del "personaje".
También existe C-M-k
, también conocido como "matar la expresión equilibrada", que eliminará una declaración entre paréntesis completa o una cadena entre comillas doble, etc., según la definición de los modos actuales de "expresión equilibrada" y el carácter actualmente bajo el punto (es decir, solo funciona si el cursor está en la apertura '"' o '(' etc.).
De manera similar a la sugerencia de Justin, CM-SPACE le ofrece "mark-sexp", que seleccionará el par de equilibrio, la cita, etc. y luego puede hacer Cw o lo que sea para que desaparezca. En caso de que quiera VER lo que está a punto de eliminar antes de eliminarlo ...
¡Si! El equivalente de VIMs ci "comando en Emacs es ... ci" :-)
http://www.emacswiki.org/emacs-de/Vimpulse
Acabo de tropezar con esta pregunta; Aquí hay una solución personalizada que me funcionó:
(defun seek-backward-to-char (chr)
"Seek backwards to a character"
(interactive "cSeek back to char: ")
(while (not (= (char-after) chr))
(forward-char -1)))
(defun delete-between-pair (char)
"Delete in between the given pair"
(interactive "cDelete between char: ")
(seek-backward-to-char char)
(forward-char 1)
(zap-to-char 1 char)
(insert char)
(forward-char -1))
Luego vincule delete-between-pair a la clave que desee. Para mí, lo tengo vinculado a Cz i.
Me temo que no sé acerca de la función ci de VIM, pero ¿ha visto reemplazar Egecs regexp? No puedo hablar de la semántica exacta o de lo fácil que es usarlo en comparación, pero es lo que usaría para lo que creo que quieres.
Magnars (autor del sitio EmacsRocks) escribió este complemento para hacer exactamente lo que está pidiendo.
https://github.com/magnars/change-inner.el
Obviamente, también puedes usar el modo Evil.
Aquí está mi versión que eliminará todo dentro (o incluyendo) un par de caracteres coincidentes. Los pares de caracteres se definen en una lista para que se conozcan los caracteres iniciales / finales coincidentes. Lo he asignado a "Cc i" para cambiar y "Cc a" para cambiar todo.
También copia los caracteres eliminados en el portapapeles para pegarlos más tarde.
; Re-create ci" ca"...
(defun seek-backward-to-char (chr)
"Seek backwards to a character"
(interactive "cSeek back to char: ")
(while (not (= (char-after) chr))
(forward-char -1)))
(setq char-pairs
'(( ?\" . ?\" )
( ?\' . ?\' )
( ?\( . ?\) )
( ?\[ . ?\] )
( ?\{ . ?\} )
( ?< . ?> )))
(defun get-char-pair (chr)
(let ((result ()))
(dolist (x char-pairs)
(setq start (car x))
(setq end (cdr x))
(when (or (= chr start) (= chr end))
(setq result x)))
result))
(defun get-start-char (chr)
(car (get-char-pair chr)))
(defun get-end-char (chr)
(cdr (get-char-pair chr)))
(defun seek-to-matching-char (start end count)
(while (> count 0)
(if (= (following-char) end)
(setq count (- count 1))
(if (= (following-char) start)
(setq count (+ count 1))))
(forward-char 1)))
(defun seek-backward-to-matching-char (start end count)
(if (= (following-char) end)
(forward-char -1))
(while (> count 0)
(if (= (following-char) start)
(setq count (- count 1))
(if (= (following-char) end)
(setq count (+ count 1))))
(if (> count 0)
(forward-char -1))))
(defun delete-between-pair (char)
"Delete in between the given pair"
(interactive "cDelete between char: ")
(seek-backward-to-matching-char (get-start-char char) (get-end-char char) 1)
(forward-char 1)
(setq mark (point))
(seek-to-matching-char (get-start-char char) (get-end-char char) 1)
(forward-char -1)
(kill-region mark (point)))
(defun delete-all-pair (char)
"Delete in between the given pair and the characters"
(interactive "cDelete all char: ")
(seek-backward-to-matching-char (get-start-char char) (get-end-char char) 1)
(setq mark (point))
(forward-char 1)
(seek-to-matching-char (get-start-char char) (get-end-char char) 1)
(kill-region mark (point)))
(global-set-key (kbd "C-c i") 'delete-between-pair)
(global-set-key (kbd "C-c a") 'delete-all-pair)
Esto era algo que me faltaba de Vim, y zap-to-char
no parecía cortarlo bien.
Aquí está mi humilde intento de recrear "ci" y "ca":
(defun change-outer (str)
(interactive "sChange outer: ")
(condition-case nil
(search-backward str (line-beginning-position))
(error (search-forward str (line-end-position))
(forward-char -1)))
(kill-sexp)
)
(defun change-inner (str)
(interactive "sChange inner: ")
(condition-case nil
(search-backward str (line-beginning-position))
(error (search-forward str (line-end-position))
(forward-char -1)))
(push-mark)
(forward-sexp)
(forward-char -1)
(exchange-point-and-mark)
(forward-char 1)
(kill-region (point) (mark))
)
Normalmente, la condición-caso no es necesaria, ya que el tercer parámetro (opcional) de búsqueda hacia adelante / búsqueda hacia atrás está destinado a indicar qué hacer en caso de que falle la búsqueda. Pero por alguna razón, colocar una segunda búsqueda como el tercer parámetro para el primero produce un comportamiento extraño.
Probé las soluciones aquí, pero encontré que cada una de ellas era de alguna manera, así que se me ocurrió esto. Acepta un delimitador inicial o final, y utiliza funciones integradas de Emacs para evitar la necesidad de una tabla de traducción para delimitadores.
(defun change-inner (prefix character)
"Kill region inside delimiters, using either beginning or
ending delimiter. With prefix arg, kill including delimiters."
(interactive "p\nc")
(let ((initial-point (point))
(start)
(end)
(move-point-by (if (> prefix 1) 0 1)))
(condition-case nil
(progn
;; Search forward for given char
(search-forward (char-to-string character))
(setq end (- (point) move-point-by))
(condition-case nil
(backward-sexp)
(error (backward-list)))
(setq start (+ (point) move-point-by))
(kill-region start end)
(or prefix (forward-char)))
(error (progn
;; Reset and search backward for given char
(goto-char initial-point)
(search-backward (char-to-string character))
(setq start (+ (point) move-point-by))
(condition-case nil
(forward-list)
(error (forward-sexp))))
(setq end (- (point) move-point-by))
(kill-region start end)
(or prefix (backward-char))))))
(global-set-key (kbd "M-i") 'change-inner)
(defun change-outer ()
(interactive)
(let ((current-prefix-arg '(4)))
(call-interactively 'change-inner)))
(global-set-key (kbd "M-o") 'change-outer)