Відповіді:
У верхній частині моєї голови найближча команда, M-z "
яка видаляє все, від точки до наступної появи символу ".
Існує також C-M-k
aka "знищити врівноважений вираз", який видалить повний скобковий вислів або подвійний цитуваний рядок і т.д. знаходиться на отворі "" "або" ("тощо).
Подібно до пропозиції Джастіна, CM-SPACE дає вам "mark-sexp", який буде обраний до балансуючого батька, цитати та ін., А потім ви можете Cw або що завгодно, щоб змусити його піти. Якщо ви хочете побачити, що ви збираєтесь видалити, перш ніж видалити його ...
Так! Еквівалент команди VIMs ci "в Emacs - це ... ci" :-)
http://www.emacswiki.org/emacs-de/Vimpulse
Просто натрапили на це питання; ось спеціальне рішення, яке працює для мене:
(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))
Потім прив’яжіть видалення між парою до будь-якого клавіші, яке вам подобається. Для мене це пов'язане з Cz i.
Боюся, я не знаю про особливості ci VIM, але ви подивилися на заміну Emacs regexp? Я не можу говорити з точною семантикою чи наскільки легко її використовувати у порівнянні, але це те, що я б використовував для того, що я думаю, що ти хочеш.
Magnars (автор сайту EmacsRocks) написав цей плагін, щоб зробити саме те, що ви просите.
https://github.com/magnars/change-inner.el
Очевидно, ви також могли використовувати режим Evil.
Ось моя версія, яка видалить усе, що знаходиться в межах (або включаючи) відповідної пари символів. Пари символів визначені у списку, так що відомі відповідні початок / кінець символу. Я відобразив його на "Cc i" для змін і "Cc a" для зміни всіх.
Він також копіює вилучені символи на дошку для кліпів, щоб потім вставити їх.
; 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)
Це було щось, що мені не вистачало від Віма, і zap-to-char
, здавалося, не вирішив це правильно.
Ось моя скромна спроба відтворити "ci" та "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))
)
Зазвичай, умова-випадок не є необхідним, оскільки третій (необов'язковий) параметр пошуку вперед / назад-назад призначений для вказівки, що робити у випадку пошуку. Але чомусь розміщення другого пошуку як третього параметра для першого викликає дивну поведінку.
Я спробував рішення тут, але виявив, що кожен із них хоче певним чином, тому я придумав це. Він приймає або початковий, або закінчуючи роздільник, і використовує вбудовані функції Emacs, щоб уникнути необхідності таблиці перекладу для роздільників.
(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)