Touche «vue rapide» fatiguée pour prévisualiser le fichier au point

19

Je voudrais créer une fonction qui fait une "vue rapide" d'un fichier sous le point dans dired.

La façon dont j'aimerais que cela fonctionne est que je maintiens une touche de fonction, ce qui rend ensuite le fichier visible dans un tampon, mais lorsque je relâche la clé, le tampon se ferme et le tampon dired revient. Je ne veux pas avoir à fermer le tampon temporaire avec C-x k .

Existe-t-il un moyen de rendre cette fonctionnalité dans Emacs? Cela semble possible si je peux lier des fonctions à une pression sur une touche / une pression.

Eric Brown
la source
1
Vous ne pouvez pas vous lier pour appuyer sur des événements de dépression, mais cette fonctionnalité peut certainement être piratée avec l'utilisation d'une carte personnalisée et d'une minuterie.
Jordon Biondo du
Parlez-vous d'une nouvelle fenêtre avec un aperçu? Ou le contenu du tampon serait-il affiché dans la fenêtre dirigée pendant que la touche est enfoncée?
nispio
1
Y a-t-il des efforts pour nous permettre de nous lier aux événements? Je veux cette fonctionnalité.
wdkrnls

Réponses:

9

Voici ma façon super hacky de simuler la liaison d'événements bas / haut en profitant des minuteurs.

Dans l'ensemble, je suggère de suivre la réponse de Sigma, mais vous avez demandé un moyen de fermer l'aperçu en le lâchant, donc je suis obligé d'essayer.

Fondamentalement, ce que vous pouvez faire est de lier une fonction qui sera votre fonction "keydown" à une liaison de touches et à l'intérieur de cette action, démarrez un temporisateur inactif qui exécute une fonction qui est votre fonction "keyup", tant que vous maintenez la touche étant donné les touches, la fonction "keydown" se déclenchera encore et encore et cela empêchera les minuteries inactives de fonctionner. Bien sûr, vous devez compenser le fait que la commande se déclenchera encore et encore, probablement en reliant la clé à une sorte de fonction noop dans votre fonction "keydown", puis en reliant la fonction "keydown" dans la fonction "keyup".

Donc, pour votre cas d'utilisation, votre fonction "keydown" ouvrira un tampon de prévisualisation avec le contenu du fichier au point et dans ce tampon de prévisualisation liera le même combo de touches à une commande de type noop. Votre fonction "keydown" démarrera également une minuterie inactive qui supprimera votre tampon d'aperçu et vous ramènera où vous étiez.

En bref, voici le code:

Liez cette fonction à un combo de touches (j'ai utilisé C-M-v), lorsque vous appuyez dessus au-dessus d'un nom de fichier, il ouvrira un nouveau tampon affichant le contenu du fichier au point, lorsque vous relâcherez, vous reviendrez à l'original tampon.

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

Voici également un gif de celui-ci en action, tout ce que je fais est:

  • placer mon curseur sur le fichier
  • appuyez et maintenez ma liaison
  • l'aperçu s'affiche
  • quand je lâche prise, l'aperçu est tué et vous êtes de retour où vous étiez.

entrez la description de l'image ici

Une chose importante à noter est les secondes de la minuterie inactive, dans mon code que j'ai utilisé .7mais c'est une sorte de nombre magique, vous voulez le garder vraiment petit, mais si vous voyez l'aperçu clignoter deux fois, essayez de l'augmenter 1 / 10e de seconde à chaque fois jusqu'à ce que vous trouviez le bon endroit pour votre machine.

* Notez également que dans la fonction, j'essaie de faire une police de caractères du tampon d'aperçu, mais je n'ai pas pu le faire fonctionner, ce sera la prochaine étape pour le rendre plus utile. **

Jordon Biondo
la source
Agréable! C'est le genre de chose que nous devons voir ici.
Malabarba
Je reçois un Error running timer: (void-variable buffer)avec cela, il semble que le buffervar ne soit pas disponible à l'intérieur du run-with-idle-timer?
Lee H
Assurez-vous que la liaison lexicale est t
Jordon Biondo
Vous voudrez peut-être répéter cette réponse là-bas .
Malabarba
8

Comme indiqué dans les commentaires, les fonctions sont liées à des clés et non à des événements. Mais pour prendre du recul, je ne suis pas sûr de comprendre pourquoi il est important pour vous de garder la clé pendant que vous lisez (vraisemblablement) le contenu du fichier. Il serait également incompatible avec des actions de base (et raisonnables) comme le défilement pour en obtenir plus. Sans parler du fait que si cela prend un certain temps, cela pourrait devenir inconfortable :)

