Töte oder kopiere die aktuelle Zeile mit minimalen Tastenanschlägen

32

Ich C-a C-k C-ktöte den gesamten Linienpunkt auf.

Wenn ich die Zeile kopieren möchte, anstatt sie zu töten, kann ich C-/ C-/ direkt nach dem Eingeben der obigen Sequenz drücken.

Alternativ kann ich tun C-a C-SPC C-n M-w.

Gibt es eine schnellere Möglichkeit, den gesamten Linienpunkt zu töten oder zu kopieren, auf der sich die Option befindet?

itsjeyd
quelle
1
Wow! Diese Antworten zeigen, welche großen Anstrengungen unternommen werden, um die Verwendung der integrierten Funktionen zu vermeiden kill-whole-line. :)
Omar
Wie unten vorgeschlagen, verwenden Sie evil-mode. Lerne Vim Befehle, du wirst es nicht bereuen!
A. Blizzard

Antworten:

44

Sie können verwenden kill-whole-line, um den gesamten Linienpunkt abzutöten, der eingeschaltet ist. Die Position des Punktes spielt keine Rolle. Dieser Befehl ist C-S-DELstandardmäßig gebunden .

Sie können auch anweisen kill-line(gebunden an C-k), die gesamte Zeile abzubrechen, indem Sie die Variable kill-whole-line auf einen Nicht- nilWert setzen:

(setq kill-whole-line t)

Beachten Sie, dass sich der Punkt am Anfang der Zeile befinden muss, damit dies funktioniert.


Dann gibt es diese zwei Edelsteine (via 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)))))

Mit diesen können Sie den Linienpunkt mit einem einzigen Tastendruck beenden oder kopieren :

  • C-w bricht die aktuelle Zeile ab
  • M-w kopiert die aktuelle Zeile

Beachten Sie, dass, wenn es eine aktive Region gibt, diese kill-regionwie kill-ring-savegewohnt weiterarbeitet: Töten oder kopieren Sie sie.


Portierung slick-cutund slick-copyneues Beratungssystem

Emacs 24.4 führt ein neues Hinweissystem ein . Solange es defadvice noch funktioniert , besteht die Möglichkeit, dass es in zukünftigen Versionen von Emacs zugunsten des neuen Systems veraltet ist. Um sich darauf vorzubereiten, sollten Sie aktualisierte Versionen von slick-cutund verwenden 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)
itsjeyd
quelle
2
Beachten Sie, dass kill-regionund kill-ring-savenoch viel Arbeit , auch wenn die Region nicht „aktiv“ . Dies setzt dieses Verhalten außer Kraft. Ich benutze dieses Verhalten von Zeit zu Zeit, aber wenn Sie es nicht gewohnt sind, sie auf diese Weise zu verwenden, werden Sie den Unterschied wahrscheinlich nicht bemerken.
Nispio
@nispio Bitte erweitern auf wann / wie kill-regionetc verwendbar / nützlich , wenn mark-activeist nil.
Phil Hudson
1
@PhilHudson Die Markierung kann (und wird normalerweise) gesetzt, ohne aktiv zu sein. Versuchen Sie es C-SPCzweimal, um die Markierung zu aktivieren und dann zu deaktivieren. Bewegen Sie den Cursor an eine andere Stelle in der Datei und führen kill-regionSie ihn aus. Dadurch wird der Bereich zwischen Punkt und Marke gelöscht, obwohl die Marke nicht aktiv ist. Einige Beispiele für Befehle, die die Markierung setzen (aber nicht aktivieren), sind yankund isearch. Nachdem ich diese Sortierbefehle ausgeführt habe, weiß ich, wo sich die Marke befindet, auch wenn sie nicht aktiv ist, und bei vielen Befehlen (einschließlich kill-region) kann ich die Marke verwenden, ohne sie explizit zu aktivieren.
Nispio
Danke @nispio. Na sicher. So war es früher, bevor die Hervorhebung sichtbarer Bereiche vor einigen wichtigen Releases zum Standard wurde, oder? Ich habe "aktiv" mit "eingestellt" verwechselt.
Phil Hudson
1
Dies ist die beste Antwort, die jemals auf einem SX veröffentlicht wurde. Ernst.
Benjamin Lindqvist
15

Die Lösung, die ich selbst gefunden habe, besteht darin, Präfixargumente zu verwenden.

