Dired "Schnellansicht" -Taste, um eine Vorschau der Datei zu Punkt

19

Ich möchte eine Funktion erstellen, die eine "Schnellansicht" einer Datei erstellt, auf die in dired verwiesen wird.

Ich möchte, dass dies funktioniert, indem ich eine Funktionstaste drücke, die die Datei dann in einem Puffer sichtbar macht. Wenn ich die Taste jedoch loslasse, wird der Puffer geschlossen und der dired-Puffer wird zurückgegeben. Ich möchte den temporären Puffer nicht mit schließen müssen C-x k .

Gibt es eine Möglichkeit, diese Funktionalität in Emacs zu implementieren? Es scheint möglich, wenn ich Funktionen mit Tastendruck / Drücken verknüpfen kann.

Eric Brown
quelle
1
Sie können nicht festlegen, ob Ereignisse gedrückt werden sollen, aber diese Funktionalität kann definitiv mithilfe einer benutzerdefinierten Karte und eines Timers gehackt werden.
Jordon Biondo
Sprechen Sie von einem neuen Fenster mit einer Vorschau? Oder wird der Inhalt des Puffers im dired-Fenster angezeigt, während die Taste gedrückt wird?
Nispio
1
Gibt es Bestrebungen, uns an Ereignisse binden zu lassen? Ich möchte diese Funktion.
wdkrnls

Antworten:

9

Hier ist meine supergeile Methode, um die Ereignisbindung beim Herunter- und Hochfahren von Tasten zu simulieren, indem ich Timer nutze.

Insgesamt würde ich vorschlagen, sich Sigmas Antwort anzuschließen, aber Sie haben nach einer Möglichkeit gefragt, die Vorschau zu schließen, indem Sie loslassen, und ich bin verpflichtet, es zu versuchen.

Grundsätzlich können Sie eine Funktion, die Ihre "keydown" -Funktion ist, an eine Tastenkombination binden und in dieser Aktion einen Leerlauf-Timer starten, der eine Funktion ausführt, die Ihre "keyup" -Funktion ist, solange Sie die Taste gedrückt halten Bei bestimmten Tasten wird die Funktion "keydown" immer wieder ausgelöst, und dies verhindert, dass die Leerlaufzeitgeber ausgeführt werden. Natürlich müssen Sie die Tatsache ausgleichen, dass der Befehl immer wieder ausgelöst wird, indem Sie wahrscheinlich die Taste in Ihrer "keydown" -Funktion mit einer Noop-Funktion neu binden und dann die "keydown" -Funktion in der "keyup" -Funktion neu binden.

Für Ihren Anwendungsfall öffnet Ihre "keydown" -Funktion einen Vorschau-Buffer mit dem Inhalt der Datei an der Stelle und bindet in diesem Vorschau-Buffer dieselbe Tastenkombination an einen noop-ähnlichen Befehl. Mit der "Tastendruck" -Funktion wird auch ein Leerlauf-Timer gestartet, der Ihren Vorschau-Puffer löscht und Sie wieder dorthin zurückversetzt, wo Sie sich befanden.

Kurz gesagt, hier ist der Code:

Binden Sie diese Funktion an eine Tastenkombination (die ich verwendet habe C-M-v). Wenn Sie sie oben auf einen Dateinamen drücken, wird ein neuer Puffer geöffnet, der den Inhalt der Datei an dem Punkt anzeigt, an dem Sie loslassen, und Sie werden zum Original zurückgeschaltet Puffer.

(setq lexical-binding t)