Et si vous répétiez une touche à la place? Quelque chose comme ce qui suit pourrait être le squelette de base d'un équivalent fonctionnel:

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

Quoi qu'il en soit, je conteste plus votre cas d'utilisation que de répondre à votre question à ce stade, car cela n'a rien à voir avec les raccourcis clavier / enfoncement :)

Sigma
la source
J'imagine une longue liste de fichiers en dired. Je ne sais pas quel est le contenu de chacun des fichiers. si je pouvais F5 pour voir, laissez F5 pour arrêter de regarder et être de retour dans Dired, puis passez au candidat suivant, etc. Je ne pense pas que vous avez réfuté mon cas d'utilisation, mais vous avez peut-être suggéré une bonne alternative basée en appuyant à nouveau sur F5 pour arrêter la visualisation.
Eric Brown
ce que vous proposez est comparable à la fonctionnalité de Midnight Commander (F3)
Eric Brown
1
La réponse soumise par @Sigma est intéressante. Mais lorsque vous parcourez un répertoire à l'aide de dired, vous pouvez déjà appuyer sur v pour afficher le fichier, et lors de la visualisation de ce fichier, appuyez sur q pour quitter et revenir au répertoire. Je suppose qu'il est plus facile d'appuyer sur la même touche pour afficher et quitter.
Nsukami _
@LeMeteore merci de me le rappeler dired-view-file! J'ai modifié mon code pour en tirer parti. Oui, je suppose que dans ce genre de scénario, ne pas avoir à passer à une autre clé est important.
Sigma
4

Au lieu d'afficher le fichier pendant qu'une touche est enfoncée, ce qui serait très difficile à mettre en œuvre, je suggère d'afficher le fichier jusqu'à ce que la touche suivante soit enfoncée.

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

Voici une variante qui montre le fichier dans une autre fenêtre, qui je pense est une interface utilisateur plus pratique.

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

Vous ne pourrez pas faire autant que faire défiler le tampon. Il pourrait être plus judicieux d'implémenter un mode «vue rapide» où les commandes de défilement sont acceptées, mais d'autres événements d'entrée provoquent la fermeture du mode vue rapide et sont interprétés selon le mode précédent, comme Isearch.

Avec v( dired-view-file), vous obtenez quelque chose d'intermédiaire: le tampon est édité en mode Affichage , où vous pouvez faire défiler, rechercher, etc. mais la fermeture du tampon est la simple frappe q.

Gilles 'SO- arrête d'être méchant'
la source
2

Une autre possibilité, si vous utilisez une souris, est de mettre l'aperçu souhaité dans une info - bulle . Ensuite, lorsque vous déplacez la souris sur un nom de fichier (avec propriété help-echo), l'aperçu s'affiche.

J'utilise cette technique dans Dired + , par exemple, pour afficher (éventuellement) des aperçus des images associées aux fichiers image, lorsque vous survolez les noms de fichier.

Vous pouvez voir l'effet de ceci en faisant ceci après le chargement dired+.el:

  • Assurez -vous que tooltip-modeest activée: (tooltip-mode 1).

  • Assurez-vous que cette option diredp-image-preview-in-tooltipn'a pas de nilvaleur (soit la taille de la vignette, soit fullune image en taille réelle).

  • Placez le pointeur de la souris sur un nom de fichier image dans Dired.

