Убить или скопировать текущую строку с минимальными нажатиями клавиш


32

Я делаю, C-a C-k C-kчтобы убить всю точку, точка включена.

Если я хочу скопировать строку вместо того, чтобы убить ее, я могу нажать C-/ C-/ сразу после ввода последовательности выше.

В качестве альтернативы я могу сделать C-a C-SPC C-n M-w.

Есть ли более быстрый способ убить или скопировать всю точку линии?


1
Вот Это Да! Эти ответы показывают, на сколько люди пойдут, чтобы избежать использования встроенного kill-whole-line. :)
Омар

Как предлагается ниже, используйте evil-mode. Изучайте команды Vim, вы не пожалеете!
A. Blizzard

Ответы:


44

Вы можете использовать, kill-whole-lineчтобы убить всю точку линии. Положение точки не имеет значения. Эта команда связана с C-S-DELпо умолчанию.

Вы также можете указать kill-line(привязать к C-k) убить всю строку, установив переменную kill-whole-line в ненулевое nilзначение:

(setq kill-whole-line t)

Обратите внимание, что точка должна быть в начале строки, чтобы это работало.


Тогда есть эти два драгоценных камня (через emacs-fu ):

(defadvice kill-region (before slick-cut activate compile)
  "When called interactively with no active region, kill a single line instead."
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-beginning-position 2)))))

(defadvice kill-ring-save (before slick-copy activate compile)
  "When called interactively with no active region, copy a single line instead."
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position) (line-beginning-position 2)))))

С их помощью вы можете убить или скопировать точку линии одним нажатием клавиши :

  • C-w убивает текущую строку
  • M-w копирует текущую строку

Обратите внимание, что если есть активный регион, kill-regionи он kill-ring-saveбудет продолжать делать то, что обычно делает: убейте или скопируйте его.


Портирование slick-cutи slick-copyновая система консультаций

Emacs 24.4 представляет новую систему рекомендаций . Хотя defadvice все еще работает , есть вероятность, что в будущих версиях Emacs это может быть признано устаревшим в пользу новой системы. Чтобы подготовиться к этому, вы можете использовать обновленные версии slick-cutи slick-copy:

(defun slick-cut (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-region :before #'slick-cut)

(defun slick-copy (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-ring-save :before #'slick-copy)

2
Обратите внимание, что kill-regionи по- kill-ring-saveпрежнему работает, даже если регион не является «активным». Это переопределит это поведение. Я использую это поведение время от времени, но если вы не привыкли использовать их таким образом, то, вероятно, вы не заметите разницу.
Ниспио

@nispio Пожалуйста, уточните, когда / как и kill-regionт. д. можно использовать / полезно, когда mark-activeесть nil.
Фил Хадсон

1
@PhilHudson Метка может быть (и обычно есть) установлена ​​без активности. Попробуйте выполнить C-SPCдважды, чтобы активировать, а затем деактивировать метку. Переместите курсор в другое место файла и запустите, kill-regionи он убьет область между точкой и меткой, даже если метка не активна. Вот несколько примеров команд, которые устанавливают (но не активируют) метку yankи isearch. После выполнения этих команд я знаю, где находится метка, даже если она не активна, и многие команды (включая kill-region) позволят мне использовать метку без явной ее активации.
Nispio

Спасибо @nispio. Конечно. Так было раньше, до тех пор, пока подсветка видимой области не стала партией по умолчанию в паре основных выпусков, верно? Я путал «активный» с «набором».
Фил Хадсон

1
Это самый лучший ответ, когда-либо размещенный на любом SX. Шутки в сторону.
Бенджамин Линдквист

15

Решение, которое я нашел для себя, заключается в использовании префиксных аргументов.

Для меня убить половину строки - полезная функция, но я хочу и более простой способ убить целые строки. Так что я сделал так, чтобы kill-lineпросто убить все, что видно, если дать префиксный аргумент.

(defmacro bol-with-prefix (function)
  "Define a new function which calls FUNCTION.
Except it moves to beginning of line before calling FUNCTION when
called with a prefix argument. The FUNCTION still receives the
prefix argument."
  (let ((name (intern (format "endless/%s-BOL" function))))
    `(progn
       (defun ,name (p)
         ,(format 
           "Call `%s', but move to BOL when called with a prefix argument."
           function)
         (interactive "P")
         (when p
           (forward-line 0))
         (call-interactively ',function))
       ',name)))

(global-set-key [remap paredit-kill] (bol-with-prefix paredit-kill))
(global-set-key [remap org-kill-line] (bol-with-prefix org-kill-line))
(global-set-key [remap kill-line] (bol-with-prefix kill-line))
(global-set-key "\C-k" (bol-with-prefix kill-line))

С этим маленьким макросом C-kвсе еще убивает из точки, но C-3 C-kпроглатывает три целые строки. В качестве бонуса мы получаем kill-whole-lineповедение, делая C-1 C-k.


Это отличная идея, спасибо, что поделились ею! :) Как бы вы адаптировали это решение для копирования одной или нескольких строк? kill-ring-saveне принимает префиксные аргументы ...
itsjeyd

@itsjeyd Я уверен, что нечто подобное можно было бы сделать, чтобы объединить два ответа. Но это заняло бы немного больше работы.
Малабарба

Последняя строка относится к paredit-kill. Это предназначено?
Boccaperta-IT

1
О, хорошо, спасибо. Я не получаю ожидаемого поведения, хотя. Если я наведу указатель на середину строки и нажму C-3 Ck, первая строка не будет полностью уничтожена. Это так должно работать или я делаю что-то не так?
Boccaperta-IT

1
@ Malabarba ты прав, kill-visual-lineобязательно C-k. Я исправлю это. Еще раз спасибо.
Boccaperta-IT

15

Существует пакет, whole-line-or-regionкоторый называет различные встроенные команды так, чтобы они действовали на текущей строке, если ни один регион не активен, поэтому M-wскопирует текущую строку и C-w, например, уничтожит ее. Я использовал пакет в течение многих лет, и считаю его незаменимым.

Кроме того, этот пакет делает так, чтобы числовой префикс указывал количество строк, на которые нужно воздействовать, поэтому M-2 M-wкопирует две строки. Другие ответы здесь не обеспечивают эту удобную функциональность.

Я взял на себя обслуживание пакета на своем аккаунте github, когда автор прекратил поддерживать его и перестал отвечать на запросы.

whole-line-or-region также предоставляет средства для добавления этого поведения в дальнейшие команды, если вам это нужно.


Пожалуйста, сообщите об этом в MELPA, потому что я не уверен, что вы имеете в виду: я устанавливаю этот пакет из MELPA все время без проблем.
sanityinc

9

Это не ответ для православных Emacs. Однако, если вы хотите поносить evilмодальное редактирование, вы можете:

  • dd для линии уничтожения
  • cc для копирования строки

Оба могут иметь префикс по количеству строк, которые нужно убить / скопировать (например, 4ccбудут скопированы следующие 4 строки).


5

Помимо ответа @itsjeyd, могу ли я предложить эти две функции?

(defun xah-copy-line-or-region ()
  "Copy current line, or text selection.
When `universal-argument' is called first, copy whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-end-position)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-ring-save p1 p2)))

(defun xah-cut-line-or-region ()
  "Cut current line, or text selection.
When `universal-argument' is called first, cut whole buffer (but respect `narrow-to-region')."
  (interactive)
  (let (p1 p2)
    (if (null current-prefix-arg)
        (progn (if (use-region-p)
                   (progn (setq p1 (region-beginning))
                          (setq p2 (region-end)))
                 (progn (setq p1 (line-beginning-position))
                        (setq p2 (line-beginning-position 2)))))
      (progn (setq p1 (point-min))
             (setq p2 (point-max))))
    (kill-region p1 p2)))

Затем ключевые определения (вы, вероятно, захотите их адаптировать):

(global-set-key (kbd "<f2>") 'xah-cut-line-or-region) ; cut

(global-set-key (kbd "<f3>") 'xah-copy-line-or-region) ; copy

(global-set-key (kbd "<f4>") 'yank) ; paste

Предоставлено ErgoEmacs


Спасибо за Ваш ответ! Возможно, вы захотите немного расширить его, описав, как эти команды отличаются от других решений, опубликованных здесь. Да, эта информация доступна в строках документации, но не мешало бы сделать ее более заметной для будущих читателей :)
itsjeyd

1
Можно ли это сделать, но изменить его, как @Jonathan сообщение ниже, так что сначала он берет sexp или слово, а затем принимает строку, если вызывается снова?
Дж Спен

@JSpen То, что я делаю, это назначение функциональной клавиши. То, что делает Джонатан, это определение совета функции. Таким образом, вы можете просто дать совет функции, а затем определить горячую клавишу для рекомендуемой функции; и ты получишь свой результат. Извините за задержку;)
Нсуками _

4

В качестве дополнения к ответу @ itsjeyd выше, у меня есть следующее. (Логика, вероятно, могла бы быть немного очищена, и я сделаю это, когда я портирую на новую систему рекомендаций, я, вероятно, также расширю ее, чтобы расширить до sexp/, paragraphесли повторюсь снова).

Инициал C-w/ M-wбудет захватывать только слово в точке, а при повторном вызове - всю строку.

;; *** Copy word/line without selecting
(defadvice kill-ring-save (before slick-copy-line activate compile)
  "When called interactively with no region, copy the word or line

Calling it once without a region will copy the current word.
Calling it a second time will copy the current line."
    (interactive
     (if mark-active (list (region-beginning) (region-end))
       (if (eq last-command 'kill-ring-save)
           (progn
             ;; Uncomment to only keep the line in the kill ring
             ;; (kill-new "" t)
             (message "Copied line")
             (list (line-beginning-position)
                   (line-beginning-position 2)))
         (save-excursion
           (forward-char)
           (backward-word)
           (mark-word)
           (message "Copied word")
           (list (mark) (point)))))))

;; *** Kill word/line without selecting
(defadvice kill-region (before slick-cut-line first activate compile)
  "When called interactively kill the current word or line.

Calling it once without a region will kill the current word.
Calling it a second time will kill the current line."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
    (if (eq last-command 'kill-region)
        (progn
          ;; Return the previous kill to rebuild the line
          (yank)
          ;; Add a blank kill, otherwise the word gets appended.
          ;; Change to (kill-new "" t) to remove the word and only
          ;; keep the whole line.
          (kill-new "")
          (message "Killed Line")
          (list (line-beginning-position)
                (line-beginning-position 2)))
      (save-excursion
        (forward-char)
        (backward-word)
        (mark-word)
        (message "Killed Word")
        (list (mark) (point)))))))

Вы обновили это, и если да, где находится копия? Кроме того, это добавляет тонну меток к кольцу меток. Можно ли просто добавить одну отметку в начале того места, где она скопирована. Итак, начало слова или начало строки. Теперь он добавляет, как четыре знака каждый раз, что раздражает. Я фактически изменил его, чтобы использовать (backward-sexp), но иногда он не может найти его, и это выдает ошибку. Может ли он просто скопировать строку, если не находит? Я не был уверен, как это сделать или просто игнорировать ошибку и не шуметь. Извини, я не лучший в Лиспе.
Дж Спен

1

Поскольку вы хотите сделать это с минимальными нажатиями клавиш, вы можете использовать превосходный пакет клавишных аккордов Дэвида Андерссона . «Аккорд клавиш» - это две клавиши, нажатые одновременно, или одна клавиша, нажатая дважды.

Вы можете связать любые ключевые аккорды с этими функциями.

(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "dd"  'kill-whole-line)
(key-chord-define-global "cc"  'yank-whole-line)

Спасибо за ваш ответ :) Я пробовал пару аккордов в прошлом и не мог к ним привыкнуть. Но это определенно полезное дополнение к набору, если ответы собраны здесь!
жид

1

Менее специализированный способ - определить mark-whole-line, для чего Emacs действительно должен иметь команду по умолчанию.

(defun mark-whole-line ()               
    "Combinition of C-a, mark, C-e"
    (interactive)
    (move-beginning-of-line nil)
    (set-mark-command nil)
    (move-end-of-line nil)
)
(global-set-key (kbd "C-2") 'mark-whole-line) ; 2 is near w

Тогда C-2 C-wсделаем работу.

Это также облегчает комментирование всей текущей строки.


0

Это модификация ответа от его jejyd - в настоящее время ответ с самым высоким рейтингом, и я использовал его в течение многих лет. Однако у него есть проблемы: рекомендованная версия kill-ring-saveиногда может потерпеть неудачу, потому что метка не установлена ​​(как правило, в новом буфере), и даже когда она работала, курсор использовал странный танец после использования функции для копирования одной строки , После некоторого копания меня осенило, что это происходит, потому что kill-ring-saveвызовы indicate-copied-regionпосле того, как он выполнил свою работу, но, поскольку точки и метки не совпадают с скопированной областью, indicate-copied-regionпомечают неправильную область.

Достаточно сказано. Вот решение, которое исправляет это:

(define-advice kill-ring-save
    (:before-while (beg end &optional region) slick)
  (or mark-active
      (not (called-interactively-p 'interactive))
      (prog1 nil
    (copy-region-as-kill
     (line-beginning-position) (line-beginning-position 2))
    (message "Copied current line"))))

Нет ничего плохого в том, что он советует kill-region. Вот вариант, во всяком случае, стилистически более соответствующий вышесказанному:

(define-advice kill-region
    (:around (kill-region beg end &optional region) slick)
  (if (or mark-active (not region))
      (funcall kill-region beg end region)
    (funcall kill-region
             (line-beginning-position) (line-beginning-position 2))
    (message "Killed current line")))

Обратите внимание, что, если transient-mark-modeне включен, эти советы ничего не делают.


Если вы хотите более комплексное решение, рассмотрите возможность использования пакета whole-line-or-region; см. ответ @sanityinc.
Харальд Ханче-Олсен

0

Я использую пакет под названием composable.el . Отличительной особенностью пакета является то, что он изменяет Mw и Cw (команды копирования и уничтожения) так, чтобы они были более похожими на Vim, так как он принимает вместо этого традиционные команды emacs. Так C-w lубивает целую линию. Но вы также можете делать такие вещи, как C-w M->убить конец файла. Обе команды действуют как обычно при маркировке региона.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.