(defun quick-view-file-at-point ()
  "Preview the file at point then jump back after some idle time.

In order for this to work you need to bind this function to a key combo, 
you cannot call it from the minibuffer and let it work.

The reason it works is that by holding the key combo down, you inhibit
idle timers from running so as long as you hold the key combo, the 
buffer preview will still display."
  (interactive)
  (let* ((buffer (current-buffer))
         (file (thing-at-point 'filename t))
         (file-buffer-name (format "*preview of %s*" file)))
    (if (and file (file-exists-p file))
        (let ((contents))
          (if (get-buffer file)
              (setq contents (save-excursion
                               (with-current-buffer (get-buffer file)
                                 (font-lock-fontify-buffer)
                                 (buffer-substring (point-min) (point-max)))))
            (let ((new-buffer (find-file-noselect file)))
              (with-current-buffer new-buffer
                (font-lock-mode t)
                (font-lock-fontify-buffer)
                (setq contents (buffer-substring (point-min) (point-max))))
              (kill-buffer new-buffer)))
          (switch-to-buffer (get-buffer-create file-buffer-name))
          (setq-local header-line-format "%60b")
          (delete-region (point-min) (point-max))
          (save-excursion (insert contents))
          (local-set-key (kbd "C-M-v") (lambda () (interactive) (sit-for .2)))
          (run-with-idle-timer
           .7 
           nil
           (lambda ()
             (switch-to-buffer buffer)
             (kill-buffer file-buffer-name))))
      (message "no file to preview at point!"))))

Auch hier ist ein GIF davon in Aktion, alles was ich tue ist:

  • platziere meinen Mauszeiger über der Datei
  • drücke und halte meine Tastenkombination
  • Die Vorschau wird angezeigt
  • Wenn ich loslasse, wird die Vorschau beendet und Sie sind wieder da, wo Sie waren.

Bildbeschreibung hier eingeben

Eine wichtige Sache, die zu beachten ist, sind die Sekunden des Leerlauf-Timers, die ich in meinem Code verwendet habe, .7aber es ist eine Art magische Zahl. Sie möchten sie wirklich klein halten bis Sie den richtigen Platz für Ihre Maschine finden.

* Beachten Sie auch, dass ich in der Funktion versuche, den Vorschau-Puffer ein wenig zu fontifizieren, aber nicht zum Laufen bringen kann. Dies ist der nächste Schritt, um ihn nützlicher zu machen. **

Jordon Biondo
quelle
Nett! So etwas müssen wir hier sehen.
Malabarba
Ich bekomme eine Error running timer: (void-variable buffer)mit, es sieht so aus, als ob die buffervar nicht innerhalb der run-with-idle-timer?
Lee H
Stellen Sie sicher, dass die lexikalische Bindung t ist
Jordon Biondo
Vielleicht möchten Sie diese Antwort dort wiederholen .
Malabarba
8

Wie in Kommentaren erwähnt, sind Funktionen an Tasten gebunden, nicht an Ereignisse. Um einen Schritt zurückzutreten, bin ich mir nicht sicher, warum es wichtig ist, dass Sie die Taste gedrückt halten, während Sie (vermutlich) den Inhalt der Datei lesen. Es wäre auch nicht kompatibel mit einfachen (und vernünftigen) Aktionen wie Scrollen, um mehr davon zu bekommen. Ganz zu schweigen von der Tatsache, dass es unangenehm werden kann, wenn es eine Weile dauert :)

Wie wäre es, wenn Sie stattdessen einen Schlüssel wiederholen ? So etwas wie das folgende könnte das Grundgerüst eines funktionalen Äquivalents sein:

(defun my-dired-view-file ()
  (interactive)
  (dired-view-file)
  (local-set-key (kbd "<f5>") 'View-quit))

(define-key dired-mode-map (kbd "<f5>") 'my-dired-view-file)

Wie auch immer, ich bin an dieser Stelle eine größere Herausforderung für Ihren Anwendungsfall als die Beantwortung Ihrer Frage, da dies nichts mit Tastendruck- / Druckbindungen zu tun hat :)

Sigma
quelle
Ich stelle mir eine lange Liste von Dateien im Verzeichnis vor. Ich bin mir nicht sicher, was der Inhalt der einzelnen Dateien ist. Wenn ich F5 anzeigen könnte, lassen Sie F5 los, um die Anzeige zu beenden, und kehren Sie in die Ausgangslage zurück. Fahren Sie dann mit dem nächsten Kandidaten fort. Ich glaube, Sie haben meinen Anwendungsfall nicht widerlegt, aber Sie haben möglicherweise eine gute Alternative vorgeschlagen Drücken Sie erneut F5, um die Anzeige zu beenden.
Eric Brown
Was Sie vorschlagen, ist vergleichbar mit der Funktionalität in Midnight Commander (F3)
Eric Brown
1
Die Antwort von @ Sigma ist interessant. Wenn Sie jedoch ein Verzeichnis mit dired durchsuchen, können Sie bereits v drücken, um die Datei anzuzeigen, und wenn Sie diese Datei anzeigen, drücken Sie q, um das Verzeichnis zu verlassen und zum Verzeichnis zurückzukehren. Ich denke, dass es einfacher ist, dieselbe Taste zum Anzeigen und Beenden zu drücken.
Nsukami _
@LeMeteore danke, dass du mich daran erinnert hast dired-view-file! Ich habe meinen Code bearbeitet, um ihn zu nutzen. Ja, ich denke in einem solchen Szenario ist es wichtig, nicht zu einem anderen Schlüssel wechseln zu müssen.
Sigma
4

Anstatt die Datei anzuzeigen, während eine Taste gedrückt wird, was sehr schwierig zu implementieren wäre, empfehle ich, die Datei anzuzeigen, bis die nächste Taste gedrückt wird.

(defun dired-find-file-until-key ()
  (interactive)
  (let ((filename (dired-file-name-at-point))
    (buffer-count (length (buffer-list))))
    (dired-find-file)
    (message "Showing %s temporarily..." filename)
    (isearch-unread-key-sequence (list (read-event)))
    (if (= (length (buffer-list)) buffer-count)
    (bury-buffer)
      (kill-buffer))))

Hier ist eine Variante, die die Datei in einem anderen Fenster anzeigt, was meiner Meinung nach eine bequemere Benutzeroberfläche darstellt.

(defun dired-find-file-other-window-until-key ()
  (interactive)
  (let ((buffer-count (length (buffer-list))))
    (dired-find-file-other-window)
    (isearch-unread-key-sequence (list (read-event)))
    (if (= (length (buffer-list)) buffer-count)
    (delete-window)
      (kill-buffer-and-window))))

Sie können nicht einmal im Puffer scrollen. Es ist möglicherweise sinnvoller, einen Schnellansichtsmodus zu implementieren, in dem Bildlaufbefehle akzeptiert werden. Bei anderen Eingabeereignissen wird der Schnellansichtsmodus jedoch beendet und entsprechend dem vorherigen Modus interpretiert, z. B. Isearch.

Mit v( dired-view-file) erhalten Sie etwas Mittelmäßiges: Der Puffer wird im Ansichtsmodus bearbeitet, in dem Sie scrollen, suchen usw. können. Das Schließen des Puffers ist jedoch ein einfacher Tastendruck q.

Gilles 'SO - hör auf böse zu sein'
quelle
2

Wenn Sie eine Maus verwenden, können Sie die gewünschte Vorschau auch in eine QuickInfo einfügen . Wenn Sie dann mit der Maus über einen Dateinamen (mit Eigenschaft help-echo) fahren, wird die Vorschau angezeigt.

Ich verwende diese Technik beispielsweise in Dired + , um (optional) eine Vorschau der mit Bilddateien verknüpften Bilder anzuzeigen, wenn Sie mit der Maus über die Dateinamen fahren.

Sie können den Effekt sehen, indem Sie dies nach dem Laden tun dired+.el:

  • Stellen Sie sicher , dass tooltip-modeeingeschaltet: (tooltip-mode 1).

  • Stellen Sie sicher, dass diese Option diredp-image-preview-in-tooltipkeinen nilWert enthält (entweder die Größe der Miniaturansicht oder fullein Bild in voller Größe).

  • Platzieren Sie den Mauszeiger über einem Bilddateinamen in Dired.

Sie können den Funktionscode diredp-mouseover-helpals Inspiration verwenden, um das zu tun, was Sie wollen (zeigen Sie Ihre "Schnellansicht" beim Mouseover an). Informationen zur Verwendung dieser Funktion finden Sie in den Aufrufen dieser Funktion. Hier ist ein solcher Anruf:

 (add-text-properties (line-beginning-position) (line-end-position)
                      '(mouse-face highlight help-echo diredp-mouseover-help))
Drew
quelle
Du hast mich bei "wenn du eine Maus benutzt" verloren. ;-) Das funktioniert bei mir nicht. image-diredfunktioniert gut, aber alles, was ich sehe, wenn ich mit der Maus darüber mouse-1: visit this file/dir in another window
fahre,
Sie werden nicht sehen, was ich gesagt habe, wenn Sie nicht laden dired+.elund den anderen Anweisungen folgen, die ich gegeben habe. Es ist kein Vanille-Emacs-Feature. Ich habe versucht zu beschreiben, wie Sie Ihren eigenen Code rollen können, um das zu tun, was Sie wollen. Der dired+.elCode ist sehr nah, wie ich glaube, zu dem, was Sie sagen , Sie wollen. Aber ja, für QuickInfos mit dem Mauszeiger muss eine Maus verwendet werden. Wenn Sie dies nicht tun, hilft der Vorschlag, einen Tooltip zu verwenden, nicht viel. ;-)
Drew
Ich verstehe, wie man Pakete lädt und Anweisungen befolgt, aber das funktioniert bei mir nicht. Ich bin nicht sicher, wie ich dieses Gespräch im Chat wieder aufnehmen soll, aber vielleicht sollten wir das tun.
Nispio
1

Ruft aus einem dired-Puffer veine Datei im Nur- qAnsichtsmodus auf, beendet den Ansichtsmodus und bringt Sie zurück zum dired-Puffer. Dies ist eine schnelle Möglichkeit, eine Vorschau einer Datei anzuzeigen, und bietet die Möglichkeit, den Puffer zu scrollen und sogar zu durchsuchen.

Ich glaube nicht, dass Emacs die Möglichkeit hat, Tastendrucknachrichten auf niedriger Ebene weiterzuleiten, die es vom Betriebssystem empfängt. Dies kann teilweise historische Gründe haben. Die Terminals, die Hackern zu der Zeit, als der Emacs in den 1970er und 1980er Jahren entwickelt wurde, zur Verfügung standen (sprich "Programmierer"), arbeiteten nicht mit Auf / Ab-Ereignissen in Echtzeit, sondern mit einer einfachen Eingabe von Zeichen und Escape-Sequenzen. Bis heute können Emacs im Rahmen einer einfachen Terminal- oder SSH-Sitzung mit nur einfachen ASCII-Zeichen und Escape-Sequenzen eindrucksvoll arbeiten.

Das heißt nicht, dass die Funktionalität im Laufe der Jahre nicht wesentlich erweitert wurde, um Funktionen wie Menüs, Verwaltung mehrerer Frames und Mausinteraktion einzubeziehen. Es gibt keinen Grund (dessen bin ich mir bewusst), dass Emacs (im Kern) nicht geändert werden könnten, um wichtige Nachrichten auf niedriger Ebene für Erweiterungen verfügbar zu machen, aber ich würde Ihren Atem nicht anhalten.

( Haftungsausschluss: Dieser Beitrag sollte eher als Meinung und Spekulation denn als harte Tatsache verstanden werden.)

Nispio
quelle
1

Ich habe meine Lösung in dieser Frage SO /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- Puffer

und meine antwort ist, das verhalten der navigationstasten zu ändern nund pdie datei an einer stelle in einem anderen fenster anzuzeigen. Der Fokus bleibt im dired-Puffer und wir löschen den besuchten Puffer, wenn wir weiter surfen.

Ich habe einen Minor-Modus erstellt, um diese Funktion einfach zu aktivieren / deaktivieren. Beachten Sie, dass wir noch die Pfeiltasten für die «normale» Navigation haben. Anruf M-x dired-show-mode(oder ranger-modeda dies eine Funktion ist, die ich im Ranger- Dateimanager entdeckt habe).

Der Code: (Kritik und Fehlerbericht erwünscht!) Https://gitlab.com/emacs-stuff/my-elisp/blob/master/dired-show.el

(defgroup dired-show nil
  "See the file at point when browsing in a Dired buffer."
  :group 'dired
  )

(setq show-next-current-buffer nil)

(defun show-next ()
     (interactive)
     (next-line 1)
     (dired-find-file-other-window)
     (if show-next-current-buffer (kill-buffer show-next-current-buffer))
     (setq show-next-current-buffer (current-buffer))
     (other-window 1)
     )

(defun show-previous ()
     (interactive)
     (previous-line 1)
     (dired-find-file-other-window)
     (if show-next-current-buffer (kill-buffer show-next-current-buffer))
     (setq show-next-current-buffer (current-buffer))
     (other-window 1)
     )


(define-minor-mode dired-show-mode
  "Toggle preview of files when browsing in a Dired buffer."
  :global t
  :group 'dired-show
  (if dired-show-mode
      (progn
        (define-key dired-mode-map "n" 'show-next)
        (define-key dired-mode-map "p" 'show-previous)
        )
  (define-key dired-mode-map "n" 'diredp-next-line)
  (define-key dired-mode-map "p" 'diredp-previous-line)
  ))

(defalias 'ranger-mode 'dired-show-mode)

(provide 'dired-show)
;;; dired-show ends here
Ehvince
quelle
0

Sie müssen die Ereigniswarteschlange abfragen, bis ein anderes oder keines der Ereignisse gelesen wurde. Die CPU-Auslastung ist spürbar, wenn auch relativ niedrig.

(defun dired-preview-command ()
  (interactive)
  (let* ((file (or (dired-get-filename nil t)
                   (error "No file here")))
         (visited-p (get-file-buffer file))
         (buffer (or visited-p (find-file-noselect file)))
         (window
          (display-buffer buffer '(nil . ((inhibit-same-window . t)))))
         (event (read-event)))
    (while (and event (eq last-command-event event))
      (setq event (read-event nil nil 0.1)))
    (when event
      (setq unread-command-events
            (list event)))
    (quit-window (not visited-p) window)))
Politza
quelle