mh-identity.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. ;;; mh-identity.el --- multiple identify support for MH-E
  2. ;; Copyright (C) 2002-2012 Free Software Foundation, Inc.
  3. ;; Author: Peter S. Galbraith <psg@debian.org>
  4. ;; Maintainer: Bill Wohler <wohler@newt.com>
  5. ;; Keywords: mail
  6. ;; See: mh-e.el
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs is free software: you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation, either version 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; Multiple identity support for MH-E.
  20. ;; Used to easily set different fields such as From and Organization,
  21. ;; as well as different signature files.
  22. ;; Customize the variable `mh-identity-list' and see the Identity menu
  23. ;; in MH-Letter mode. The command `mh-insert-identity' can be used
  24. ;; to manually insert an identity.
  25. ;;; Change Log:
  26. ;;; Code:
  27. (require 'mh-e)
  28. (autoload 'mml-insert-tag "mml")
  29. (defvar mh-identity-pgg-default-user-id nil
  30. "Holds the GPG key ID to be used by pgg.el.
  31. This is normally set as part of an Identity in
  32. `mh-identity-list'.")
  33. (make-variable-buffer-local 'mh-identity-pgg-default-user-id)
  34. (defvar mh-identity-menu nil
  35. "The Identity menu.")
  36. (defalias 'mh-identity-make-menu-no-autoload 'mh-identity-make-menu)
  37. ;;;###mh-autoload
  38. (defun mh-identity-make-menu ()
  39. "Build the Identity menu.
  40. This should be called any time `mh-identity-list' or
  41. `mh-auto-fields-list' change.
  42. See `mh-identity-add-menu'."
  43. (easy-menu-define mh-identity-menu mh-letter-mode-map
  44. "MH-E identity menu"
  45. (append
  46. '("Identity")
  47. ;; Dynamically render :type corresponding to `mh-identity-list'
  48. ;; e.g.:
  49. ;; ["Home" (mh-insert-identity "Home")
  50. ;; :style radio :active (not (equal mh-identity-local "Home"))
  51. ;; :selected (equal mh-identity-local "Home")]
  52. '(["Insert Auto Fields"
  53. (mh-insert-auto-fields) mh-auto-fields-list]
  54. "--")
  55. (mapcar (function
  56. (lambda (arg)
  57. `[,arg (mh-insert-identity ,arg) :style radio
  58. :selected (equal mh-identity-local ,arg)]))
  59. (mapcar 'car mh-identity-list))
  60. '(["None"
  61. (mh-insert-identity "None") :style radio
  62. :selected (not mh-identity-local)]
  63. "--"
  64. ["Set Default for Session"
  65. (setq mh-identity-default mh-identity-local) t]
  66. ["Save as Default"
  67. (customize-save-variable 'mh-identity-default mh-identity-local) t]
  68. ["Customize Identities" (customize-variable 'mh-identity-list) t]
  69. ))))
  70. ;;;###mh-autoload
  71. (defun mh-identity-add-menu ()
  72. "Add the current Identity menu.
  73. See `mh-identity-make-menu'."
  74. (if mh-identity-menu
  75. (easy-menu-add mh-identity-menu)))
  76. (defvar mh-identity-local nil
  77. "Buffer-local variable that holds the identity currently in use.")
  78. (make-variable-buffer-local 'mh-identity-local)
  79. (defun mh-header-field-delete (field value-only)
  80. "Delete header FIELD, or only its value if VALUE-ONLY is t.
  81. Return t if anything is deleted."
  82. (let ((field-colon (if (string-match "^.*:$" field)
  83. field
  84. (concat field ":"))))
  85. (when (mh-goto-header-field field-colon)
  86. (if (not value-only)
  87. (beginning-of-line)
  88. (forward-char))
  89. (delete-region (point)
  90. (progn (mh-header-field-end)
  91. (if (not value-only) (forward-char 1))
  92. (point)))
  93. t)))
  94. (defvar mh-identity-signature-start nil
  95. "Marker for the beginning of a signature inserted by `mh-insert-identity'.")
  96. (defvar mh-identity-signature-end nil
  97. "Marker for the end of a signature inserted by `mh-insert-identity'.")
  98. (defun mh-identity-field-handler (field)
  99. "Return the handler for header FIELD or nil if none set.
  100. The field name is downcased. If the FIELD begins with the
  101. character \":\", then it must have a special handler defined in
  102. `mh-identity-handlers', else return an error since it is not a
  103. valid header field."
  104. (or (cdr (mh-assoc-string field mh-identity-handlers t))
  105. (and (eq (aref field 0) ?:)
  106. (error "Field %s not found in `mh-identity-handlers'" field))
  107. (cdr (assoc ":default" mh-identity-handlers))
  108. 'mh-identity-handler-default))
  109. ;;;###mh-autoload
  110. (defun mh-insert-identity (identity &optional maybe-insert)
  111. "Insert fields specified by given IDENTITY.
  112. In a program, do not insert fields if MAYBE-INSERT is non-nil,
  113. `mh-identity-default' is non-nil, and fields have already been
  114. inserted.
  115. See `mh-identity-list'."
  116. (interactive
  117. (list (completing-read
  118. "Identity: "
  119. (if mh-identity-local
  120. (cons '("None")
  121. (mapcar 'list (mapcar 'car mh-identity-list)))
  122. (mapcar 'list (mapcar 'car mh-identity-list)))
  123. nil t)
  124. nil))
  125. (when (or (not maybe-insert)
  126. (and (boundp 'mh-identity-default)
  127. mh-identity-default
  128. (not mh-identity-local)))
  129. (save-excursion
  130. ;;First remove old settings, if any.
  131. (when mh-identity-local
  132. (let ((pers-list (cadr (assoc mh-identity-local mh-identity-list))))
  133. (while pers-list
  134. (let* ((field (caar pers-list))
  135. (handler (mh-identity-field-handler field)))
  136. (funcall handler field 'remove))
  137. (setq pers-list (cdr pers-list)))))
  138. ;; Then insert the replacement
  139. (when (not (equal "None" identity))
  140. (let ((pers-list (cadr (assoc identity mh-identity-list))))
  141. (while pers-list
  142. (let* ((field (caar pers-list))
  143. (value (cdar pers-list))
  144. (handler (mh-identity-field-handler field)))
  145. (funcall handler field 'add value))
  146. (setq pers-list (cdr pers-list))))))
  147. ;; Remember what is in use in this buffer
  148. (if (equal "None" identity)
  149. (setq mh-identity-local nil)
  150. (setq mh-identity-local identity))))
  151. ;;;###mh-autoload
  152. (defun mh-identity-handler-gpg-identity (field action &optional value)
  153. "Process header FIELD \":pgg-default-user-id\".
  154. The ACTION is one of 'remove or 'add. If 'add, the VALUE is added.
  155. The buffer-local variable `mh-identity-pgg-default-user-id' is set to
  156. VALUE when action 'add is selected."
  157. (cond
  158. ((or (equal action 'remove)
  159. (not value)
  160. (string= value ""))
  161. (setq mh-identity-pgg-default-user-id nil))
  162. ((equal action 'add)
  163. (setq mh-identity-pgg-default-user-id value))))
  164. ;;;###mh-autoload
  165. (defun mh-identity-handler-signature (field action &optional value)
  166. "Process header FIELD \":signature\".
  167. The ACTION is one of 'remove or 'add. If 'add, the VALUE is
  168. added."
  169. (cond
  170. ((equal action 'remove)
  171. (when (and (markerp mh-identity-signature-start)
  172. (markerp mh-identity-signature-end))
  173. (delete-region mh-identity-signature-start
  174. mh-identity-signature-end)))
  175. (t
  176. ;; Insert "signature". Nil value means to use `mh-signature-file-name'.
  177. (when (not (mh-signature-separator-p)) ;...unless already present
  178. (goto-char (point-max))
  179. (save-restriction
  180. (narrow-to-region (point) (point))
  181. (if (null value)
  182. (mh-insert-signature)
  183. (mh-insert-signature value))
  184. (set (make-local-variable 'mh-identity-signature-start)
  185. (point-min-marker))
  186. (set-marker-insertion-type mh-identity-signature-start t)
  187. (set (make-local-variable 'mh-identity-signature-end)
  188. (point-max-marker)))))))
  189. (defvar mh-identity-attribution-verb-start nil
  190. "Marker for the beginning of the attribution verb.")
  191. (defvar mh-identity-attribution-verb-end nil
  192. "Marker for the end of the attribution verb.")
  193. ;;;###mh-autoload
  194. (defun mh-identity-handler-attribution-verb (field action &optional value)
  195. "Process header FIELD \":attribution-verb\".
  196. The ACTION is one of 'remove or 'add. If 'add, the VALUE is
  197. added."
  198. (when (and (markerp mh-identity-attribution-verb-start)
  199. (markerp mh-identity-attribution-verb-end))
  200. (delete-region mh-identity-attribution-verb-start
  201. mh-identity-attribution-verb-end)
  202. (goto-char mh-identity-attribution-verb-start)
  203. (cond
  204. ((equal action 'remove) ; Replace with default
  205. (mh-identity-insert-attribution-verb nil))
  206. (t ; Insert attribution verb.
  207. (mh-identity-insert-attribution-verb value)))))
  208. ;;;###mh-autoload
  209. (defun mh-identity-insert-attribution-verb (value)
  210. "Insert VALUE as attribution verb, setting up delimiting markers.
  211. If VALUE is nil, use `mh-extract-from-attribution-verb'."
  212. (save-restriction
  213. (narrow-to-region (point) (point))
  214. (if (null value)
  215. (insert mh-extract-from-attribution-verb)
  216. (insert value))
  217. (set (make-local-variable 'mh-identity-attribution-verb-start)
  218. (point-min-marker))
  219. (set-marker-insertion-type mh-identity-attribution-verb-start t)
  220. (set (make-local-variable 'mh-identity-attribution-verb-end)
  221. (point-max-marker))))
  222. (defun mh-identity-handler-default (field action top &optional value)
  223. "Process header FIELD.
  224. The ACTION is one of 'remove or 'add. If TOP is non-nil, add the
  225. field and its VALUE at the top of the header, else add it at the
  226. bottom of the header. If action is 'add, the VALUE is added."
  227. (let ((field-colon (if (string-match "^.*:$" field)
  228. field
  229. (concat field ":"))))
  230. (cond
  231. ((equal action 'remove)
  232. (mh-header-field-delete field-colon nil))
  233. (t
  234. (cond
  235. ;; No value, remove field
  236. ((or (not value)
  237. (string= value ""))
  238. (mh-header-field-delete field-colon nil))
  239. ;; Existing field, replace
  240. ((mh-header-field-delete field-colon t)
  241. (insert value))
  242. ;; Other field, add at end or top
  243. (t
  244. (goto-char (point-min))
  245. (if (not top)
  246. (mh-goto-header-end 0))
  247. (insert field-colon " " value "\n")))))))
  248. ;;;###mh-autoload
  249. (defun mh-identity-handler-top (field action &optional value)
  250. "Process header FIELD.
  251. The ACTION is one of 'remove or 'add. If 'add, the VALUE is
  252. added. If the field wasn't present, it is added to the top of the
  253. header."
  254. (mh-identity-handler-default field action t value))
  255. ;;;###mh-autoload
  256. (defun mh-identity-handler-bottom (field action &optional value)
  257. "Process header FIELD.
  258. The ACTION is one of 'remove or 'add. If 'add, the VALUE is
  259. added. If the field wasn't present, it is added to the bottom of
  260. the header."
  261. (mh-identity-handler-default field action nil value))
  262. (provide 'mh-identity)
  263. ;; Local Variables:
  264. ;; indent-tabs-mode: nil
  265. ;; sentence-end-double-space: nil
  266. ;; End:
  267. ;;; mh-identity.el ends here