Das Töten einer halben Linie ist für mich eine nützliche Funktion, aber ich möchte auch eine einfachere Möglichkeit, ganze Linien zu töten. Also habe ich es so gemacht, dass kill-lineeinfach alles in Sichtweite ermordet wird, wenn ein Präfix-Argument angegeben wird.

(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-kTötet mit diesem kleinen Makro immer noch ab Punkt, C-3 C-kschluckt aber drei ganze Zeilen. Als Bonus bekommen wir das kill-whole-lineVerhalten dadurch C-1 C-k.

Malabarba
quelle
Das ist eine großartige Idee, danke, dass du sie geteilt hast! :) Wie würden Sie diese Lösung anpassen, um eine oder mehrere Zeilen zu kopieren? kill-ring-saveakzeptiert keine Präfix-Argumente ...
itsjeyd
@itsjeyd Ich bin sicher, dass etwas Ähnliches getan werden könnte, um die beiden Antworten zusammenzuführen. Aber es würde nur ein bisschen mehr Arbeit erfordern.
Malabarba,
Letzte Zeile bezieht sich auf paredit-kill. Ist es beabsichtigt?
Boccaperta-IT,
1
Oh ok danke Ich bekomme jedoch nicht das erwartete Verhalten. Wenn ich den Zeiger in die Mitte einer Zeile setze und C-3 Ck drücke, wird die erste Zeile nicht vollständig getötet. Soll es so funktionieren oder mache ich etwas falsch?
Boccaperta-IT,
1
@Malabarba du hast recht, kill-visual-lineist gebunden an C-k. Ich werde es reparieren. Danke noch einmal.
Boccaperta-IT
15

Es gibt ein Paket mit dem Namen, whole-line-or-regiondas verschiedene integrierte Befehle anweist, damit sie auf die aktuelle Zeile angewendet werden, wenn keine Region aktiv ist. Dadurch M-wwird beispielsweise die aktuelle Zeile kopiert und beendet C-w. Ich benutze das Paket seit Jahren und finde es unverzichtbar.

Darüber hinaus bewirkt dieses Paket, dass ein numerisches Präfix die Anzahl der zu verarbeitenden Zeilen angibt und M-2 M-wzwei Zeilen kopiert. Die anderen Antworten bieten diese praktische Funktionalität nicht.

Ich habe die Wartung des Pakets auf meinem Github-Konto übernommen, als der Autor die Wartung eingestellt hat und nicht mehr reagiert hat.

whole-line-or-region bietet auch die Möglichkeit, dieses Verhalten zu weiteren Befehlen hinzuzufügen, falls Sie dies benötigen.

sanityinc
quelle
Bitte reichen Sie dafür ein MELPA-Problem ein, da ich nicht sicher bin, was Sie meinen: Ich installiere dieses Paket von MELPA die ganze Zeit über ohne Probleme.
Sanityinc
9

Dies ist keine Antwort für orthodoxe Emacs. Wenn Sie jedoch bereit sind, die evilmodale Bearbeitung zu lästern , haben Sie folgende Möglichkeiten:

  • dd für kill line
  • cc für Kopierzeile

Beiden kann die Anzahl der zu tötenden / zu kopierenden Zeilen vorangestellt werden (z. B. 4ccwerden die nächsten 4 Zeilen kopiert).

Dan
quelle
5

Darf ich neben @itsjeyd answer diese beiden Funktionen vorschlagen?

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

Dann die Schlüsseldefinitionen (Sie werden sie wahrscheinlich anpassen wollen):

(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

Mit freundlicher Genehmigung von ErgoEmacs

Nsukami _
quelle
Danke für deine Antwort! Vielleicht möchten Sie es ein wenig erweitern, indem Sie beschreiben, wie sich diese Befehle von anderen hier veröffentlichten Lösungen unterscheiden. Ja, diese Informationen in den Docstrings vorhanden sind, aber es tut nicht weh , es besser sichtbar für zukünftige Leser zu machen :)
itsjeyd
1
Ist es möglich, dies zu tun, aber es wie @ Jonathan Post unten zu ändern, so dass es zuerst das Sexp oder Wort nimmt und dann die Zeile nimmt, wenn es erneut aufgerufen wird?
J Spen
@JSpen Ich weise der Funktion eine Tastenkombination zu. Was Jonathan tut, ist einen Rat für eine Funktion zu definieren. Sie können die Funktion also nur beraten und dann eine Tastenkombination für die empfohlene Funktion definieren. und Sie werden Ihr Ergebnis haben. Entschuldigung für die Verspätung;)
Nsukami _
4

