Opuszczony klawisz „szybkiego podglądu” do podglądu pliku w punkcie


19

Chciałbym stworzyć funkcję, która wykonuje „szybki podgląd” pliku, który jest podważony.

Chciałbym, aby to zadziałało: przytrzymuję klawisz funkcyjny, co powoduje, że plik jest widoczny w buforze, ale kiedy go zwolnię, bufor się zamyka i bufor zwrócony. Nie chcę zamykać bufora tymczasowego za pomocą C-x k .

Czy istnieje sposób na uczynienie tej funkcji w Emacsie? Wydaje się możliwe, że mogę powiązać funkcje z naciśnięciem / naciśnięciem klawisza.


1
Nie możesz powiązać wydarzeń z depresją prasową, ale tę funkcję można zdecydowanie zhakować za pomocą niestandardowej mapy i timera.
Jordon Biondo,

Czy mówisz o nowym oknie wyskakującym z podglądem? A może zawartość bufora będzie wyświetlana w oknie z wybraniem, gdy klawisz jest wciśnięty?
nispio

1
Czy są jakieś wysiłki, aby umożliwić nam powiązanie z wydarzeniami? Chcę tę funkcję.
wdkrnls

Odpowiedzi:


9

Oto mój super hackerski sposób na symulację powiązania zdarzenia kluczowania / opuszczania za pomocą timerów.

Ogólnie sugerowałbym skorzystanie z odpowiedzi Sigmy, ale poprosiłeś o sposób na zamknięcie podglądu przez zwolnienie, więc muszę spróbować.

Zasadniczo to, co możesz zrobić, to powiązać funkcję, która będzie twoją funkcją „keydown”, z klawiszem i wewnątrz tej akcji, uruchom licznik czasu bezczynności, który wykonuje funkcję, która jest twoją funkcją „keyup”, dopóki przytrzymasz klawisz dane klucze, funkcja „keydown” będzie się uruchamiała w kółko, co uniemożliwi działanie liczników czasu bezczynności. Oczywiście musisz zrekompensować fakt, że polecenie będzie się uruchamiało w kółko, prawdopodobnie przez ponowne przypisanie klawisza do jakiejś funkcji noop w funkcji „keydown”, a następnie ponowne przypisanie funkcji „keydown” w funkcji „keyup”.

Tak więc w twoim przypadku funkcja „keydown” otworzy bufor podglądu z zawartością pliku w punkcie iw tym buforze podglądu wiąże tę samą kombinację klawiszy z jakimś poleceniem noop. Funkcja „keydown” uruchomi również czas bezczynności, który usunie bufor podglądu i przywróci Cię z powrotem tam, gdzie byłeś.

Krótka historia tutaj to kod:

Powiązanie tej funkcji z kombinacją klawiszy (użyłem C-M-v), kiedy naciśniesz ją nad nazwą pliku, otworzy się nowy bufor wyświetlający zawartość pliku w punkcie, kiedy puścisz, nastąpi powrót do pierwotnego bufor.

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

Również tutaj jest gif w akcji, wszystko co robię to:

  • umieść kursor nad plikiem
  • naciśnij i przytrzymaj moje skrót klawiszowy
  • podgląd jest wyświetlany
  • kiedy puszczam, podgląd zostaje zabity, a ty wracasz tam, gdzie byłeś.

wprowadź opis zdjęcia tutaj

Jedną ważną rzeczą, na którą należy zwrócić uwagę, są sekundy bezczynnika, w moim kodzie użyłem, .7ale to rodzaj magicznej liczby, chcesz zachować ją naprawdę małą, ale jeśli widzisz, że podgląd miga dwa razy, spróbuj za każdym razem zwiększać go o 1/10 sekundy aż znajdziesz odpowiednie miejsce dla swojej maszyny.

* Zauważ też, że w funkcji staram się trochę czcionkizować bufor podglądu, ale nie udało mi się go uruchomić, to będzie następny krok, aby uczynić go bardziej użytecznym. **


Ładny! To jest coś, co musimy zobaczyć tutaj.
Malabarba

