PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lisp/play/fortune.el

https://gitlab.com/wilfred/emacs
Emacs Lisp | 336 lines | 229 code | 41 blank | 66 comment | 13 complexity | 17a7fa1614a9fbf8f665c52ca3e1ca7b MD5 | raw file
  1. ;;; fortune.el --- use fortune to create signatures
  2. ;; Copyright (C) 1999, 2001-2016 Free Software Foundation, Inc.
  3. ;; Author: Holger Schauer <Holger.Schauer@gmx.de>
  4. ;; Keywords: games utils mail
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; This utility allows you to automatically cut regions to a fortune
  18. ;; file. In case that the region stems from an article buffer (mail or
  19. ;; news), it will try to automatically determine the author of the
  20. ;; fortune. It will also allow you to compile your fortune-database
  21. ;; as well as providing a function to extract a fortune for use as your
  22. ;; signature.
  23. ;; Of course, it can simply display a fortune, too.
  24. ;; Use prefix arguments to specify different fortune databases.
  25. ;;; Installation:
  26. ;; Please check the customize settings -- you will at least have to
  27. ;; modify the values of `fortune-dir' and `fortune-file'.
  28. ;; I then use this in my .gnus:
  29. ;;(message "Making new signature: %s" (fortune-to-signature "~/fortunes/"))
  30. ;; This automagically creates a new signature when starting up Gnus.
  31. ;; Note that the call to fortune-to-signature specifies a directory in which
  32. ;; several fortune-files and their databases are stored.
  33. ;; If you like to get a new signature for every message, you can also hook
  34. ;; it into message-mode:
  35. ;; (add-hook 'message-setup-hook 'fortune-to-signature)
  36. ;; This time no fortune-file is specified, so fortune-to-signature would use
  37. ;; the default-file as specified by fortune-file.
  38. ;; I have also this in my .gnus:
  39. ;;(add-hook 'gnus-article-mode-hook
  40. ;; (lambda ()
  41. ;; (define-key gnus-article-mode-map "i" 'fortune-from-region)))
  42. ;; which allows marking a region and then pressing "i" so that the marked
  43. ;; region will be automatically added to my favorite fortune-file.
  44. ;;; Code:
  45. ;;; **************
  46. ;;; Customizable Settings
  47. (defgroup fortune nil
  48. "Settings for fortune."
  49. :link '(emacs-commentary-link "fortune.el")
  50. :version "21.1"
  51. :group 'games)
  52. (defgroup fortune-signature nil
  53. "Settings for use of fortune for signatures."
  54. :group 'fortune
  55. :group 'mail)
  56. (defcustom fortune-dir "~/docs/ascii/misc/fortunes/"
  57. "The directory to look in for local fortune cookies files."
  58. :type 'directory
  59. :group 'fortune)
  60. (defcustom fortune-file
  61. (expand-file-name "usenet" fortune-dir)
  62. "The file in which local fortune cookies will be stored."
  63. :type 'file
  64. :group 'fortune)
  65. (defcustom fortune-database-extension ".dat"
  66. "The extension of the corresponding fortune database.
  67. Normally you won't have a reason to change it."
  68. :type 'string
  69. :group 'fortune)
  70. (defcustom fortune-program "fortune"
  71. "Program to select a fortune cookie."
  72. :type 'string
  73. :group 'fortune)
  74. (defcustom fortune-program-options ()
  75. "List of options to pass to the fortune program."
  76. :type '(choice (repeat (string :tag "Option"))
  77. (string :tag "Obsolete string of options"))
  78. :version "23.1"
  79. :group 'fortune)
  80. (defcustom fortune-strfile "strfile"
  81. "Program to compute a new fortune database."
  82. :type 'string
  83. :group 'fortune)
  84. (defcustom fortune-strfile-options ""
  85. "Options to pass to the strfile program (a string)."
  86. :type 'string
  87. :group 'fortune)
  88. (defcustom fortune-quiet-strfile-options "> /dev/null"
  89. "Text added to the command for running `strfile'.
  90. By default it discards the output produced by `strfile'.
  91. Set this to \"\" if you would like to see the output."
  92. :type 'string
  93. :group 'fortune)
  94. (defcustom fortune-always-compile t
  95. "Non-nil means automatically compile fortune files.
  96. If nil, you must invoke `fortune-compile' manually to do that."
  97. :type 'boolean
  98. :group 'fortune)
  99. (defcustom fortune-author-line-prefix " -- "
  100. "Prefix to put before the author name of a fortunate."
  101. :type 'string
  102. :group 'fortune-signature)
  103. (defcustom fortune-fill-column fill-column
  104. "Fill column for fortune files."
  105. :type 'integer
  106. :group 'fortune-signature)
  107. (defcustom fortune-from-mail "private e-mail"
  108. "String to use to characterize that the fortune comes from an e-mail.
  109. No need to add an `in'."
  110. :type 'string
  111. :group 'fortune-signature)
  112. (defcustom fortune-sigstart ""
  113. "Some text to insert before the fortune cookie, in a mail signature."
  114. :type 'string
  115. :group 'fortune-signature)
  116. (defcustom fortune-sigend ""
  117. "Some text to insert after the fortune cookie, in a mail signature."
  118. :type 'string
  119. :group 'fortune-signature)
  120. ;; not customizable settings
  121. (defvar fortune-buffer-name "*fortune*")
  122. (defconst fortune-end-sep "\n%\n")
  123. ;;; **************
  124. ;;; Inserting a new fortune
  125. (defun fortune-append (string &optional interactive file)
  126. "Appends STRING to the fortune FILE.
  127. If INTERACTIVE is non-nil, don't compile the fortune file afterwards."
  128. (setq file (expand-file-name
  129. (substitute-in-file-name (or file fortune-file))))
  130. (if (file-directory-p file)
  131. (error "Cannot append fortune to directory %s" file))
  132. (if interactive ; switch to file and return buffer
  133. (find-file-other-frame file)
  134. (find-file-noselect file))
  135. (let ((fortune-buffer (get-file-buffer file)))
  136. (set-buffer fortune-buffer)
  137. (goto-char (point-max))
  138. (setq fill-column fortune-fill-column)
  139. (setq auto-fill-inhibit-regexp "^%")
  140. (turn-on-auto-fill)
  141. (insert string fortune-end-sep)
  142. (unless interactive
  143. (save-buffer)
  144. (if fortune-always-compile
  145. (fortune-compile file)))))
  146. (defun fortune-ask-file ()
  147. "Asks the user for a file-name."
  148. (expand-file-name
  149. (read-file-name
  150. "Fortune file to use: "
  151. fortune-dir nil nil "")))
  152. ;;;###autoload
  153. (defun fortune-add-fortune (string file)
  154. "Add STRING to a fortune file FILE.
  155. Interactively, if called with a prefix argument,
  156. read the file name to use. Otherwise use the value of `fortune-file'."
  157. (interactive
  158. (list (read-string "Fortune: ")
  159. (if current-prefix-arg (fortune-ask-file))))
  160. (fortune-append string t file))
  161. ;;;###autoload
  162. (defun fortune-from-region (beg end file)
  163. "Append the current region to a local fortune-like data file.
  164. Interactively, if called with a prefix argument,
  165. read the file name to use. Otherwise use the value of `fortune-file'."
  166. (interactive
  167. (list (region-beginning) (region-end)
  168. (if current-prefix-arg (fortune-ask-file))))
  169. (let ((string (buffer-substring beg end))
  170. author newsgroup help-point)
  171. ;; try to determine author ...
  172. (save-excursion
  173. (goto-char (point-min))
  174. (setq help-point
  175. (search-forward-regexp
  176. "^From: \\(.*\\)$"
  177. (point-max) t))
  178. (if help-point
  179. (setq author (buffer-substring (match-beginning 1) help-point))
  180. (setq author "An unknown author")))
  181. ;; ... and newsgroup
  182. (save-excursion
  183. (goto-char (point-min))
  184. (setq help-point
  185. (search-forward-regexp
  186. "^Newsgroups: \\(.*\\)$"
  187. (point-max) t))
  188. (if help-point
  189. (setq newsgroup (buffer-substring (match-beginning 1) help-point))
  190. (setq newsgroup (if (or (eq major-mode 'gnus-article-mode)
  191. (eq major-mode 'vm-mode)
  192. (eq major-mode 'rmail-mode))
  193. fortune-from-mail
  194. "unknown"))))
  195. ;; append entry to end of fortune file, and display result
  196. (setq string (concat "\"" string "\""
  197. "\n"
  198. fortune-author-line-prefix
  199. author " in " newsgroup))
  200. (fortune-append string t file)))
  201. ;;; **************
  202. ;;; Compile new database with strfile
  203. ;;;###autoload
  204. (defun fortune-compile (&optional file)
  205. "Compile fortune file.
  206. If called with a prefix asks for the FILE to compile, otherwise uses
  207. the value of `fortune-file'. This currently cannot handle directories."
  208. (interactive
  209. (list
  210. (if current-prefix-arg
  211. (fortune-ask-file)
  212. fortune-file)))
  213. (let* ((fortune-file (expand-file-name (substitute-in-file-name file)))
  214. (fortune-dat (expand-file-name
  215. (substitute-in-file-name
  216. (concat fortune-file fortune-database-extension)))))
  217. (cond ((file-exists-p fortune-file)
  218. (cond ((file-newer-than-file-p fortune-file fortune-dat)
  219. (message "Compiling new fortune database %s" fortune-dat)
  220. (shell-command
  221. (concat fortune-strfile fortune-strfile-options
  222. " " fortune-file fortune-quiet-strfile-options)))))
  223. (t (error "Can't compile fortune file %s" fortune-file)))))
  224. ;;; **************
  225. ;;; Use fortune for signature
  226. ;;;###autoload
  227. (defun fortune-to-signature (&optional file)
  228. "Create signature from output of the fortune program.
  229. If called with a prefix asks for the FILE to choose the fortune from,
  230. otherwise uses the value of `fortune-file'. If you want to have fortune
  231. choose from a set of files in a directory, call interactively with prefix
  232. and choose the directory as the fortune-file."
  233. (interactive
  234. (list
  235. (if current-prefix-arg
  236. (fortune-ask-file)
  237. fortune-file)))
  238. (save-excursion
  239. (fortune-in-buffer t file)
  240. (set-buffer fortune-buffer-name)
  241. (let* ((fortune (buffer-string))
  242. (signature (concat fortune-sigstart fortune fortune-sigend)))
  243. (setq mail-signature signature)
  244. (if (boundp 'message-signature)
  245. (setq message-signature signature)))))
  246. ;;; **************
  247. ;;; Display fortune
  248. (defun fortune-in-buffer (_interactive &optional file)
  249. "Put a fortune cookie in the *fortune* buffer.
  250. INTERACTIVE is ignored. Optional argument FILE, when supplied,
  251. specifies the file to choose the fortune from."
  252. (let ((fortune-buffer (or (get-buffer fortune-buffer-name)
  253. (generate-new-buffer fortune-buffer-name)))
  254. (fort-file (expand-file-name
  255. (substitute-in-file-name
  256. (or file fortune-file)))))
  257. (with-current-buffer fortune-buffer
  258. (let ((inhibit-read-only t))
  259. (erase-buffer)
  260. (if fortune-always-compile
  261. (fortune-compile fort-file))
  262. (apply 'call-process
  263. fortune-program ; program to call
  264. nil fortune-buffer nil ; INFILE BUFFER DISPLAY
  265. (append (if (stringp fortune-program-options)
  266. (split-string fortune-program-options)
  267. fortune-program-options) (list fort-file)))))))
  268. ;;;###autoload
  269. (defun fortune-message (&optional file)
  270. "Display a fortune cookie to the mini-buffer.
  271. If called with a prefix, it has the same behavior as `fortune'.
  272. Optional FILE is a fortune file from which a cookie will be selected."
  273. (interactive (list (if current-prefix-arg
  274. (fortune-ask-file)
  275. fortune-file)))
  276. (with-temp-buffer
  277. (let ((fortune-buffer-name (current-buffer)))
  278. (fortune-in-buffer t file)
  279. (message "%s" (buffer-string)))))
  280. ;;;###autoload
  281. (defun fortune (&optional file)
  282. "Display a fortune cookie.
  283. If called with a prefix asks for the FILE to choose the fortune from,
  284. otherwise uses the value of `fortune-file'. If you want to have fortune
  285. choose from a set of files in a directory, call interactively with prefix
  286. and choose the directory as the fortune-file."
  287. (interactive (list (if current-prefix-arg
  288. (fortune-ask-file)
  289. fortune-file)))
  290. (fortune-in-buffer t file)
  291. (switch-to-buffer (get-buffer fortune-buffer-name))
  292. (setq buffer-read-only t))
  293. ;;; Provide ourselves.
  294. (provide 'fortune)
  295. ;;; fortune.el ends here