Como selecionar regiões não contíguas no Emacs?

31

Suponha que eu já tenha selecionado algum texto no buffer atual. É possível selecionar outro trecho de texto, mantendo a seleção anterior (e assim por diante)?

Adicionado : Uma motivação para essa funcionalidade é a seguinte: Suponha que eu tenha algum texto parecido com este:

paragraph 1 ...

paragraph 2 ...

paragraph 3 ...

paragraph 4 ...

paragraph 5 ...

Gostaria de remover alguns parágrafos (por exemplo, 2, 4 e 6) e inseri-los antes do parágrafo 1.

Nome
fonte
1
Há uma seleção secundária .
Wasamasa 7/15
2
Existe um pacote multiselect: skamphausen.de/cgi-bin/ska/multiselect Parece um hack rápido.
Tobias
Dependendo do tamanho do que você está selecionando e do motivo, multiple-cursorspode dar uma solução.
Jordon Biondo
@wasamasa Segui as instruções fornecidas no link que você forneceu. Após a primeira seleção, selecionei a segunda região, mantendo a tecla Meta. Foi selecionado, mas há dois problemas: (1) a segunda seleção parece não ser uma seleção real, pois copiar ou excluir não funciona. (2) não é possível selecionar uma terceira seleção dessa maneira.
Name
1
O Wiki do Emacs tem uma boa seção sobre a seleção secundária . Vários aprimoramentos tornam o teclado mais utilizável, por exemplo.
Tirou

Respostas:

43

Você pode usar append-next-kill(vinculado C-M-wpor padrão) para acumular o texto que deseja inserir acima paragraph 1:

  1. Mate paragraph 2como faria normalmente.

  2. Marque paragraph 4e pressione C-M-wantes de matá-lo. Repita esta etapa para todos os parágrafos que você deseja mover antes paragraph 1.

Quando terminar, você pode puxar o texto acumulado antes paragraph 1.

itsjeyd
fonte
5
Mesmo com o básico, sempre há coisas novas para aprender! Isso é bastante útil, pois geralmente desperdiço muita tecla pressionando o anel de matar quando preciso fazer isso. Gostaria de poder upvote isso um pouco mais ...
Meaningful Usuário
9

Você pode usar registros combinados com o anel da marca. Empurre as marcas atuais com C-<SPC> C-<SPC>, recupere-as mais tarde com C-u C-<SPC>ou salve-as em um registro, digamos b, via C-x r <SPC> be volte mais tarde com C-x r j b.

Agora marque outra região. C-u C-x r s acopiará a região marcada para registrar ae excluir o texto. Em seguida, marque a próxima região e C-u C-x r + aanexará outra seleção a esse registro ae a excluirá.

Você pode inserir o conteúdo com C-x r i a.

Consulte a seção "Salvando texto nos registros" do manual do Emacs.

Andrew Swann
fonte
5

O novo suporte à região retangular no Emacs-24.4 realmente introduziu (grande parte) a infraestrutura necessária para essa funcionalidade [afinal, uma região retangular é uma região não contígua].

Portanto, agora deve ser possível implementar um pacote de "região dividida" que forneça exatamente a funcionalidade que você está solicitando.

É certo que muitos comandos do Emacs ainda não foram adaptados para usar a nova infraestrutura (por exemplo, comandos como upcase-region ou undo-in-region, query-replace, ...) e, portanto, ainda não funcionam corretamente em retângulos (para que eles também não funcionassem corretamente em uma "região dividida"), mas esses são erros que esperamos que sejam corrigidos com o tempo.

Stefan
fonte
4

Instale browse-kill-ring.el

copie e mate todas as regiões de interesse.

Chegou ao ponto onde a reinserção deve começar.

M-x browse-kill-ring RET irá abrir um buffer e colocar o cursor nele.

Digite npara viajar em pedaços.

RET lá irá inserir o pedaço no ponto no original / outro buffer.

Andreas Röhler
fonte
3

Se as linhas que você deseja manipular puderem ser distinguidas por meio de uma correspondência de regex, use o modo de ocorrência para visualizá-las em uma nova janela. Você pode usar o modo de edição de ocorrências para editá- los, com o buffer original refletindo as alterações feitas no buffer Ocorrer.

