Продолжайте двигаться до конца строк

9

По умолчанию привязка ключей C-a/C-eиспользуется только для одной цели: перейти к началу / концу строки, есть ли пакет, который может заставить Emacs работать так:

  1. Если я не в конце строки, C-eперейду в конец строки, в противном случае, до конца следующей строки
  2. Если я не в начале строки, C-aперейду к началу строки, в противном случае перейду к началу следующей строки.

Дело в том, что вы можете просто нажимать, C-a/eчтобы перейти к началу / концу каждой строки, не двигая пальцем, чтобы достичь C-n/p.

И с префиксом ( C-u) они пойдут в начало / конец строки в обратном направлении.

CodyChan
источник
В комментарии к ответу ниже @kaushalmodi указывает, что, возможно, я неправильно истолковал ваш вопрос. Вы хотите C-aпойти "вверх" и C-eпойти "вниз"? Другими словами, является ли значение «следующей строки» одинаковым в пунктах 1 и 2?
Константин
@ Константин Я действительно думал о проблеме « C-aвверх и C-eвниз», когда я публиковал этот вопрос, но потом я подумал, что если кто-то даст defunрешение, подобное тебе, кто-нибудь будет знать, что делать, если ему нравится C-a«вверх» ..
CodyChan
ХОРОШО; Я думаю, что это все еще стоит исправить. Я обновлю ответ - это всего лишь изменение в одну строку.
Константин

Ответы:

11

Я не знаю пакета, который бы позволял это поведение, но вот один из способов сделать это.

Нажмите, C-h k C-aчтобы узнать, что C-aсвязано с move-beginning-of-line; это функция, которую мы должны изменить - или просто использовать для реализации части «переход к началу». Точно так же с помощью C-h kя могу найти forward-line, который будет использоваться для перемещения вверх / вниз.

Чтобы иметь возможность привязать функцию к клавише, нам нужно сделать ее командой , поэтому нам нужно использовать interactiveспециальную форму (см. Использование интерактива ). Чтобы взять C-uпрефиксный аргумент, нам нужен "P"символ кода.

Комбинируя это с bolp(проверьте, если в начале строки) и eolp(проверьте, если в конце строки), мы можем написать:

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

Теперь мы можем повторно связать C-aи C-eназвать их:

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

С другой стороны , можно было бы добавить рекомендации к move-beginning-of-lineи move-end-of-line.

Константин
источник
Это действительно хорошее объяснение и элегантное решение. В функции есть опечатка my-move-beginning-of-line. Должно ли это быть (previous-line (if arg -1 1))или (forward-line (if arg 1 -1))(1 и -1 переключены)?
Каушал Моди
@kaushalmodi: в вопросе оба пункта 1 и 2 говорят «следующая строка», которую я интерпретировал как «вниз». Итак, давайте зададим вопрос автору! :-)
Константин
Ах, я добавил свое собственное предположение к вопросу ОП. Вы правы, он указывает на переход к следующей строке при использовании либо C-aили C-e.
Каушал Моди
@kaushalmodi: Оказывается, ты был прав! Я обновил ответ, чтобы сделать C-a"вверх".
Константин
8

Библиотека misc-cmds.elдавно имела эту особенность.

Это соответствующие команды и предлагаемые привязки клавиш (эти привязки сделаны в 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+)))

Вот что C-h f end-of-line+говорит, в качестве одного примера:

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.
Нарисовалась
источник
Это очень элегантно.
sanityinc
1

Следующие две функции выполняют желаемые действия.

(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)))))
Патрик Стил
источник