Qual é a maneira mais fácil de mover a região ou linha selecionada (se não houver seleção) para cima ou para baixo no emacs? Estou procurando a mesma funcionalidade do eclipse (limitada a M-up, M-down).
Qual é a maneira mais fácil de mover a região ou linha selecionada (se não houver seleção) para cima ou para baixo no emacs? Estou procurando a mesma funcionalidade do eclipse (limitada a M-up, M-down).
Respostas:
Uma linha pode ser movida usando linhas de transposição ligadas aC-x C-t
. Não sei sobre as regiões embora.
Eu encontrei este snippet elisp que faz o que você deseja, exceto que você precisa alterar as ligações.
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
(global-set-key [\M-\S-up] 'move-text-up)
(global-set-key [\M-\S-down] 'move-text-down)
Atualização: Instale o move-text
pacote do Marmalade ou MELPA para obter o seguinte código.
Aqui está o que eu uso, que funciona tanto em regiões quanto em linhas individuais:
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg)
(when (and (eval-when-compile
'(and (>= emacs-major-version 24)
(>= emacs-minor-version 3)))
(< arg 0))
(forward-line -1)))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
(global-set-key [M-S-up] 'move-text-up)
(global-set-key [M-S-down] 'move-text-down)
Você deveria tentar drag-stuff
!
Funciona exatamente como eclipse Alt+ Up/ Downpara linhas simples, bem como para linhas de regiões selecionadas!
Além disso, permite que você mova as palavras com Alt+ Left/. Right
Isso é exatamente o que você está procurando! E está até disponível nos repositórios do ELPA !
Outras soluções nunca funcionaram para mim. Alguns deles estavam com erros (transpondo linhas ao mudar sua ordem, wtf?) E alguns deles estavam se movendo exatamente na região selecionada, deixando partes não selecionadas das linhas em suas posições. Masdrag-stuff
funciona exatamente como no eclipse!
E ainda mais! Você pode tentar selecionar uma região e usar Alt+ Left/Right ! Isso irá transpor a região selecionada em um caractere à esquerda ou à direita. Surpreendente!
Para ativá-lo globalmente, basta executar o seguinte:
(drag-stuff-global-mode)
(drag-stuff-define-keys)
no arquivo init antes que as combinações de teclas comecem a funcionar. Isso é explicado neste github: github.com/rejeep/drag-stuff.el
Eu escrevi algumas funções interativas para mover as linhas para cima / para baixo:
;; move line up
(defun move-line-up ()
(interactive)
(transpose-lines 1)
(previous-line 2))
(global-set-key [(control shift up)] 'move-line-up)
;; move line down
(defun move-line-down ()
(interactive)
(next-line 1)
(transpose-lines 1)
(previous-line 1))
(global-set-key [(control shift down)] 'move-line-down)
As combinações de teclas são no estilo IntelliJ IDEA, mas você pode usar o que quiser. Provavelmente, devo implementar algumas funções que operam em regiões também.
Aqui está meu trecho para mover a linha atual ou as linhas estendidas pela região ativa. Ele respeita a posição do cursor e a região destacada. E não quebrará linhas quando a região não começar / terminar na (s) borda (s) da linha. (É inspirado no eclipse; achei o eclipse muito mais conveniente do que 'linhas de transposição'.)
;; move the line(s) spanned by the active region up/down (line transposing)
;; {{{
(defun move-lines (n)
(let ((beg) (end) (keep))
(if mark-active
(save-excursion
(setq keep t)
(setq beg (region-beginning)
end (region-end))
(goto-char beg)
(setq beg (line-beginning-position))
(goto-char end)
(setq end (line-beginning-position 2)))
(setq beg (line-beginning-position)
end (line-beginning-position 2)))
(let ((offset (if (and (mark t)
(and (>= (mark t) beg)
(< (mark t) end)))
(- (point) (mark t))))
(rewind (- end (point))))
(goto-char (if (< n 0) beg end))
(forward-line n)
(insert (delete-and-extract-region beg end))
(backward-char rewind)
(if offset (set-mark (- (point) offset))))
(if keep
(setq mark-active t
deactivate-mark nil))))
(defun move-lines-up (n)
"move the line(s) spanned by the active region up by N lines."
(interactive "*p")
(move-lines (- (or n 1))))
(defun move-lines-down (n)
"move the line(s) spanned by the active region down by N lines."
(interactive "*p")
(move-lines (or n 1)))
Há uma entrada no wiki do emacs apenas para isso:
http://www.emacswiki.org/emacs/MoveLine
Para regiões em movimento:
Não há embutido. Você pode usar linhas de transposição (Cx Ct), mas não pode repetidamente. Veja as funções em http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/ .
Deve ser fácil adaptá-lo às regiões também.
o transpose-paragraph
função pode ajudá-lo.
Você também pode querer dar uma olhada na seção de transposição no manual do Emacs. Essencialmente:
C-t
Transpose two characters (transpose-chars).
M-t
Transpose two words (transpose-words).
C-M-t
Transpose two balanced expressions (transpose-sexps).
C-x C-t
Transpose two lines (transpose-lines).
Eu uso o pacote smart-shift (em Melpa) para isso. Por padrão, ele é religado C-C <arrow>
para mover uma linha ou região. Ele se move horizontalmente por uma quantidade específica do modo principal (por exemplo, c-basic-offset ou python-indent-offset). Funciona também em regiões.
;; binds C-C <arrows>
(when (require 'smart-shift nil 'noerror)
(global-smart-shift-mode 1))