ปุ่ม "Quick-view" Dired เพื่อแสดงตัวอย่างไฟล์ที่จุด


19

ฉันต้องการสร้างฟังก์ชั่นที่ทำ "มุมมองด่วน" ของไฟล์ที่อยู่ภายใต้จุดใน dired

วิธีที่ฉันต้องการให้มันทำงานคือฉันกดปุ่มฟังก์ชั่นค้างไว้ซึ่งทำให้ไฟล์นั้นปรากฏในบัฟเฟอร์ แต่เมื่อฉันปล่อยกุญแจออกบัฟเฟอร์จะปิดและบัฟเฟอร์ที่ส่งคืน ฉันไม่ต้องการให้มีการปิดบัฟเฟอร์ชั่วคราว C-x k

มีวิธีที่จะทำให้ฟังก์ชั่นนี้ใน Emacs หรือไม่? ดูเหมือนว่าเป็นไปได้ถ้าฉันสามารถผูกฟังก์ชั่นเพื่อกดปุ่ม / กด


1
คุณไม่สามารถผูกกดเหตุการณ์กดดัน แต่ฟังก์ชั่นนี้สามารถถูกแฮ็กด้วยการใช้แผนที่ที่กำหนดเองและตัวจับเวลา
Jordon Biondo

คุณกำลังพูดถึงหน้าต่างใหม่โผล่ขึ้นมาพร้อมกับตัวอย่าง? หรือเนื้อหาของบัฟเฟอร์จะแสดงในหน้าต่าง dired ในขณะที่คีย์ถูกกด?
nispio

1
มีความพยายามที่จะทำให้เราผูกพันกับเหตุการณ์หรือไม่? ฉันต้องการคุณสมบัตินี้
wdkrnls

คำตอบ:


9

ต่อไปนี้เป็นวิธีแฮ็กสุดของฉันในการจำลองเหตุการณ์สำคัญขึ้น / ลงโดยใช้ประโยชน์จากตัวจับเวลา

โดยรวมแล้วฉันอยากจะแนะนำโดยใช้คำตอบของซิกม่า แต่คุณขอวิธีปิดภาพตัวอย่างโดยปล่อยให้ฉันต้องลองดู

โดยทั่วไปสิ่งที่คุณสามารถทำได้คือผูกบางฟังก์ชั่นที่จะเป็น "keydown" ของคุณเข้ากับการทำ keybinding และภายในการกระทำนั้นให้เริ่มจับเวลาว่างที่ทำหน้าที่ของฟังก์ชั่น "keyup" ของคุณตราบใดที่คุณกด คีย์ที่ได้รับฟังก์ชั่น "keydown" จะเริ่มซ้ำแล้วซ้ำอีกและสิ่งนี้จะยับยั้งตัวจับเวลาที่ไม่ทำงาน แน่นอนว่าคุณต้องชดเชยความจริงที่ว่าคำสั่งจะเริ่มซ้ำไปซ้ำมาโดยการกดปุ่มซ้ำเพื่อฟังก์ชั่น noop ในฟังก์ชั่น "keydown" ของคุณจากนั้นเรียกฟังก์ชั่น "keydown" ในฟังก์ชัน "keyup"

ดังนั้นสำหรับกรณีการใช้งานฟังก์ชัน "keydown" ของคุณจะเปิดบัฟเฟอร์ตัวอย่างพร้อมเนื้อหาของไฟล์ที่จุดและในบัฟเฟอร์ตัวอย่างนั้นผูกคำสั่งผสมคีย์เดียวกันกับคำสั่ง noop like บางอย่าง ฟังก์ชัน "keydown" ของคุณจะเริ่มตัวจับเวลาว่างที่จะลบบัฟเฟอร์แสดงตัวอย่างของคุณและเรียกคืนตำแหน่งที่คุณอยู่

เรื่องสั้นที่นี่คือรหัส:

ผูกฟังก์ชั่นนี้กับคำสั่งผสมคีย์ (ฉันใช้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 / 10th ต่อวินาทีในแต่ละครั้ง จนกว่าคุณจะพบจุดที่เหมาะสมสำหรับเครื่องของคุณ

* โปรดทราบว่าในฟังก์ชั่นฉันพยายามที่จะทำให้การแสดงตัวอย่างของบัฟเฟอร์ตัวอย่างบางอย่าง แต่ฉันไม่สามารถใช้งานได้นั่นจะเป็นขั้นตอนต่อไปในการทำให้มีประโยชน์มากขึ้น **


ดี! นี่คือสิ่งที่เราต้องดูที่นี่
Malabarba

ฉันได้รับError running timer: (void-variable buffer)กับสิ่งนี้ดูเหมือนว่าbuffervar ไม่สามารถใช้งานได้ภายในrun-with-idle-timerหรือไม่
Lee H

ตรวจสอบให้แน่ใจศัพท์ผูกพันคือ t
Jordon Biondo

คุณอาจต้องการที่จะทำซ้ำคำตอบนี้มีมากกว่า
Malabarba

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 อีกครั้งเพื่อหยุดดู
Eric Brown เมื่อ

สิ่งที่คุณแนะนำนั้นเปรียบได้กับฟังก์ชั่นการใช้งานใน Midnight Commander (F3)
Eric Brown

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 ฉันพยายามอธิบายวิธีที่คุณสามารถหมุนโค้ดของคุณเพื่อทำสิ่งที่คุณต้องการ dired+.elรหัสอยู่ใกล้มากผมคิดว่าสิ่งที่คุณพูดว่าคุณต้องการ แต่ใช่คำแนะนำเครื่องมือของ mouseover ต้องการให้คุณใช้เมาส์ หากคุณไม่ทำเช่นนั้นคำแนะนำในการใช้คำแนะนำเครื่องมือจะไม่ช่วยอะไรมากนัก ;-)
ดึง

ฉันเข้าใจวิธีโหลดแพ็กเกจและทำตามคำแนะนำ แต่มันไม่ทำงานสำหรับฉัน ฉันไม่แน่ใจว่าจะเริ่มการสนทนานี้ต่อได้อย่างไร แต่บางทีเราควรทำเช่นนั้น
nispio


1

จากบัฟเฟอร์ dired vจะไปที่ไฟล์ในโหมดดูอย่างเดียวและqจะออกจากโหมดดูและนำคุณกลับไปที่บัฟเฟอร์ dired นี่เป็นวิธีที่รวดเร็วในการดูตัวอย่างไฟล์และให้ความเป็นไปได้ในการเลื่อนและแม้แต่การค้นหาบัฟเฟอร์

ฉันไม่คิดว่า emacs สามารถส่งข้อความ keypress ระดับต่ำที่ได้รับจากระบบปฏิบัติการ นี่อาจเป็นส่วนหนึ่งด้วยเหตุผลทางประวัติศาสตร์ เทอร์มินัลที่มีให้กับแฮ็กเกอร์ (อ่าน "โปรแกรมเมอร์") ในเวลาที่ emacs ได้รับการพัฒนาย้อนกลับไปในช่วงทศวรรษ 1970 - 1980 ไม่ได้ทำงานกับเหตุการณ์คีย์ขึ้น / ลงแบบเรียลไทม์ แต่เป็นการป้อนข้อมูลของตัวละคร จนถึงทุกวันนี้ emacs ยังคงสามารถทำงานได้อย่างน่าประทับใจในขอบเขตของเทอร์มินัลธรรมดาหรือเซสชัน SSH โดยใช้เฉพาะอักขระ ASCII แบบง่ายและลำดับการยกเว้น

ไม่ได้กล่าวว่าฟังก์ชั่นนี้ไม่ได้เติบโตขึ้นอย่างมีนัยสำคัญในช่วงหลายปีที่ผ่านมาเพื่อรวมคุณสมบัติต่าง ๆ เช่นเมนูการจัดการหลายเฟรมและการโต้ตอบกับเมาส์ ไม่มีเหตุผล (ที่ฉันรู้) ว่า emacs ไม่สามารถเปลี่ยนแปลงได้ (ที่แกนกลาง) เพื่อทำให้ข้อความหลักระดับต่ำพร้อมใช้งานสำหรับส่วนขยาย แต่ฉันจะไม่กลั้นลมหายใจของคุณ

( ข้อจำกัดความรับผิดชอบ:โพสต์นี้ควรเป็นความคิดเห็นและการเก็งกำไรมากกว่าความเป็นจริงยาก)


1

ฉันให้วิธีการแก้ปัญหาของฉันในคำถามนี้/programming/26409768/how-to-show-buffer-content-in-real-time-in-other-window-when-focus-is/- กันชน

และคำตอบของฉันคือเปลี่ยนพฤติกรรมของปุ่มนำทางnและpแสดงไฟล์ที่จุดในหน้าต่างอื่น โฟกัสยังคงอยู่ในบัฟเฟอร์ที่ dired และเราจะฆ่าบัฟเฟอร์ที่เยี่ยมชมเมื่อเราทำการค้นหาต่อไป

ฉันสร้างโหมดย่อยเพื่อเปิดใช้งาน / ปิดใช้งานคุณลักษณะนี้ได้อย่างง่ายดาย โปรดทราบว่าเรายังคงมีปุ่มลูกศรสำหรับการนำทาง "ปกติ" โทร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)))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.