Для попереднього перегляду файлу в точці використана клавіша "швидкого перегляду"


19

Я хотів би створити функцію, яка робить "швидкий перегляд" файлу, який знаходиться під точкою в діред.

Я хотів би, щоб це працювало, це те, що я утримую функціональну клавішу, яка потім робить файл видимим у буфері, але коли я відпускаю ключ, буфер закривається, і введений буфер повертається. Мені не хочеться закривати тимчасовий буфер C-x k .

Чи є спосіб зробити цю функціональність в Emacs? Мабуть, можливо, якщо я можу прив’язати функції до натискання / натискання клавіш.


1
Ви не можете прив’язати натискання подій депресії, але ця функціональність напевно може бути зламана за допомогою користувацької карти та таймера.
Джордон Біондо

Ви говорите про те, що з’явиться нове вікно з попереднім переглядом? Або вміст буфера відображатиметься у вибраному вікні під час натискання клавіші?
nispio

1
Чи є зусилля, які дозволяють нам пов'язуватися з подіями? Я хочу цю функцію.
wdkrnls

Відповіді:


9

Ось мій супер хакітний спосіб імітувати прив'язку клавіш вниз / вгору, скориставшись таймерами.

В цілому я б запропонував відповісти від Sigma, але ви попросили спосіб закрити попередній перегляд, відпустивши його, тому я зобов'язаний спробувати.

В основному, що ви можете зробити - прив’язати деяку функцію, яка буде вашою функцією "клавіші", для клавіатури, і всередині цієї дії запустіть таймер очікування, який виконує функцію, яка є вашою функцією "клавіатури", поки ви утримуєте клавішу Якщо натиснути клавіші, функція "keydown" буде спрацьовувати знову і знову, і це заважатиме запущеним таймерам працювати. Звичайно, ви повинні компенсувати той факт, що команда буде стріляти знову і знову, ймовірно, повторним прив'язкою ключа до якоїсь функції noop у вашій функції "keydown", потім повторним прив'язкою функції "keydown" у функції "keyup".

Отже, у випадку використання, функція "клавіш" відкриє буфер попереднього перегляду із вмістом файлу в точці, і в цьому буфері попереднього перегляду пов'язують ту саму клавішну комбінацію з якоюсь командою noop типу. Ви "функція клавіатури" також запустить таймер очікування, який видалить попередній буфер і відновить вас там, де ви були.

Короткий сюжет короткий ось код:

Прив’яжіть цю функцію до комбінації клавіш (я використав C-M-v), коли ви натиснете її вгорі на ім'я файлу, вона відкриє новий буфер із відображенням вмісту файлу в момент, коли ви відпустите вас, ви повернетеся до оригіналу буфер.

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

Крім того, тут є gif цього дії, і все, що я роблю, це:

  • розміщую мій курсор над файлом
  • натисніть і утримуйте моє в'язання клавіш
  • відображається попередній перегляд
  • коли я відпускаю, попередній перегляд вбивається, і ти знову там, де ти був.

введіть тут опис зображення

Одне важливе, що слід зазначити, - це секундомір простою таймера, у моєму коді я використовував, .7але це якесь магічне число, ви хочете, щоб воно було дійсно невеликим, але якщо ви бачите, що попередній перегляд блимає двічі, спробуйте підняти його на 1/10 секунди кожен раз поки ви не знайдете потрібне місце для своєї машини.

* Також зауважте, що у цій функції я намагаюся виконати деяку деталізацію буфера попереднього перегляду, але мені не вдалося змусити його працювати, це стане наступним кроком для того, щоб зробити його більш корисним. **


Приємно! Це щось таке, що нам тут потрібно бачити.
Малабарба

Я розумію Error running timer: (void-variable buffer), це виглядає, що buffervar не доступний всередині run-with-idle-timer?
Лі Н

Переконайтесь, що лексичне зв’язування є t
Джордон Біондо

Ви можете повторити цю відповідь там .
Малабарба

8

Як зазначається в коментарях, функції прив’язані до клавіш, а не до подій. Але, щоб зробити крок назад, я не впевнений, що розумію, чому вам важливо утримувати ключ, поки ви (мабуть) читаєте вміст файлу. Це також було б несумісне з основними (і розумними) діями, такими як прокрутка, щоб отримати більше від цього. Не кажучи вже про те, що якщо це пройде певний час, це може стати незручно :)

А як повторити ключ замість цього? Щось подібне може бути базовим скелетом функціонального еквівалента:

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

У будь-якому випадку, я більш складний у вашому випадку використання, ніж відповідь на ваше запитання в цей момент, оскільки це не має нічого спільного з прив'язкою клавіш / натисканням :)


Я уявляю собі довгий список файлів у дірі. Я не впевнений, який вміст кожного з файлів. якщо я міг би F5 переглянути, відпустіть F5, щоб зупинити перегляд і повернутися назад, потім перейдіть до наступного кандидата і т.д. натисніть кнопку F5 знову, щоб зупинити перегляд.
Ерік Браун

те, що ви пропонуєте, порівнянне з функціональністю в Midnight Commander (F3)
Ерік Браун

1
Відповідь, яку подав @Sigma, цікава. Але під час перегляду каталогів з використанням знаку "dired" ви вже можете натиснути v, щоб переглянути файл, а під час перегляду цього файлу натисніть q, щоб вийти з нього та повернутися до каталогу. Я думаю, натиснути ту саму клавішу для перегляду та виходу з програми простіше.
Nsukami _

