Wie setze ich eine Marke in elisp und habe eine Schichtauswahl?


9

Das normale Verhalten von Emacs, wenn der Transient-Mark-Modus aktiv ist, besteht darin, dass bei einer Shift-Auswahl die Markierung deaktiviert wird, wenn der nächste Befehl eine Nicht-Shift-Bewegung ist. Zum Beispiel wird nach den Befehlen M-l(um die aktuelle Zeile mit der folgenden Funktion zu markieren) und C-fdie Markierung deaktiviert. Wie kann man dieses Verhalten von elisp nach emulieren (set-mark-command nil)?

Beispielsweise:

(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (set-mark-command nil)
  (end-of-line)
  (forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

Jetzt wird Ml Cf und die Region wachsen, aber stattdessen möchte ich das Standardverhalten, dh die Region wird deaktiviert, wenn Cf, und mit CSf wachsen.

BEARBEITEN : Sollte eine andere Funktion als der Befehl set-mark-verwendet werden, die dies ermöglicht? Ich konnte keine finden.


Ich glaube, das ist nicht möglich (und ich könnte mich irren). Solange eine Region aktiv ist, ändern Navigationsbefehle die Auswahl. Die Shift-Auswahl mit C-S-fist analog zu C-SPC(Aktivieren einer Region) + C-f(Navigation). Sie können wahrscheinlich das bekommen, was Sie wollen, indem Sie C-f an eine Wrapper-Funktion binden , die zuerst eine Region deaktiviert, wenn sie aktiv ist, und dann fortfährt, was zu tun C-f( forward-char); und C-S-fdirekt binden an forward-char. Beachten Sie, dass , wenn Sie jemals Emacs im Terminal - Modus verwenden, C-fund C-S-fwerden beide verhalten sich wie C-fwie das Terminal zwischen den beiden nicht unterscheiden.
Kaushal Modi

Der Wrapper und die Bindung, für C-fdie Sie sich entschieden haben , gelten auch für alle anderen Navigationsbefehle, die Sie ebenfalls verwenden.
Kaushal Modi

btw C-fnach M-lnicht dem Bereich erstrecken , weil es keinen aktiver Bereich am Ende ist M-l(die gebunden ist downcase-wordStandard).
Kaushal Modi

1
@ KaushalModi Ich denke, dass die M-lvom OP genannte nicht die Standardbindung ( downcase-word) ist, sondern die benutzerdefinierte Bindung vonmy-mark-current-line
nispio

in der Tat @nispio.
Mikl

Antworten:


8

Da die Schichtübersetzung und die vorübergehende Aktivierung der Marke von der Befehlsschleife übernommen werden, müssen Sie die interaktiven Versionen der Bewegungsfunktionen aufrufen, um das entsprechende Schichtauswahlverhalten von ihnen zu erhalten:

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line ()
  (interactive)
  (beginning-of-line)
  (setq this-command-keys-shift-translated t)
  (call-interactively 'end-of-line)
  (call-interactively 'forward-char))

(global-set-key (kbd "M-l") 'my-mark-current-line)

Aktualisieren:

Seit ich die obige Antwort geschrieben habe, habe ich mir die Zeit genommen, etwas mehr darüber zu lernen, wie die Schichtauswahl wirklich unter der Haube funktioniert. Es setzt den Symbolwert transient-mark-modeals Konsolenzelle des Formulars (only . OLDVAL), wobei OLDVALder Wert vor der Schichtauswahl ist.

Die folgende Lösung vermeidet die Verwendung von, call-interactivelyindem die Markierung nach Bedarf aktiviert und der entsprechende Wert von eingestellt wird transient-mark-mode. Grundsätzlich halte ich diese Lösung für weniger hackig als die erste.

Als Bonus hat es jetzt eine optionale Wiederholungszahl und erweitert die aktuelle Auswahl in beide Richtungen, wenn die Markierung bereits aktiv ist.

;; (source: http://emacs.stackexchange.com/a/22166/93)
(defun my-mark-current-line (&optional arg)
  "Uses shift selection to select the current line.
When there is an existing shift selection, extends the selection
in the appropriate direction to include current line."
  (interactive "p")
  (let ((oldval (or (cdr-safe transient-mark-mode) transient-mark-mode))
        (backwards (and mark-active (> (mark) (point))))
        (beg (and mark-active (mark-marker))))
    (unless beg
      (if backwards (end-of-line) (beginning-of-line))
      (setq beg (point-marker)))
    (if backwards (end-of-line (- 1 arg)) (beginning-of-line (+ 1 arg)))
    (unless mark-active
      (push-mark beg nil t))
    (setq transient-mark-mode (cons 'only oldval))))

1
Beide funktionieren perfekt und das alte Ding ist sehr nützlich! Danke vielmals!
Mikl
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.