Mengarahkan "tampilan cepat" kunci untuk melihat pratinjau file pada titik

19

Saya ingin membuat fungsi yang melakukan "tampilan cepat" dari file yang di bawah titik dired.

Cara yang saya ingin agar ini berfungsi adalah bahwa saya menahan tombol fungsi, yang kemudian membuat file terlihat dalam buffer, tetapi ketika saya melepaskan kunci, buffer menutup dan buffer dired kembali. Saya tidak mau harus menutup buffer sementara C-x k .

Apakah ada cara untuk membuat fungsi ini di Emacs? Tampaknya mungkin jika saya dapat mengikat fungsi keypress / depress.

Eric Brown
sumber
1
Anda tidak dapat mengikat untuk menekan acara yang tertekan, tetapi fungsi ini pasti dapat diretas dengan menggunakan peta khusus, dan timer.
Jordon Biondo
Apakah Anda berbicara tentang jendela baru yang muncul dengan pratinjau? Atau apakah isi buffer ditampilkan di jendela dired ketika kunci ditekan?
nispio
1
Apakah ada upaya untuk memungkinkan kami mengikat acara? Saya ingin fitur ini.
wdkrnls

Jawaban:

9

Ini adalah cara saya yang super hacky untuk mensimulasikan pengikatan kunci acara turun / naik dengan memanfaatkan timer.

Secara keseluruhan saya akan menyarankan pergi dengan jawaban Sigma, tetapi Anda meminta cara untuk menutup pratinjau dengan melepaskan jadi saya wajib mencoba.

Pada dasarnya apa yang dapat Anda lakukan adalah mengikat beberapa fungsi yang akan menjadi fungsi "keydown" Anda ke pengikat tombol dan di dalam tindakan itu, mulailah penghitung waktu idle yang menjalankan fungsi yang merupakan fungsi "keyup" Anda, selama Anda menekan tombol diberikan kunci, fungsi "keydown" akan menyala berulang dan ini akan menghambat timer idle dari berjalan. Tentu saja Anda perlu mengimbangi kenyataan bahwa perintah akan menyala berulang-ulang, kemungkinan dengan memutar kembali kunci ke semacam fungsi noop di fungsi "keydown" Anda, kemudian memutarkan fungsi "keydown" di fungsi "keyup".

Jadi untuk kasus penggunaan Anda, fungsi "keydown" Anda akan membuka buffer pratinjau dengan isi file pada titik dan dalam buffer pratinjau mengikat kombo kunci yang sama ke beberapa perintah seperti noop. Fungsi "keydown" Anda juga akan memulai penghitung waktu idle yang akan menghapus buffer pratinjau Anda dan mengembalikan Anda ke tempat semula.

Singkat cerita di sini adalah kode:

Bind fungsi ini ke kombo kunci (saya menggunakan C-M-v), ketika Anda menekannya di atas nama file itu akan membuka buffer baru menampilkan isi file pada titik, ketika Anda melepaskan Anda akan beralih kembali ke aslinya penyangga.

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

Juga di sini adalah gif dari itu dalam aksi, semua yang saya lakukan adalah:

  • letakkan kursor saya di atas file
  • tekan dan tahan tombolbinding saya
  • pratinjau ditampilkan
  • ketika saya melepaskan, pratinjau terbunuh dan Anda kembali ke tempat semula.

masukkan deskripsi gambar di sini

Satu hal penting yang perlu diperhatikan adalah detik pengatur waktu idle, dalam kode saya yang saya gunakan .7tetapi ini semacam angka ajaib, Anda ingin tetap sangat kecil, tetapi jika Anda melihat pratinjau berkedip dua kali coba naikkan 1/10 per detik setiap kali sampai Anda menemukan tempat yang tepat untuk mesin Anda.

* Juga perhatikan bahwa dalam fungsi saya mencoba untuk melakukan beberapa fontifikasi dari pratinjau buffer tetapi saya tidak dapat membuatnya berfungsi, itu akan menjadi langkah selanjutnya untuk membuatnya lebih berguna. **

