gnus-dired.el 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. ;;; gnus-dired.el --- utility functions where gnus and dired meet
  2. ;; Copyright (C) 1996-1999, 2001-2012 Free Software Foundation, Inc.
  3. ;; Authors: Benjamin Rutt <brutt@bloomington.in.us>,
  4. ;; Shenghuo Zhu <zsh@cs.rochester.edu>
  5. ;; Keywords: mail, news, extensions
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; This package provides utility functions for intersections of gnus
  19. ;; and dired. To enable the gnus-dired-mode minor mode which will
  20. ;; have the effect of installing keybindings in dired-mode, place the
  21. ;; following in your ~/.gnus:
  22. ;; (require 'gnus-dired) ;, isn't needed due to autoload cookies
  23. ;; (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
  24. ;; Note that if you visit dired buffers before your ~/.gnus file has
  25. ;; been read, those dired buffers won't have the keybindings in
  26. ;; effect. To get around that problem, you may want to add the above
  27. ;; statements to your ~/.emacs instead.
  28. ;;; Code:
  29. (eval-when-compile
  30. (when (featurep 'xemacs)
  31. (require 'easy-mmode))) ; for `define-minor-mode'
  32. (require 'dired)
  33. (autoload 'mml-attach-file "mml")
  34. (autoload 'mm-default-file-encoding "mm-decode");; Shift this to `mailcap.el'?
  35. (autoload 'mailcap-extension-to-mime "mailcap")
  36. (autoload 'mailcap-mime-info "mailcap")
  37. ;; Maybe shift this function to `mailcap.el'?
  38. (autoload 'mm-mailcap-command "mm-decode")
  39. (autoload 'ps-print-preprint "ps-print")
  40. ;; Autoloads to avoid byte-compiler warnings. These are used only if the user
  41. ;; customizes `gnus-dired-mail-mode' to use Message and/or Gnus.
  42. (autoload 'message-buffers "message")
  43. (autoload 'gnus-print-buffer "gnus-sum")
  44. (defvar gnus-dired-mode-map
  45. (let ((map (make-sparse-keymap)))
  46. (define-key map "\C-c\C-m\C-a" 'gnus-dired-attach)
  47. (define-key map "\C-c\C-m\C-l" 'gnus-dired-find-file-mailcap)
  48. (define-key map "\C-c\C-m\C-p" 'gnus-dired-print)
  49. map))
  50. ;; FIXME: Make it customizable, change the default to `mail-user-agent' when
  51. ;; this file is renamed (e.g. to `dired-mime.el').
  52. (defcustom gnus-dired-mail-mode 'gnus-user-agent ;; mail-user-agent
  53. "Your preference for a mail composition package.
  54. See `mail-user-agent' for more information."
  55. :group 'mail ;; dired?
  56. :version "23.1" ;; No Gnus
  57. :type '(radio (function-item :tag "Default Emacs mail"
  58. :format "%t\n"
  59. sendmail-user-agent)
  60. (function-item :tag "Emacs interface to MH"
  61. :format "%t\n"
  62. mh-e-user-agent)
  63. (function-item :tag "Gnus Message package"
  64. :format "%t\n"
  65. message-user-agent)
  66. (function-item :tag "Gnus Message with full Gnus features"
  67. :format "%t\n"
  68. gnus-user-agent)
  69. (function :tag "Other")))
  70. (eval-when-compile
  71. (when (featurep 'xemacs)
  72. (defvar gnus-dired-mode-hook)
  73. (defvar gnus-dired-mode-on-hook)
  74. (defvar gnus-dired-mode-off-hook)))
  75. (define-minor-mode gnus-dired-mode
  76. "Minor mode for intersections of gnus and dired.
  77. \\{gnus-dired-mode-map}"
  78. :keymap gnus-dired-mode-map
  79. (unless (derived-mode-p 'dired-mode)
  80. (setq gnus-dired-mode nil)))
  81. ;;;###autoload
  82. (defun turn-on-gnus-dired-mode ()
  83. "Convenience method to turn on gnus-dired-mode."
  84. (interactive)
  85. (gnus-dired-mode 1))
  86. (defun gnus-dired-mail-buffers ()
  87. "Return a list of active mail composition buffers."
  88. (if (and (memq gnus-dired-mail-mode '(message-user-agent gnus-user-agent))
  89. (require 'message)
  90. (fboundp 'message-buffers))
  91. (message-buffers)
  92. ;; Cf. `message-buffers' in `message.el':
  93. (let (buffers)
  94. (save-excursion
  95. (dolist (buffer (buffer-list t))
  96. (set-buffer buffer)
  97. (when (eq major-mode 'mail-mode)
  98. (push (buffer-name buffer) buffers))))
  99. (nreverse buffers))))
  100. (autoload 'gnus-completing-read "gnus-util")
  101. ;; Method to attach files to a mail composition.
  102. (defun gnus-dired-attach (files-to-attach)
  103. "Attach dired's marked files to a gnus message composition.
  104. If called non-interactively, FILES-TO-ATTACH should be a list of
  105. filenames."
  106. (interactive
  107. (list
  108. (delq nil
  109. (mapcar
  110. ;; don't attach directories
  111. (lambda (f) (if (file-directory-p f) nil f))
  112. (nreverse
  113. (let ((arg nil)) ;; Silence XEmacs 21.5 when compiling.
  114. (dired-map-over-marks (dired-get-filename) arg)))))))
  115. (let ((destination nil)
  116. (files-str nil)
  117. (bufs nil))
  118. ;; warn if user tries to attach without any files marked
  119. (if (null files-to-attach)
  120. (error "No files to attach")
  121. (setq files-str
  122. (mapconcat
  123. (lambda (f) (file-name-nondirectory f))
  124. files-to-attach ", "))
  125. (setq bufs (gnus-dired-mail-buffers))
  126. ;; set up destination mail composition buffer
  127. (if (and bufs
  128. (y-or-n-p "Attach files to existing mail composition buffer? "))
  129. (setq destination
  130. (if (= (length bufs) 1)
  131. (get-buffer (car bufs))
  132. (gnus-completing-read "Attach to which mail composition buffer"
  133. bufs t)))
  134. ;; setup a new mail composition buffer
  135. (let ((mail-user-agent gnus-dired-mail-mode)
  136. ;; A workaround to prevent Gnus from displaying the Gnus
  137. ;; logo when invoking this command without loading Gnus.
  138. ;; Gnus demonstrates it when gnus.elc is being loaded if
  139. ;; a command of which the name is prefixed with "gnus"
  140. ;; causes that autoloading. See the code in question,
  141. ;; that is the one first found in gnus.el by performing
  142. ;; `C-s this-command'.
  143. (this-command (if (eq gnus-dired-mail-mode 'gnus-user-agent)
  144. 'gnoose-dired-attach
  145. this-command)))
  146. (compose-mail))
  147. (setq destination (current-buffer)))
  148. ;; set buffer to destination buffer, and attach files
  149. (set-buffer destination)
  150. (goto-char (point-max)) ;attach at end of buffer
  151. (while files-to-attach
  152. (mml-attach-file (car files-to-attach)
  153. (or (mm-default-file-encoding (car files-to-attach))
  154. "application/octet-stream") nil)
  155. (setq files-to-attach (cdr files-to-attach)))
  156. (message "Attached file(s) %s" files-str))))
  157. (autoload 'mailcap-parse-mailcaps "mailcap" "" t)
  158. (defun gnus-dired-find-file-mailcap (&optional file-name arg)
  159. "In dired, visit FILE-NAME according to the mailcap file.
  160. If ARG is non-nil, open it in a new buffer."
  161. (interactive (list
  162. (file-name-sans-versions (dired-get-filename) t)
  163. current-prefix-arg))
  164. (mailcap-parse-mailcaps)
  165. (if (file-exists-p file-name)
  166. (let (mime-type method)
  167. (if (and (not arg)
  168. (not (file-directory-p file-name))
  169. (string-match "\\.[^\\.]+$" file-name)
  170. (setq mime-type
  171. (mailcap-extension-to-mime
  172. (match-string 0 file-name)))
  173. (stringp
  174. (setq method
  175. (cdr (assoc 'viewer
  176. (car (mailcap-mime-info mime-type
  177. 'all
  178. 'no-decode)))))))
  179. (let ((view-command (mm-mailcap-command method file-name nil)))
  180. (message "viewing via %s" view-command)
  181. (start-process "*display*"
  182. nil
  183. shell-file-name
  184. shell-command-switch
  185. view-command))
  186. (find-file file-name)))
  187. (if (file-symlink-p file-name)
  188. (error "File is a symlink to a nonexistent target")
  189. (error "File no longer exists; type `g' to update Dired buffer"))))
  190. (defun gnus-dired-print (&optional file-name print-to)
  191. "In dired, print FILE-NAME according to the mailcap file.
  192. If there is no print command, print in a PostScript image. If the
  193. optional argument PRINT-TO is nil, send the image to the printer. If
  194. PRINT-TO is a string, save the PostScript image in a file with that
  195. name. If PRINT-TO is a number, prompt the user for the name of the
  196. file to save in."
  197. (interactive (list
  198. (file-name-sans-versions (dired-get-filename) t)
  199. (ps-print-preprint current-prefix-arg)))
  200. (mailcap-parse-mailcaps)
  201. (cond
  202. ((file-directory-p file-name)
  203. (error "Can't print a directory"))
  204. ((file-exists-p file-name)
  205. (let (mime-type method)
  206. (if (and (string-match "\\.[^\\.]+$" file-name)
  207. (setq mime-type
  208. (mailcap-extension-to-mime
  209. (match-string 0 file-name)))
  210. (stringp
  211. (setq method (mailcap-mime-info mime-type "print"
  212. 'no-decode))))
  213. (call-process shell-file-name nil
  214. (generate-new-buffer " *mm*")
  215. nil
  216. shell-command-switch
  217. (mm-mailcap-command method file-name mime-type))
  218. (with-temp-buffer
  219. (insert-file-contents file-name)
  220. (if (eq gnus-dired-mail-mode 'gnus-user-agent)
  221. (gnus-print-buffer)
  222. ;; FIXME:
  223. (error "MIME print only implemented via Gnus")))
  224. (ps-despool print-to))))
  225. ((file-symlink-p file-name)
  226. (error "File is a symlink to a nonexistent target"))
  227. (t
  228. (error "File no longer exists; type `g' to update Dired buffer"))))
  229. (provide 'gnus-dired)
  230. ;;; gnus-dired.el ends here