Continuez d'avancer jusqu'à la fin des lignes

9

La valeur par défaut de la liaison de clé C-a/C-en'est que pour une chose, déplacez-vous au début / à la fin de la ligne, y a-t-il un paquet qui peut faire en sorte qu'Emacs agisse comme ceci:

  1. Si je ne suis pas à la fin d'une ligne, C-eira à la fin de la ligne, sinon, allez à la fin de la ligne suivante
  2. Si je ne suis pas au début d'une ligne, C-aira au début de la ligne, sinon passez au début de la ligne suivante.

Le fait est que vous pouvez simplement continuer à frapper C-a/epour aller au début / à la fin de chaque ligne sans déplacer votre doigt pour l'atteindre C-n/p.

Et avec un préfixe ( C-u), ils iront au début / fin de la ligne dans la direction opposée.

CodyChan
la source
Dans un commentaire à une réponse ci-dessous @kaushalmodi souligne que j'ai peut-être mal interprété votre question. Voulez-vous C-amonter "et C-edescendre"? En d'autres termes, la signification de «ligne suivante» est-elle la même aux points 1 et 2?
Constantine
@Constantine En fait, j'ai pensé au problème " C-amonter et C-edescendre" lorsque j'ai posté cette question, mais j'ai pensé que si quelqu'un donnait une defunsolution comme vous, n'importe qui saurait quoi faire s'il aime C-a"monter" ..
CodyChan
D'ACCORD; Je pense qu'il vaut toujours la peine d'être réparé. Je mettrai à jour la réponse - c'est juste un changement d'une ligne.
Constantine

Réponses:

11

Je ne connais pas de package qui permettrait ce comportement, mais voici une façon de le faire.

Appuyez C-h k C-apour découvrir ce qui C-aest lié à move-beginning-of-line; c'est la fonction que nous devons modifier --- ou simplement utiliser pour implémenter la partie "passer au début". De même, avec C-h kje peux trouver forward-line, qui sera utilisé pour monter / descendre.

Pour pouvoir lier une fonction à une clé, nous devons en faire une commande , nous devons donc utiliser le interactiveformulaire spécial (voir Utilisation d'Interactive ). Pour prendre l' C-uargument préfixe, nous avons besoin du "P"caractère de code.

En combinant cela avec bolp(vérifier si au début d'une ligne) et eolp(vérifier si à la fin d'une ligne), nous pouvons écrire:

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

Maintenant, nous pouvons réaffecter C-aet C-eles appeler:

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

Alternativement, on pourrait ajouter des conseils à move-beginning-of-lineet move-end-of-line.

Constantine
la source
C'est une très bonne explication et une solution élégante. Il y a une faute de frappe dans la my-move-beginning-of-linefonction .. Doit-elle être (previous-line (if arg -1 1))ou (forward-line (if arg 1 -1))(1 et -1 commutée)?
Kaushal Modi
@kaushalmodi: dans la question, les points 1 et 2 disent "ligne suivante", que j'ai interprétée comme "vers le bas". Alors, posons l'auteur de la question! :-)
Constantine
Ah, j'ai ajouté ma propre hypothèse à la question du PO. Vous avez raison, il précise de passer à la ligne suivante lors de l'utilisation de C-aou C-e.
Kaushal Modi
@kaushalmodi: Il s'avère que vous aviez raison! J'ai mis à jour la réponse pour faire C-a"monter".
Constantine
8

La bibliothèque misc-cmds.elpossède depuis longtemps cette fonctionnalité.

Ce sont les commandes pertinentes et les raccourcis clavier suggérés (ces liens sont créés en 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+)))

Voici ce que C-h f end-of-line+dit, à titre d'exemple:

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.
A dessiné
la source
C'est très élégant.
sanityinc
1

Les deux fonctions suivantes exécutent les actions souhaitées.

(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
la source