Réponses:
Du haut de ma tête, la commande la plus proche est celle M-z "
qui supprime tout du point à la prochaine occurrence du "caractère".
Il y a aussi C-M-k
, alias "tuer l'expression équilibrée", qui supprimera une instruction entre parenthèses complète ou une chaîne entre guillemets, etc. basée sur la définition des modes actuels de "l'expression équilibrée" et le caractère actuellement sous le point (c'est-à-dire que cela ne fonctionne que si le curseur est sur l'ouverture "" "ou" ("etc.).
De manière similaire à la suggestion de Justin, CM-SPACE vous donne "mark-sexp" qui sélectionnera la paren d'équilibrage, la citation, etc. et ensuite vous pouvez Cw ou quoi que ce soit pour le faire disparaître. Si vous souhaitez voir ce que vous êtes sur le point de supprimer avant de le supprimer ...
Oui! L'équivalent de la commande VIMs ci "dans Emacs est ... ci" :-)
http://www.emacswiki.org/emacs-de/Vimpulse
Je suis juste tombé sur cette question; voici une solution personnalisée qui a fonctionné pour moi:
(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))
Ensuite, liez la suppression entre paires à la clé que vous souhaitez. Pour moi, je l'ai lié sur Cz i.
J'ai bien peur de ne pas connaître la fonctionnalité ci de VIM, mais avez-vous regardé la regexp Emacs remplacer? Je ne peux pas parler de la sémantique exacte ou de la facilité d'utilisation en comparaison, mais c'est ce que j'utiliserais pour ce que je pense que vous voulez.
Magnars (auteur du site EmacsRocks) a écrit ce plugin pour faire exactement ce que vous demandez.
https://github.com/magnars/change-inner.el
Évidemment, vous pouvez également utiliser le mode Evil.
Voici ma version qui supprimera tout dans (ou y compris) une paire de caractères correspondante. Les paires de caractères sont définies dans une liste afin que le caractère de début / fin correspondant soit connu. Je l'ai mappé à "Cc i" pour le changement et "Cc a" pour le changement de tous.
Il copie également les caractères supprimés dans le presse-papiers pour un collage ultérieur.
; 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)
C'était quelque chose qui me manquait à Vim, et zap-to-char
ne semblait pas le faire correctement.
Voici mon humble tentative de recréer "ci" et "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))
)
Normalement, la condition-case n'est pas nécessaire, car le troisième paramètre (facultatif) de search-forward / search-backward est destiné à indiquer quoi faire en cas d'échec de la recherche. Mais pour une raison quelconque, placer une seconde recherche comme troisième paramètre pour la première donne un comportement étrange.
J'ai essayé les solutions ici, mais j'ai trouvé que chacune d'elles manquait d'une certaine manière, alors j'ai trouvé cela. Il accepte un délimiteur de début ou de fin et utilise des fonctions Emacs intégrées pour éviter d'avoir besoin d'une table de traduction pour les délimiteurs.
(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)