Isso funciona maravilhosamente, por exemplo, em combinação com o modo de cursores múltiplos : como as linhas que você selecionou para aparecer no buffer Ocorrer são exibidas de forma contígua, independentemente da distância que estão no buffer original, você pode marcar todos eles ou um subconjunto e, em seguida, ative mc/edit-linese edite todos de uma vez. (Sim, eu sei que vários cursores podem fazer isso sozinhos mc/mark-all-like-this, mas é bom ter opções.)

Qualquer outra operação de edição que seria mais fácil se você estivesse vendo apenas as linhas nas quais queria trabalhar, como configurar uma pesquisa e substituição complicada de regex ou uma macro que precise ser executada em cada linha de um buffer por sua vez, também pode ser feito dessa maneira.

dodgethesteamroller
fonte
3

Isso responde à sua pergunta geral, mas não particularmente ao caso de uso mencionado (movendo bits de código).

O Emacs agora tem o que chama de região não contígua , que é o tipo de seleção que você está perguntando. O Vanilla Emacs não fornece nenhuma maneira especial de criar uma região não contígua, exceto se for um retângulo . Mas a biblioteca Zones sim.

As zonas da biblioteca permitem definir várias zonas no seu buffer. Uma lista de zonas é uma região não contígua . Você também pode pensar nele como várias regiões, dependendo de como deseja utilizá-lo. Você pode ter várias listas de zonas definidas a qualquer momento, cada uma atribuída a uma variável de zonas diferentes, e pode alternar entre elas.

Se você também usar a biblioteca Bookmark + , poderá salvar as listas de zonas persistentemente e restaurá-las nas sessões posteriores do Emacs. O Marcador + também permite atribuir tags arbitrárias a um marcador. Isso significa que você pode marcar uma lista de zonas.

As zonas em uma determinada lista de zonas geralmente estão no mesmo buffer, mas não precisam estar. Nesse caso, uma lista de zonas é mais geral que uma região não contígua. Também é mais geral, pois cada zona pode conter informações adicionais, além dos limites da zona, e pode ter um identificador.

Existem várias maneiras de criar uma zona. Um dos mais fáceis é usar C-x n a: define uma zona da região ativa e a adiciona ao conjunto de zonas atual. ( C-x n n( narrow-to-region) também faz isso, além de restringir.)

Estas são algumas das ações que você pode fazer com um conjunto (lista) de zonas:

  • Classifique-os.
  • Unir (unir) zonas adjacentes ou sobrepostas (o que inclui a classificação).
  • Intersectá-los.
  • Limite o buffer a uma zona da lista. Ciclo entre estreitamentos. Consulte Várias restrições .
  • Selecione uma zona na lista como a região ativa. Ciclo entre regiões.
  • Pesquise-os (eles são automaticamente unidos primeiro). Para isso, você precisa da biblioteca Isearch + .
  • Substitua a consulta sobre eles.
  • Destaque e não destaque. (Para isso, você precisa da biblioteca Highlight ou library facemenu+.el.

Consulte também Narrow Indirect , que permite criar buffers indiretos que são clones de um determinado buffer e que são limitados a diferentes partes dele.

Desenhou
fonte
2

Outra opção: transposição de parágrafos

Por uma questão de completude, você pode obter sua reordenação de parágrafos (sequencialmente) com regiões marcadas e M-0 M-x transpose-paragraph(o argumento zero faz com que tra-paros parágrafos sejam trocados nos pontos e marcas, ou seja, a região começa e termina)!

A propósito, isso funciona para todos os transpose-.*comandos (-words, -sexp, -sentences, ...) e é extremamente útil em muitas situações.

Dieter.Wilhelm
fonte
2

Outra maneira é usar o pacote contestado (eu sou o autor). Você pode marcar qualquer objeto de texto com mo ponto que é movido automaticamente para o próximo objeto do tipo atual. Desmarque qualquer objeto navegando até ele e pressione m novamente. Aqui está um exemplo de screencast (mostra linhas de marcação, mas funciona para outros objetos, como parágrafos, desafia ... também):

insira a descrição da imagem aqui

clemera
fonte
Quando tento instalar este pacote da Melpa, recebo o erro package-install-from-archive: http://melpa.milkbox.net/packages/objed-20181201.1346.tar: Not found.
Nome
@Name Isso parece necessário para atualizar sua lista de pacotes. Tente M-x package-refresh-contentse então M-x package-install.
Clemera
@Name Funciona agora? Diga-me se tiver mais perguntas.
Clemera
Eu consegui instalar o pacote. Parece funcionar bem, não testei todos os seus recursos. Obrigado.
Name