Als Erweiterung zu @ itsjeyds Antwort oben habe ich Folgendes. (Die Logik könnte wahrscheinlich leicht aufgeräumt werden, und ich werde sie, wenn ich auf das neue Ratgebersystem portiere, wahrscheinlich auch auf sexp/ erweitern, paragraphwenn sie erneut wiederholt wird.)

Ein initiales C-w/ M-wfasst nur das Wort an der Stelle zusammen, während ein zweiter Aufruf die gesamte Zeile erfasst.

;; *** 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)))))))
Jonathan Leech-Pepin
quelle
Haben Sie dies aktualisiert und wenn ja, wo befindet sich eine Kopie? Dies fügt dem Markierungsring auch eine Tonne Markierungen hinzu. Kann es nur eine Markierung am Anfang des Kopierbereichs einfügen? Also der Wortanfang oder der Zeilenanfang. Jetzt werden jedes Mal vier Punkte hinzugefügt, was nervt. Ich habe es tatsächlich geändert, um es zu verwenden (Rückwärts-Sexp), aber manchmal kann es eins nicht finden und es gibt einen Fehler. Kann es die Zeile einfach kopieren, wenn es keine findet? Ich war mir nicht sicher, wie ich das machen sollte, oder habe den Fehler einfach ignoriert und kein Geräusch gemacht. Entschuldigung, ich bin nicht der Beste im Lispeln.
J Spen
1

Da Sie es mit minimalen Tastenanschlägen tun möchten, können Sie das exzellente Key-Chord- Paket von David Andersson verwenden . Ein "Tastenakkord" besteht aus zwei gleichzeitig gedrückten Tasten oder einer einzigen Taste, die zweimal gedrückt wird.

Sie können beliebige Tastenakkorde an diese Funktionen binden.

(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "dd"  'kill-whole-line)
(key-chord-define-global "cc"  'yank-whole-line)
ChillarAnand
quelle
Vielen Dank für Ihre Antwort :) Ich habe in der Vergangenheit ein paar Mal Tastenakkorde ausprobiert und konnte mich nicht wirklich daran gewöhnen. Aber dies ist definitiv eine nützliche Ergänzung zum Set, wenn hier Antworten gesammelt werden!
Es ist der
1

Weniger ad-hoc ist es zu definieren mark-whole-line, für welche Emacs eigentlich einen Standardbefehl haben soll.

(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

Dann C-2 C-wmache ich den Job.

Es erleichtert auch das Kommentieren der aktuellen Zeile.

Chromatisch
quelle
0

Dies ist eine Modifikation der Antwort von itsjeyd - derzeit die Antwort mit der höchsten Stimmenzahl und eine, die ich seit Jahren verwende. Es gibt jedoch einige Probleme: Die empfohlene Version von schlägt kill-ring-savemanchmal fehl, weil die Marke nicht gesetzt ist (normalerweise in einem neuen Puffer), und selbst wenn sie funktioniert hat, hat der Cursor nach Verwendung der Funktion zum Kopieren einer einzelnen Zeile einen seltsamen Tanz ausgeführt . Nach einigem Graben wurde mir klar, dass dies passiert, weil kill-ring-saveAnrufe, indicate-copied-regionnachdem sie ihre Arbeit erledigt haben, aber da Punkt und Markierung nicht mit dem kopierten Bereich übereinstimmen, indicate-copied-regionden falschen Bereich markiert haben.

Genug gesagt. Hier ist eine Lösung, die dies behebt:

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

An itsjeyds Ratschlägen ist nichts auszusetzen kill-region. Hier ist eine Variante davon, die stilistisch mehr mit dem oben Gesagten übereinstimmt:

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

Beachten Sie, dass transient-mark-modediese Hinweise nichts bewirken , wenn sie nicht aktiviert sind.

Harald Hanche-Olsen
quelle
Wenn Sie eine umfassendere Lösung wünschen, sollten Sie whole-line-or-regionstattdessen das Paket verwenden. Siehe die Antwort von @sanityinc.
Harald Hanche-Olsen
0

Ich benutze ein Paket namens composable.el . Das Schöne an dem Paket ist, dass es Mw und Cw (copy and kill -Befehle) modifiziert, um Vim-ähnlicher zu sein, mit dem Unterschied, dass es stattdessen traditionelle Emacs-Befehle akzeptiert. So C-w ltötet eine ganze Reihe. Sie können aber auch Dinge tun C-w M->, um das Dateiende zu beenden. Beide Befehle verhalten sich beim Markieren einer Region normal.

Greth
quelle