Continue indo para o fim das linhas

9

O padrão da ligação de teclas C-a/C-eé apenas uma coisa: vá para o início / fim da linha; existe algum pacote que possa fazer o Emacs agir assim:

  1. Se eu não estiver no final de uma linha, C-eirei para o final da linha, caso contrário, vá para o final da próxima linha
  2. Se eu não estiver no início de uma linha, C-airá para o início da linha, caso contrário, vá para o início da próxima linha.

O ponto é que você pode continuar pressionando C-a/epara ir para o início / fim de cada linha sem mover o dedo para alcançá-lo C-n/p.

E com um prefixo ( C-u), eles irão para o início / fim da linha na direção oposta.

CodyChan
fonte
Em um comentário a uma resposta abaixo, @kaushalmodi indica que eu posso ter interpretado mal sua pergunta. Você quer C-asubir e C-edescer? Em outras palavras, o significado de "próxima linha" é o mesmo nos itens 1 e 2?
Constantine
@ Constantine Eu realmente pensei sobre o problema de " C-asubir e C-edescer" quando postei essa pergunta, mas então pensei que se alguém desse uma defunsolução como você, alguém saberia o que fazer se ele gosta C-ade "subir" ..
CodyChan
ESTÁ BEM; Eu acho que ainda vale a pena consertar. Vou atualizar a resposta - é apenas uma alteração de uma linha.
Constantine

Respostas:

11

Não conheço um pacote que permita esse comportamento, mas aqui está uma maneira de fazê-lo.

Pressione C-h k C-apara descobrir a que C-aestá vinculado move-beginning-of-line; esta é a função que precisamos modificar --- ou apenas usar para implementar a parte "movendo para o início". Da mesma forma, com C-h keu posso encontrar forward-line, que será usado para mover para cima / baixo.

Para poder vincular uma função a uma chave, precisamos transformá-la em um comando , portanto, precisamos usar o interactiveformulário especial (consulte Usando o Interactive ). Para pegar o C-uargumento prefix, precisamos do "P"caractere de código.

Combinando isso com bolp(verifique se no início de uma linha) e eolp(verifique se no final de uma linha), podemos escrever:

(defun my-move-beginning-of-line (arg)
  (interactive "P")
  (when (bolp) (previous-line (if arg -1 1)))
  (move-beginning-of-line nil))

(defun my-move-end-of-line (arg)
  (interactive "P")
  (when (eolp) (forward-line (if arg -1 1)))
  (move-end-of-line nil))

Agora podemos voltar a ligar C-ae C-echamá-los:

(global-set-key [remap move-beginning-of-line] #'my-move-beginning-of-line)
(global-set-key [remap move-end-of-line] #'my-move-end-of-line)

Como alternativa, pode-se adicionar conselhos para move-beginning-of-linee move-end-of-line.

Constantine
fonte
Esta é realmente uma boa explicação e uma solução elegante. Há um erro de digitação na my-move-beginning-of-linefunção. Deve ser (previous-line (if arg -1 1))ou (forward-line (if arg 1 -1))(1 e -1 alternado)?
precisa
@kaushalmodi: na pergunta, os itens 1 e 2 dizem "próxima linha", que eu interpretei como "inativo". Então, vamos perguntar ao autor da pergunta! :-)
Constantine
Ah, eu adicionei minha própria suposição à pergunta do OP. Você está certo, ele especifica ir para a próxima linha ao usar um C-aou outro C-e.
precisa
@kaushalmodi: Acontece que você estava certo! Eu atualizei a resposta para fazer C-asubir ".
Constantine
8

A biblioteca misc-cmds.eltem esse recurso há muito tempo.

Estes são os comandos relevantes e as ligações de teclas sugeridas (essas ligações são feitas em setup-keys.el).

(cond ((fboundp 'move-beginning-of-line)
       (substitute-key-definition 'move-beginning-of-line 'beginning-of-line+ global-map)
       (substitute-key-definition 'move-end-of-line 'end-of-line+ global-map))
      (t
       (substitute-key-definition 'beginning-of-line 'beginning-of-line+ global-map)
       (substitute-key-definition 'end-of-line 'end-of-line+ global-map)))
(when (boundp 'visual-line-mode-map)
  (define-key visual-line-mode-map [remap move-beginning-of-line] nil)
  (define-key visual-line-mode-map [remap move-end-of-line]       nil)
  (define-key visual-line-mode-map [home] 'beginning-of-line+)
  (define-key visual-line-mode-map [end]  'end-of-line+)
  (define-key visual-line-mode-map "\C-a" 'beginning-of-visual-line+)
  (define-key visual-line-mode-map "\C-e" 'end-of-visual-line+)))

Aqui está o que C-h f end-of-line+diz, como um exemplo:

end-of-line+ is an interactive compiled Lisp function in
`misc-cmds.el'.

It is bound to C-e, end.

(end-of-line+ &optional N)

Move cursor to end of current line or end of next line if repeated.
This is similar to `end-of-line', but:
  If called interactively with no prefix arg:
     If the previous command was also `end-of-line+', then move to the
     end of the next line.  Else, move to the end of the current line.
  Otherwise, move to the end of the Nth next line (Nth previous line
     if N<0).  Command `end-of-line', by contrast, moves to the end of
     the (N-1)th next line.
Desenhou
fonte
Isso é muito elegante.
sanityinc
1

As duas funções a seguir executam as ações desejadas.

(defun move-beginning-of-line-or-previous (&optional pre)
  "Move to the start of the line. If we are already at the start
of the line, move to the start of the previous line or, if called 
with a prefix argument, the next line."
  (interactive "P")
  (let* ((pos (point)))
    (move-beginning-of-line nil)
    (if (= (point) pos)
        (if pre
            (next-line)
          (previous-line)))))

(defun move-end-of-line-or-next (&optional pre)
  "Move to the end of the line. If we are already at the end of
the line, move to the end of the next line or, if called with a 
prefix argument, the previous line."
  (interactive "P")
  (let* ((pos (point)))
    (move-end-of-line nil)
    (if (= (point) pos)
        (if pre
            (previous-line)
          (next-line)))))
Patrick Steele
fonte