Jordon Biondo
sumber
Bagus! Ini adalah hal yang perlu kita lihat di sini.
Malabarba
Saya mendapatkan Error running timer: (void-variable buffer)dengan ini, sepertinya buffervar tidak tersedia di dalam run-with-idle-timer?
Lee H
Pastikan leksikal-mengikat adalah t
Jordon Biondo
Anda mungkin ingin mengulangi jawaban ini di sana .
Malabarba
8

Seperti yang ditunjukkan dalam komentar, fungsi terikat pada kunci, bukan acara. Tetapi untuk mengambil langkah mundur, saya tidak yakin saya mengerti mengapa penting bagi Anda untuk menyimpan kunci saat Anda (mungkin) membaca konten file. Ini juga tidak sesuai dengan tindakan dasar (dan masuk akal) seperti menggulir untuk mendapatkan lebih banyak. Belum lagi fakta bahwa jika perlu waktu, itu mungkin menjadi tidak nyaman :)

Bagaimana dengan mengulangi kunci saja? Sesuatu seperti yang berikut ini bisa menjadi kerangka dasar dari persamaan fungsional:

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

Ngomong-ngomong, saya lebih menantang kasus penggunaan Anda daripada menjawab pertanyaan Anda pada saat ini, karena ini tidak ada hubungannya dengan ikatan tombol yang menekan / menekan :)

Sigma
sumber
Saya membayangkan daftar panjang file dalam dired. Saya tidak yakin apa isinya dari masing-masing file. jika saya bisa melihat F5, matikan F5 untuk berhenti melihat dan kembali dired, kemudian lanjutkan ke kandidat berikutnya, dll. Saya tidak berpikir Anda telah membantah kasus penggunaan saya, tetapi Anda mungkin telah menyarankan alternatif yang baik berdasarkan pada menekan F5 lagi untuk berhenti melihat.
Eric Brown
apa yang Anda sarankan sebanding dengan fungsi di Midnight Commander (F3)
Eric Brown
1
Jawaban yang dikirimkan oleh @Sigma menarik. Tetapi saat menelusuri direktori menggunakan dired, Anda sudah dapat menekan v untuk melihat file, dan saat melihat file itu, tekan q untuk keluar dan kembali ke direktori. Saya kira, menekan tombol yang sama untuk melihat dan berhenti lebih mudah.
Nsukami _
@LeMeteore terima kasih telah mengingatkan saya pada dired-view-file! Saya telah mengedit kode saya untuk meningkatkannya. Ya, saya kira dalam skenario seperti ini, tidak harus pindah ke kunci yang berbeda itu penting.
Sigma
4

Alih-alih menunjukkan file saat tombol ditekan, yang akan sangat sulit untuk diterapkan, saya sarankan menunjukkan file sampai tombol berikutnya ditekan.

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

Berikut adalah varian yang menunjukkan file di jendela lain, yang saya pikir merupakan antarmuka pengguna yang lebih nyaman.

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

Anda tidak akan dapat melakukan sebanyak gulir di buffer. Mungkin lebih masuk akal untuk menerapkan mode "tampilan cepat" di mana perintah gulir diterima, tetapi peristiwa input lainnya menyebabkan mode tampilan cepat keluar dan ditafsirkan menurut mode sebelumnya, seperti Isearch.

Dengan v( dired-view-file), Anda mendapatkan sesuatu yang sedang: buffer diedit dalam mode View , di mana Anda dapat menggulir, mencari, dll. Tetapi menutup buffer adalah keystroke sederhana q.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Kemungkinan lain, jika Anda menggunakan mouse, adalah untuk menempatkan pratinjau yang Anda inginkan di tooltip . Kemudian, ketika Anda memindahkan mouse di atas nama file (dengan properti help-echo) pratinjau akan muncul.

Saya menggunakan teknik ini di Dired + , misalnya, untuk (opsional) menampilkan pratinjau gambar yang terkait dengan file gambar, ketika Anda mengarahkan mouse ke nama file.

Anda dapat melihat efeknya dengan melakukan ini setelah memuat dired+.el:

  • Pastikan tooltip-modedihidupkan: (tooltip-mode 1).

  • Pastikan opsi diredp-image-preview-in-tooltiptersebut tidak nilbernilai (baik ukuran thumbnail atau fulluntuk gambar ukuran penuh).

  • Tempatkan pointer mouse di atas nama file gambar di Dired.

