Emacs equivalente ao VIM ci "?

13

O emacs tem o equivalente ao comando VIMs ci "? Basicamente, quero substituir o texto dentro de um conjunto de aspas.

No vim eu posso ci) ou ci] ou ci} "mudar interior *" ...

erikcw
fonte

Respostas:

19

Em cima da minha cabeça, o comando mais próximo é o M-z "que apaga tudo, do ponto até a próxima ocorrência do personagem ".

Também existe C-M-k, também conhecido como "matar expressão equilibrada", que excluirá uma declaração entre parênteses completa ou cadeia de caracteres com aspas duplas, etc. com base na definição atual dos modos de "expressão equilibrada" e no caractere atualmente em questão (isto é, só funciona se o cursor está na abertura '"' ou '(' etc.).

Justin Smith
fonte
7

Da mesma forma que a sugestão de Justin, o CM-SPACE fornece "mark-sexp", que seleciona o ponto de equilíbrio, a citação etc., e então você pode Cw ou qualquer outra coisa para fazê-lo desaparecer. Caso você queira VER o que está prestes a excluir antes de excluí-lo ...

Brian Postow
fonte
3

Apenas tropeçou nessa questão; aqui está uma solução personalizada que funcionou para mim:

(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))

Em seguida, vincule excluir entre pares a qualquer tecla que desejar. Para mim, eu tenho isso ligado a Cz i.

ozataman
fonte
2

Receio não conhecer o recurso ci do VIM, mas você já viu o Emacs regexp substituir? Não posso falar com a semântica exata ou com o quão fácil é usar em comparação, mas é o que eu usaria para o que acho que você deseja.

Michael H.
fonte
O emacs regexp replace é equivalente a vi: s / regex / Replacement /, o que ele quer é pressionar a tecla para excluir e substituir a expressão balanceada atual no momento.
Justin Smith
2

Eu fiz um modo menor que fornece algumas dessas instalações do Vim chamadas Markit .

Daimrod
fonte
0

Aqui está minha versão que excluirá tudo dentro (ou incluindo) de um par de caracteres correspondente. Os pares de caracteres são definidos em uma lista para que o caractere inicial / final correspondente seja conhecido. Eu mapeei para "Cc i" para alterar e "Cc a" para alterar todos.

Ele também copia os caracteres removidos para a área de transferência para colar posteriormente.

; 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)
user2549917
fonte
0

Isso era algo que estava faltando no Vim, e zap-to-charnão parecia acertar.

Aqui está minha humilde tentativa de recriar "ci" e "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, o caso de condição não é necessário, uma vez que o terceiro parâmetro (opcional) de pesquisa para frente / pesquisa para trás serve para indicar o que fazer caso a pesquisa falhe. Mas, por alguma razão, colocar a segunda pesquisa como o terceiro parâmetro para a primeira gera um comportamento estranho.

vladimird
fonte
0

Eu tentei as soluções aqui, mas achei que cada uma delas estava querendo de alguma forma, então eu vim com isso. Ele aceita um delimitador inicial ou final e usa funções internas do Emacs para evitar a necessidade de uma tabela de conversão 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) 
Blujay
fonte