copiar o conteúdo do buffer atual em um buffer temporário e operar nesse

8

Preciso copiar o conteúdo do buffer atual para um buffer temporário, configurá-lo para um modo principal específico para aproveitar seus benefícios e obter as informações necessárias de volta à lógica principal.

Isso é loucura completa? E se não, qual é a estrutura para isso?

Trevoke
fonte

Respostas:

10

Se você deseja copiar algumas informações para outro buffer e, a partir de então, permitir que os buffers evoluam independentemente, você pode fazer exatamente isso .

Mas se você deseja que o outro buffer reflita o conteúdo original em tempo real, o Emacs fornece isso com buffers indiretos . Um buffer indireto é outro buffer que tem o mesmo conteúdo que o original (modificações em um buffer são refletidas no outro buffer), mas configurações diferentes: um modo principal diferente, modos secundários diferentes, variáveis ​​locais diferentes, um ponto diferente, marcas diferentes , um estreitamento diferente etc.

Assim, é possível visualizar uma parte de um buffer em um modo principal diferente, mantendo o controle das modificações no buffer original e refletindo as modificações de volta ao buffer original. Primeiro faça um buffer indireto com M-x clone-indirect buffer; há também o clone-indirect-buffer-other-windowque está vinculado a C-x 4 c( C-x 4prefixo da janela e cpara clone ). No buffer clonado, restrinja a região que você deseja: selecione a parte interessante e execute C-x n n( narrow-to-region). Mude o modo principal conforme desejado.

Você pode automatizar isso com um comando como este para uso interativo:

(defun edit-region-in-foo-mode (beg end)
  (interactive "@r")
  (let ((new-buffer (clone-indirect-buffer nil t)))
    (narrow-to-region beg end)
    (foo-mode)))

Para uso em programação:

(defmacro with-indirect-buffer-in-foo-mode (beg end &rest body)
  `(with-current-buffer (clone-indirect-buffer nil nil)
     (narrow-to-region beg end)
     (foo-mode)
     (unwind-protect
         ,body
       (kill-buffer (current-buffer)))))
Gilles 'SO- parar de ser mau'
fonte
8

Algo assim:

(let ((old-buffer (current-buffer)))
  (with-temp-buffer
    (insert-buffer-substring old-buffer)
    (my-favourite-major-mode 1)
    (extract-needed-information)))
legoscia
fonte
2
Estava escrevendo quase exatamente isso. Apenas enrole que, em um defun se você precisa ser capaz de chamá-lo de forma arbitrária
Jonathan Sanguessuga-Pepin
Isso parece muito bom. Vou esperar um pouco, apenas no caso existe algo melhor marca como aceitou, mas eu acho que é isso :)
Trevoke
Na verdade M-x copy-to-buffer, eu estava sugerindo , então eu vermelho a resposta @legoscia, que provavelmente é o que você deseja. se o processo de extração e o modo principal são as mesmas, uma função será melhor
Nsukami _
2

Gostei do que @Gilles escreveu. Modifiquei o que o @Gilles escreveu para perguntar ao usuário que modo ele gostaria de usar. Você pode editar o que escrevi para fornecer os modos que preferir ou até alterar a chamada para concluir a leitura, para permitir que você forneça um modo não fornecido na lista padrão.

(defun edit-region-in-mode (beg end)
  "Create an indirect buffer cloned from the current buffer and
  narrowed to the highlighted region. The cloned indirect buffer
  will have org-mode active. Changes to the indirect buffer will
  be updated in real time in the originating buffer. This is
  useful, for instance, when you are in a non-org-mode mode and
  want to edit table data or in a non-emacs-lisp mode and want to
  write some elisp utilizing code formatting and highlighting."
  (interactive "@r")
  (let ((new-buffer (clone-indirect-buffer nil t)))
    (narrow-to-region beg end)
    (funcall
     (intern
      (completing-read
       "Choose the mode you want to use when editing the highlighted region: "
       '(org-mode emacs-lisp-mode lisp-mode haskell-mode julia-mode
          python-mode mathematica-mode matlab-mode c++-mode))))))
Joe
fonte
1

Para um caso de uso semelhante, eu escrevi uma função elisp modi/switch-to-scratch-and-backque permite alternar rapidamente entre um buffer FILE e um buffer * scratch * com o mesmo modo principal que o buffer FILE. A função com hiperlink acima levará você a uma pergunta existente do emacs SE.

Aqui está como você pode usar essa função:

  • Crie uma função de invólucro para copiar seu buffer existente, crie um * scratch * buffer com o mesmo modo principal e cole o conteúdo copiado.

Aqui está um exemplo de função de wrapper

(defun copy-current-buffer-to-scratch ()
 "Copied the current buffer, open scratch, paste it there."
  (interactive)
  (kill-ring-save (point-min) (point-max))
  (modi/switch-to-scratch-and-back)
  (yank))
  • Agora você pode vincular isso copy-current-buffer-to-scratcha uma chave, se desejar, e sua execução fornecerá um buffer * scratch * com o conteúdo do seu buffer de trabalho.
  • Quando estiver satisfeito com as edições no buffer temporário, será necessário copiar manualmente a seção necessária de volta ao buffer original.

Esta é apenas outra maneira de fazer o que você deseja; você pode querer usar buffers indiretos sobre os quais a solução @Gilles fala. Essa abordagem é útil se você precisar fazer algumas edições pesadas em um buffer temporário sem arriscar salvamentos acidentais no buffer original até chegar a uma solução estável.

Um exemplo de caso de uso é experimentar funções elisp experimentais antes de salvá-las no init do emacs.

Kaushal Modi
fonte