Rozumiem Error running timer: (void-variable buffer), wygląda na to, że buffervar nie jest dostępny w run-with-idle-timer?
Lee H

Upewnij się, że wiązanie leksykalne jest t
Jordon Biondo

Możesz powtórzyć tę odpowiedź tam .
Malabarba

8

Jak wskazano w komentarzach, funkcje są powiązane z kluczami, a nie ze zdarzeniami. Ale aby cofnąć się o krok, nie jestem pewien, czy rozumiem, dlaczego ważne jest, aby trzymać wciśnięty klawisz podczas (prawdopodobnie) czytania zawartości pliku. Byłoby to również niezgodne z podstawowymi (i rozsądnymi) działaniami, takimi jak przewijanie, aby uzyskać więcej. Nie wspominając już o tym, że jeśli to potrwa chwilę, może stać się niewygodne :)

Co powiesz na powtórzenie klucza zamiast tego? Coś takiego może być podstawowym szkieletem funkcjonalnego odpowiednika:

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

W każdym razie bardziej podważam twój przypadek użycia niż odpowiadanie na twoje pytanie, ponieważ nie ma to nic wspólnego z powiązaniami klawiszy / naciśnięć :)


Wyobrażam sobie długą listę plików w dired. Nie jestem pewien, jaka jest zawartość każdego z plików. jeśli mógłbym F5 do oglądania, pozwól F5 przestać oglądać i wrócić do szaleństwa, a następnie przejdź do następnego kandydata itp. Nie sądzę, żebyś odrzucił mój przypadek użycia, ale mógłbyś zasugerować dobrą alternatywę po ponownym naciśnięciu F5, aby zatrzymać przeglądanie.
Eric Brown

to, co sugerujesz, jest porównywalne z funkcjonalnością w Midnight Commander (F3)
Eric Brown,

1
Odpowiedź przesłana przez @Sigma jest interesująca. Ale podczas przeglądania katalogu przy użyciu dired można już nacisnąć v, aby wyświetlić plik, a podczas przeglądania tego pliku naciśnij q, aby wyjść i wrócić do katalogu. Chyba naciśnięcie tego samego klawisza do przeglądania i wychodzenia jest łatwiejsze.
Nsukami _

@LeMeteore dzięki za przypomnienie mi dired-view-file! Zmodyfikowałem swój kod, aby go wykorzystać. Tak, myślę, że w tego rodzaju scenariuszu nie jest konieczne przejście do innego klucza.
Sigma,

4

Zamiast pokazywać plik podczas naciskania klawisza, co byłoby bardzo trudne do wdrożenia, sugeruję pokazywanie pliku aż do naciśnięcia następnego klawisza.

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

Oto wariant, który pokazuje plik w innym oknie, co moim zdaniem jest wygodniejszym interfejsem użytkownika.

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

Nie będziesz w stanie zrobić tyle, co przewijanie w buforze. Bardziej sensowne może być wdrożenie trybu „szybkiego podglądu”, w którym akceptowane są polecenia przewijania, ale inne zdarzenia wejściowe powodują zakończenie trybu szybkiego podglądu i są interpretowane zgodnie z poprzednim trybem, takim jak Isearch.

Za pomocą v( dired-view-file) otrzymujesz coś pośredniego: bufor jest edytowany w trybie przeglądania , w którym możesz przewijać, wyszukiwać itp., Ale zamknięcie bufora jest prostym naciśnięciem klawisza q.


2

Inną możliwością, jeśli używasz myszy, jest umieszczenie podglądu w podpowiedzi . Następnie, gdy najedziesz myszką na nazwę pliku (z właściwością help-echo), pojawi się podgląd.

Używam tej techniki w Dired + , na przykład, aby (opcjonalnie) wyświetlać podgląd obrazów związanych z plikami obrazów, gdy najedziesz myszką na nazwy plików.

Możesz zobaczyć efekt tego, robiąc to po załadowaniu dired+.el:

  • Upewnić się, że tooltip-modejest włączony: (tooltip-mode 1).

  • Upewnij się, że opcja diredp-image-preview-in-tooltipma inną nilwartość (rozmiar miniatury lub fullobraz w pełnym rozmiarze).

  • Umieść wskaźnik myszy nad nazwą pliku obrazu w Dired.