Vous pouvez utiliser le code de fonction diredp-mouseover-helpcomme source d'inspiration pour faire ce que vous voulez (afficher votre "vue rapide" au survol de la souris). Voir les appels de cette fonction pour savoir comment l'utiliser. Voici un tel appel:

 (add-text-properties (line-beginning-position) (line-end-position)
                      '(mouse-face highlight help-echo diredp-mouseover-help))
A dessiné
la source
Vous m'avez perdu à "si vous utilisez une souris". ;-) Cela ne fonctionne pas pour moi. image-diredfonctionne bien, mais tout ce que je vois quand je passe la souris estmouse-1: visit this file/dir in another window
nispio
Vous ne verrez pas ce que j'ai dit si vous ne chargez pas dired+.elet suivez les autres instructions que j'ai données. Ce n'est pas une fonctionnalité Emacs vanille. J'essayais de décrire comment vous pouvez faire rouler votre propre code pour faire ce que vous voulez. Le dired+.elcode est très proche, je pense, de ce que vous dites vouloir. Mais oui, les info-bulles de survol nécessitent l'utilisation d'une souris. Si vous ne le faites pas, la suggestion d'utiliser une info-bulle n'aidera pas beaucoup. ;-)
Drew
Je comprends comment charger des packages et suivre les instructions, mais cela ne fonctionne pas pour moi. Je ne sais pas comment reprendre cette conversation dans le chat, mais nous devrions peut-être le faire.
nispio
1

À partir d'un tampon dired, vvisitera un fichier en mode lecture seule, qquittera le mode vue et vous ramènera au tampon dired. C'est un moyen rapide de prévisualiser un fichier, et il donne la possibilité de faire défiler et même de rechercher le tampon.

Je ne pense pas qu'emacs ait la capacité de transmettre les messages de pression de bas niveau qu'il reçoit du système d'exploitation. Cela peut être en partie pour des raisons historiques. Les terminaux disponibles pour les pirates (lire "programmeurs") au moment où emacs était développé dans les années 1970-1980 ne fonctionnaient pas avec des événements de montée / descente de touches en temps réel, mais plutôt une simple entrée de caractères et de séquences d'échappement. À ce jour, emacs peut encore fonctionner de manière impressionnante dans les limites d'un simple terminal ou d'une session SSH en utilisant uniquement des caractères ASCII simples et des séquences d'échappement.

Cela ne veut pas dire que la fonctionnalité n'a pas considérablement augmenté au fil des ans pour inclure des fonctionnalités telles que les menus, la gestion de plusieurs cadres et l'interaction avec la souris. Il n'y a aucune raison (à ma connaissance) que les emacs ne puissent pas être modifiés (à sa base) pour rendre les messages clés de bas niveau disponibles pour les extensions, mais je ne retiendrais pas votre souffle.

( Avertissement: ce message doit être considéré comme une opinion et une spéculation, plutôt que comme un fait dur.)

nispio
la source
1

J'ai donné ma solution dans cette question SO /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- tampon

et ma réponse est de changer le comportement des touches de navigation net pd'afficher le fichier au point dans une autre fenêtre. Le focus reste dans le tampon dired et nous tuons le tampon visité lorsque nous continuons la navigation.

J'ai créé un mode mineur pour activer / désactiver facilement cette fonctionnalité. Notez que nous avons encore les touches fléchées pour une navigation «normale». Appelez M-x dired-show-mode(ou ranger-modepuisque c'est une fonctionnalité que j'ai découverte dans le gestionnaire de fichiers ranger ).

Le code: (toute révision et rapport de bogue apprécié!) 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
la source
0

Vous devez interroger la file d'attente d'événements jusqu'à ce qu'un événement différent, ou aucun, soit lu. La charge du processeur est perceptible, bien que raisonnablement faible.

(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
la source