@LeMeteore дякую, що нагадали про мене dired-view-file! Я відредагував свій код, щоб використовувати його. Так, я думаю, що в такому сценарії важливо не переходити до іншого ключа.
Sigma

4

Замість показу файлу під час натискання клавіші, що було б дуже важко реалізувати, я пропоную показувати файл до наступної клавіші.

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

Ось варіант, який показує файл в іншому вікні, що, на мою думку, є більш зручним інтерфейсом користувача.

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

Ви не зможете зробити так багато, як прокрутка в буфері. Можливо, буде більше сенсу реалізувати режим «швидкого перегляду», коли команди прокрутки приймаються, але інші події введення призводять до виходу режиму швидкого перегляду та інтерпретації відповідно до попереднього режиму, як Isearch.

За допомогою v( dired-view-file) ви отримуєте щось проміжне: буфер редагується в режимі перегляду , де ви можете прокручувати, шукати тощо, але закриття буфера - це простий набір клавіш q.


2

Іншою можливістю, якщо ви користуєтеся мишею, є розміщення потрібного попереднього перегляду в підказці . Потім, коли ви перемістите курсор миші на ім’я файлу (із властивістю help-echo), попередній перегляд з’явиться.

Я використовую цю техніку в Dired + , наприклад, для (необов'язково) показу попереднього перегляду зображень, пов’язаних із файлами зображень, коли ви перебираєте назви файлів мишею.

Ви можете побачити ефект цього, зробивши це після завантаження dired+.el:

  • Переконайтеся , що tooltip-modeвключений: (tooltip-mode 1).

  • Переконайтесь, що параметр diredp-image-preview-in-tooltipмає нецілене nilзначення (або розмір ескізів, або зображення fullв повному розмірі).

  • Помістіть покажчик миші на ім’я файлу зображення у Dired.

Ви можете використовувати функціональний код diredp-mouseover-helpяк натхнення для того, щоб робити те, що ви хочете (відображайте свій "швидкий перегляд" на миші). Див. Виклики цієї функції, як їх використовувати. Ось один такий дзвінок:

 (add-text-properties (line-beginning-position) (line-end-position)
                      '(mouse-face highlight help-echo diredp-mouseover-help))

Ви втратили мене на "якщо ви користуєтеся мишкою". ;-) Це не працює для мене. image-diredпрацює чудово, але все, що я бачу, коли наводить курсор мишіmouse-1: visit this file/dir in another window
nispio

Ви не побачите, що я сказав, якщо ви не завантажуєтесь dired+.elі не будете виконувати інші вказівки, які я дав. Це не особливість ванільного Emacs. Я намагався описати, як можна прокручувати власний код, щоб робити те, що ти хочеш. Thedired+.elКод дуже близько, я думаю, що ви говорите , що ви хочете. Але так, підказки щодо перегляду миші вимагають використання миші. Якщо цього не зробити, то пропозиція використовувати підказку не дуже допоможе. ;-)
Дрю

Я розумію, як завантажувати пакунки та слідувати вказівкам, але це не працює для мене. Я не впевнений, як відновити цю розмову в чаті, але, можливо, ми повинні це зробити.
nispio


1

З перенаправленого буфера vвідвідає файл у режимі лише для перегляду та qвийде з режиму перегляду та поверне вас до переповненого буфера. Це швидкий спосіб попереднього перегляду файлу, і він дає можливість прокрутки та навіть пошуку буфера.

Я не думаю, що Emacs має можливість передавати будь-які повідомлення низького рівня натискання клавіш, які він отримує від операційної системи. Частково це може бути з історичних причин. Термінали, доступні хакерам (читайте "програмісти") в той час, коли Emacs розроблявся ще в 1970-х - 1980-х роках, не працювали з подіями вгору / вниз в режимі реального часу, а з простого введення символів та послідовностей втечі. На сьогоднішній день emacs все ще може працювати вражаюче в межах простого терміналу або сеансу SSH, використовуючи лише прості символи ASCII та послідовності втечі.

Це не означає, що за останні роки функціональність не зросла, включаючи такі функції, як меню, управління кількома кадрами та взаємодія миші. Немає жодних причин (що я знаю), що emacs не міг бути змінений (у своїй основі), щоб зробити доступними для розширень ключові повідомлення низького рівня, але я б не затримував дихання.

( Відмова від відповідальності: цю посаду слід сприймати як думку та спекуляцію, а не жорсткий факт.)


1

Я дав своє рішення в цьому ТАКОМУ питанні /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- буфер

і моя відповідь - змінити поведінку навігаційних клавіш nі pпоказати файл у точці в іншому вікні. Фокус залишається у введеному буфері, і ми вбиваємо відвідуваний буфер під час перегляду.

Я створив мінорний режим, щоб легко ввімкнути / вимкнути цю функцію. Зауважте, що у нас ще є клавіші зі стрілками для «нормальної» навігації. Виклик M-x dired-show-mode(або ranger-modeоскільки це функція, яку я виявив у менеджері файлів рейнджера ).

Код: (будь-який звіт про огляд та помилку оцінено!) 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

0

Вам потрібно буде опитувати чергу подій, поки не буде прочитана інша подія, або її немає. Навантаження процесора помітна, хоча і досить низька.

(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)))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.