Anda dapat menggunakan kode fungsi diredp-mouseover-helpsebagai inspirasi untuk melakukan apa yang Anda inginkan (tampilkan "tampilan cepat" pada mouseover). Lihat panggilan fungsi itu untuk cara menggunakannya. Inilah satu panggilan seperti itu:

 (add-text-properties (line-beginning-position) (line-end-position)
                      '(mouse-face highlight help-echo diredp-mouseover-help))
Drew
sumber
Anda kehilangan saya di "jika Anda menggunakan mouse." ;-) Ini tidak bekerja untuk saya. image-diredberfungsi dengan baik, tetapi yang saya lihat ketika saya mengarahkan mouse adalahmouse-1: visit this file/dir in another window
nispio
Anda tidak akan melihat apa yang saya katakan jika Anda tidak memuat dired+.eldan mengikuti petunjuk lain yang saya berikan. Ini bukan fitur vanilla Emacs. Saya mencoba menjelaskan bagaimana Anda bisa menggulirkan kode Anda sendiri untuk melakukan apa yang Anda inginkan. Menurut saya, dired+.elkodenya sangat dekat dengan apa yang Anda inginkan. Tapi ya, tooltip mouseover mengharuskan Anda menggunakan mouse. Jika tidak, maka saran untuk menggunakan tooltip tidak akan banyak membantu. ;-)
Drew
Saya mengerti cara memuat paket dan mengikuti petunjuk, tetapi itu tidak berfungsi untuk saya. Saya tidak yakin bagaimana melanjutkan percakapan ini dalam obrolan, tetapi mungkin kita harus melakukannya.
nispio
1

Dari buffer dired, vakan mengunjungi file dalam mode view-only, dan qakan keluar dari mode tampilan dan membawa Anda kembali ke buffer dired. Ini adalah cara cepat untuk melihat pratinjau file, dan memberikan kemungkinan untuk menggulir dan bahkan mencari buffer.

Saya tidak berpikir bahwa emacs memiliki kemampuan untuk meneruskan pesan penekanan tombol tingkat rendah yang diterimanya dari sistem operasi. Ini mungkin sebagian karena alasan historis. Terminal yang tersedia untuk peretas (baca "programmer") pada waktu itu emacs sedang dikembangkan kembali pada tahun 1970-an-1980-an tidak bekerja dengan peristiwa kunci naik / turun waktu nyata, melainkan input karakter sederhana dan urutan pelarian. Hingga hari ini emacs masih dapat beroperasi secara mengesankan dalam batas-batas terminal sederhana atau sesi SSH hanya menggunakan karakter ASCII sederhana dan lolos dari urutan.

Itu tidak berarti bahwa fungsionalitas tidak tumbuh secara signifikan selama bertahun-tahun untuk memasukkan fitur-fitur seperti menu, manajemen multi-bingkai, dan interaksi mouse. Tidak ada alasan (bahwa saya sadar) bahwa emacs tidak dapat diubah (pada intinya) untuk membuat pesan kunci tingkat rendah tersedia untuk ekstensi, tetapi saya tidak akan menahan nafas.

( Penafian: Posting ini harus dianggap sebagai opini dan spekulasi, bukan fakta yang sulit.)

nispio
sumber
1

Saya memberikan solusi saya dalam pertanyaan SO ini /programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is-in- penyangga

dan jawaban saya adalah mengubah perilaku tombol navigasi ndan pmenunjukkan file pada titik di jendela lain. Fokus tetap di buffer dired dan kami membunuh buffer yang dikunjungi saat kami menjelajah.

Saya membuat mode minor untuk mengaktifkan / menonaktifkan fitur ini dengan mudah. Perhatikan bahwa kami masih memiliki tombol panah untuk navigasi «normal». Panggil M-x dired-show-mode(atau ranger-modekarena ini adalah fitur yang saya temukan di manajer file ranger ).

Kode: (setiap ulasan dan laporan bug dihargai!) 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
sumber
0

Anda harus melakukan polling antrian acara hingga acara yang berbeda, atau tidak ada, terbaca. Beban CPU terlihat, meskipun cukup rendah.

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