Możesz użyć kodu funkcji diredp-mouseover-helpjako inspiracji do robienia tego, co chcesz (wyświetl swój „szybki podgląd” po najechaniu myszką). Zobacz wywołania tej funkcji, aby dowiedzieć się, jak z niej korzystać. Oto jedno takie połączenie:

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

Straciłeś mnie na „jeśli używasz myszy”. ;-) To nie działa dla mnie. image-direddziała dobrze, ale wszystko, co widzę po najechaniu myszą tomouse-1: visit this file/dir in another window
nispio,

Nie zobaczysz tego, co powiedziałem, jeśli nie załadujesz dired+.eli nie wykonasz innych instrukcji, które podałem. To nie jest waniliowa funkcja Emacsa. Próbowałem opisać, jak możesz zrobić własny kod, aby zrobić to, co chcesz. dired+.elKod jest bardzo blisko, jak sądzę, do tego, co chcesz powiedzieć. Ale tak, podpowiedzi najechania myszką wymagają użycia myszy. Jeśli tego nie zrobisz, sugestia użycia podpowiedzi niewiele pomoże. ;-)
Drew

Rozumiem, jak ładować paczki i postępować zgodnie ze wskazówkami, ale to nie działa dla mnie. Nie jestem pewien, jak wznowić tę rozmowę na czacie, ale być może powinniśmy to zrobić.
nispio


1

Z bufora dired vodwiedzi plik w trybie tylko do przeglądania, qwyjdzie z trybu przeglądania i zabierze Cię z powrotem do bufora dired. Jest to szybki sposób na wyświetlenie podglądu pliku i daje możliwość przewijania, a nawet przeszukiwania bufora.

Nie sądzę, aby emacs mógł przekazywać wiadomości o niskim naciśnięciu klawisza otrzymywane z systemu operacyjnego. Może to częściowo wynikać z przyczyn historycznych. Terminale dostępne dla hakerów (czytaj „programiści”) w czasie, gdy emacs był rozwijany w latach 70. i 80. XX wieku, nie działały ze zdarzeniami kluczowymi w górę / w dół w czasie rzeczywistym, ale raczej prostym wprowadzaniem znaków i sekwencji ucieczki. Do dziś emacs może nadal imponująco dobrze działać w ramach prostej sesji terminalu lub SSH, używając tylko prostych znaków ASCII i sekwencji ucieczki.

Nie oznacza to, że funkcjonalność nie rozwinęła się znacząco na przestrzeni lat, obejmując takie funkcje, jak menu, zarządzanie wieloma ramkami i interakcja myszy. Nie ma powodu (jestem tego świadomy), że emacs nie mógł zostać zmieniony (w jego rdzeniu), aby udostępnić kluczowe wiadomości niskiego poziomu dla rozszerzeń, ale nie wstrzymałbym cię.

( Uwaga: ten post powinien być traktowany jako opinia i spekulacja, a nie fakt).


1

Dałem moje rozwiązanie w tym SO pytaniu /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- bufor

a moją odpowiedzią jest zmiana zachowania klawiszy nawigacyjnych ni ppokazanie pliku w punkcie w innym oknie. Fokus pozostaje w opróżnionym buforze i zabijamy odwiedzany bufor podczas przeglądania.

Utworzyłem tryb pomocniczy, aby łatwo włączyć / wyłączyć tę funkcję. Pamiętaj, że nadal mamy klawisze strzałek do nawigacji „normalnej”. Zadzwoń M-x dired-show-mode(lub ranger-modeponieważ jest to funkcja, którą odkryłem w menedżerze plików ranger ).

Kod: (doceniamy każdą recenzję i zgłoszenie błędu!) 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

Trzeba będzie sondować kolejkę zdarzeń, dopóki inne zdarzenie lub żadne nie zostanie odczytane. Obciążenie procesora jest zauważalne, choć stosunkowo niskie.

(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)))
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.