dired-read-file-name: pop-up dired mode to read-fi

2019-03-01 06:28发布

问题:

Could anyone please give me a hand to briefly pop-up a dired buffer for the purposes of read-file-name:

(defun dired-insert-file ()
  (interactive)
  (setq filename (dired-read-file-name "~/Desktop"))
  (kill-buffer dired)
  (get-buffer-create "*foo*")
  (set-buffer "*foo*")
  (insert-file filename))

EDIT: Revised example:

(require 'dired)

(defvar open-with-variable nil)
(defvar save-as-variable nil)
(defvar save-as-buffer-filename nil)

(defun dired-read-file-name (&optional directory)
  (let* (
      output-filename
      (working-buffer (buffer-name)))
    (if directory
      (dired directory)
    (dired nil))
    (if save-as-buffer-filename
      (progn
        (goto-char (point-min))
        (re-search-forward (file-name-nondirectory save-as-buffer-filename) nil t)))
    (recursive-edit)
    (switch-to-buffer working-buffer)
    output-filename))

(defun dired-insert-file ()
(interactive)
  (let* (
    (save-as-variable t)
    (lawlist-filename (dired-read-file-name)))
    (insert-file-contents lawlist-filename)))

;; Open with external application.
(define-key dired-mode-map (kbd "C-c o") (lambda () (interactive)
  (let* (
      (open-with-variable t)
      (lawlist-filename (dired-get-file-for-visit))
      (application (dired-read-file-name "/Applications")))
  (start-process "external-application" nil "open" "-a" application lawlist-filename))))

(defun lawlist-save-as ()
(interactive)
  (let* (
      save-as-filename
      (save-as-variable t)
      (save-as-buffer-filename (if (buffer-file-name) (buffer-file-name)))
      (proposed-filename (dired-read-file-name)))
    (when proposed-filename ;; needed if aborting recursive-edit
      (setq save-as-filename (read-string "Save-As:  "
        (if (file-directory-p proposed-filename)
          (concat proposed-filename (buffer-name))
          proposed-filename)))
      (when (and save-as-filename (file-exists-p save-as-filename))
        (or (y-or-n-p (format "File `%s' exists; overwrite? " save-as-filename))
          (error "Canceled")))
      (set-visited-file-name save-as-filename)
      (set-buffer-modified-p t)
      (and (buffer-file-name)
           (file-writable-p buffer-file-name)
           (setq buffer-read-only nil))
      (save-buffer))))

;; delete the buffer after selecting file | application | directory
(define-key dired-mode-map (kbd "<return>") (lambda () (interactive)
  (select-file-application-directory t)))

;; do not delete the buffer after selecting file | application | directory
(define-key dired-mode-map (kbd "<C-M-s-return>") (lambda () (interactive)
  (select-file-application-directory nil)))

;; select file | application | directory
(defun select-file-application-directory (&optional delete-buffer)
  (let* (
    (fn-list (dired-get-marked-files))
    (rfn-list (mapcar (function dired-make-relative) fn-list))
    (dired-one-file (and (consp fn-list) (null (cdr fn-list)) (car fn-list)))
    (input-filename (if dired-one-file dired-one-file fn-list))
    (ext
      (cond
        ((stringp input-filename)
          (file-name-extension input-filename))
        ((listp input-filename)
          (file-name-extension (car input-filename)))))
    (path (if (stringp input-filename) (file-name-directory input-filename)))
    (dired-buffer-name (buffer-name))
    (msword "/Applications/Microsoft Office 2011/Microsoft Word.app/Contents/MacOS/Microsoft Word")
    (ooo "/Applications/OpenOffice.org.app")
    (excel "/Applications/Microsoft Office 2011/Microsoft Excel.app/Contents/MacOS/Microsoft Excel")
    (adobe "/Applications/Adobe Acrobat 9 Pro/Adobe Acrobat Pro.app/Contents/MacOS/AdobeAcrobat")
    (preview "/Applications/Preview.app/Contents/MacOS/Preview")
    (skim "/Applications/Skim.app/Contents/MacOS/Skim")
    (input-regexp '("odt" "wpd" "docx" "doc" "xls" "pdf" "tif" "bmp" "jpg"))
    (pdf-regexp '("pdf" "tif" "bmp" "jpg"))
    (ooo-regexp '("odt" "wpd"))
    (msword-regexp '("doc" "docx")))
  (cond
    ;; only use current path a save-as situation.
    ((and
        (equal input-filename (concat path "."))
        save-as-variable)
      (setq output-filename (expand-file-name default-directory))
      (if delete-buffer (kill-buffer dired-buffer-name))
      (throw 'exit nil))
    ;; save-as (stringp) | dired-insert-file
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        save-as-variable)
      (setq output-filename input-filename)
      (if delete-buffer (kill-buffer dired-buffer-name))
      (throw 'exit nil))
    ;; open just one file, except input-regexp
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not save-as-variable)
        (not (regexp-match-p input-regexp ext)))
      (if delete-buffer (kill-buffer dired-buffer-name))
      (find-file input-filename))
    ;; open numerous files, except input-regexp
    ((and
        (listp input-filename)
        (not (regexp-match-p input-regexp ext)))
      (if delete-buffer (kill-buffer dired-buffer-name))
      (mapc 'find-file input-filename))
    ;; open OpenOfficeOrg
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not save-as-variable)
        (regexp-match-p ooo-regexp ext))
      (start-process "ooo-view" nil "open" "-a" ooo input-filename)
      (if delete-buffer (kill-buffer dired-buffer-name)))
    ;; open msword
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not save-as-variable)
        (regexp-match-p msword-regexp ext))
      (start-process "msword-view" nil "open" "-a" msword input-filename)
      (if delete-buffer (kill-buffer dired-buffer-name)))
    ;; open excel
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not save-as-variable)
        (equal ext "xls"))
      (start-process "excel-view" nil "open" "-a" excel input-filename)
      (if delete-buffer (kill-buffer dired-buffer-name)))
    ;; *.pdf -- open just one *.pdf file.
    ((and
        (stringp input-filename)
        (not (file-directory-p input-filename))
        (file-exists-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not save-as-variable)
        (regexp-match-p pdf-regexp ext))
      (lawlist-message "[a]dobe | [p]review | [s]kim")
      (let* ((select-pdf-viewer (read-char-exclusive)))
        (cond
          ((eq select-pdf-viewer ?a)
            (start-process "pdf-with-adobe" nil "open" "-a" adobe input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          ((eq select-pdf-viewer ?p)
            (start-process "pdf-with-preview" nil "open" "-a" preview input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          ((eq select-pdf-viewer ?s)
            (start-process "pdf-with-adobe" nil "open" "-a" skim input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          (t (message "You have exited the sub-function.")) )) )
    ;; *.pdf -- open more than just one *.pdf file.
    ((and
        (listp input-filename)
        (not save-as-variable)
        (regexp-match-p pdf-regexp ext))
      (lawlist-message "[a]dobe | [p]review | [s]kim")
      (let* ((select-pdf-viewer (read-char-exclusive)))
        (cond
          ((eq select-pdf-viewer ?a)
            (mapcar (lambda (x)
              (start-process "pdf-with-adobe" nil "open" "-a" adobe x) )
                input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          ((eq select-pdf-viewer ?p)
            (mapcar (lambda (x)
              (start-process "pdf-with-preview" nil "open" "-a" preview x) )
                input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          ((eq select-pdf-viewer ?s)
            (mapcar (lambda (x)
              (start-process "pdf-with-adobe" nil "open" "-a" skim x) )
                input-filename)
            (if delete-buffer (kill-buffer dired-buffer-name)))
          (t (message "You have exited the sub-function.")) )) )
    ;; open with external application, because the `open-with-variable` is t.
    ((and
        open-with-variable
        (equal ext "app"))
      (setq output-filename input-filename)
      (if delete-buffer (kill-buffer dired-buffer-name))
      (throw 'exit nil))
    ;; Enter the directory; or, open an application
    ((and
        (file-directory-p input-filename)
        (not (equal input-filename (concat path ".")))
        (not open-with-variable))
      (if (equal ext "app")
        (progn
          (message "[d]eeper | [o]pen")
          (let* ((deeper-open (read-char-exclusive)))
            (cond
              ((eq deeper-open ?d)
                (dired-find-file)
                (goto-char (point-min))
                (re-search-forward " \\.\\.$" nil t)
                (if delete-buffer (kill-buffer dired-buffer-name)))
              ((eq deeper-open ?o)
                (start-process "application" nil "open" "-a" input-filename)
                (if delete-buffer (kill-buffer dired-buffer-name)))
              (t (message "You have exited the sub-function.")) )) )
        (dired-find-file)
        (goto-char (point-min))
        (re-search-forward " \\.\\.$" nil t)
        (if delete-buffer (kill-buffer dired-buffer-name)))) )))

;; https://github.com/kentaro/auto-save-buffers-enhanced
;; `regexp-match-p` function modified by @sds on stackoverflow
;; http://stackoverflow.com/questions/20343048/distinguishing-files-with-extensions-from-hidden-files-and-no-extensions
(defun regexp-match-p (regexps string)
  (and string
       (catch 'matched
         (let ((inhibit-changing-match-data t)) ; small optimization
           (dolist (regexp regexps)
             (when (string-match regexp string)
               (throw 'matched t)))))))

(defun lawlist-message (input)
(interactive)
  (message
    (propertize input 'face 'font-lock-warning-face)))

回答1:

You'll want to look into recursive-edit: pop up a dired buffer in which you add a way to exit (which works by performing a (throw 'exit <value>)), and then call (recursive-edit) which will return the <value> passed to throw.