1 ;;; ganneff.el --- Lotsa functiuons and their variables for stuff
2 ;;; ganneffs .emacs wants
4 ;; Copyright (C) 2012 Joerg Jaspert
6 ;; Filename: ganneff.de
7 ;; Author: Joerg Jaspert <joerg@debian.org>
9 ;; The functions in the bh/ namespace are taken from
10 ;; http://doc.norang.ca/org-mode.org.html which has:
11 ;; #+AUTHOR: Bernt Hansen (IRC:Thumper_ on freenode)
12 ;; #+EMAIL: bernt@norang.ca
13 ;; and the following license statement:
15 ;; This document http://doc.norang.ca/org-mode.html and (either in its
16 ;; HTML format or in its Org format) is licensed under the GNU Free
17 ;; Documentation License version 1.3 or later
18 ;; (http://www.gnu.org/copyleft/fdl.html).
20 ;; The code examples and css stylesheets are licensed under the GNU
21 ;; General Public License v3 or later
22 ;; (http://www.gnu.org/licenses/gpl.html).
25 ;;** Correct message and unread count (http://www.emacswiki.org/emacs/GnusNiftyTricks)
29 (defun gnus-nnimap-count-format (n)
30 (let ((method (or gnus-tmp-method gnus-select-method)))
31 (when (eq (car method) 'nnimap)
32 (let ((counts (nnimap-request-message-counts gnus-tmp-group method)))
33 (if counts (format "%d" (nth n counts)) "?")))))
36 (defun gnus-user-format-function-t (dummy)
37 (or (gnus-nnimap-count-format 0)
38 gnus-tmp-number-total))
41 (defun gnus-user-format-function-x (dummy)
42 (or (gnus-nnimap-count-format 1)
43 gnus-tmp-number-of-unread))
45 (defvar gnus-user-format-function-g-prev "" "")
47 (defun empty-common-prefix (left right)
48 "Given `left' '(\"foo\" \"bar\" \"fie\") and `right' '(\"foo\"
49 \"bar\" \"fum\"), return '(\" \" \" \" \"fum\")."
50 (if (and (cdr right) ; always keep the last part of right
51 (equal (car left) (car right)))
52 (cons (make-string (length (car left)) ? )
53 (empty-common-prefix (cdr left) (cdr right)))
56 (defun gnus-user-format-function-g (arg)
57 "The full group name, but if it starts with a previously seen
58 prefix, empty that prefix."
59 (if (equal gnus-user-format-function-g-prev gnus-tmp-group) ; line-format is updated on exiting the summary, making prev equal this
61 (let* ((prev (split-string-and-unquote gnus-user-format-function-g-prev "\\.\\|:"))
62 (this (split-string-and-unquote gnus-tmp-group "\\.\\|:")))
63 (setq gnus-user-format-function-g-prev gnus-tmp-group)
64 (combine-and-quote-strings
65 (empty-common-prefix prev this)
69 (defvar nnimap-message-count-cache-alist nil)
72 (defun nnimap-message-count-cache-clear ()
73 (setq nnimap-message-count-cache-alist nil))
76 (defun nnimap-message-count-cache-get (group)
77 (cadr (assoc group nnimap-message-count-cache-alist)))
80 (defun nnimap-message-count-cache-set (group count)
81 (push (list group count) nnimap-message-count-cache-alist))
84 (defun nnimap-request-message-counts (group method)
85 (or (nnimap-message-count-cache-get group)
86 (let ((counts (nnimap-fetch-message-counts group method)))
87 (nnimap-message-count-cache-set group counts)
91 (defun nnimap-fetch-message-counts (group method)
92 (let ((imap-group (nnimap-decode-gnus-group (car (last (split-string group ":")))))
93 (server (cadr method)))
94 (when (nnimap-change-group imap-group server)
95 (message "Requesting message count for %s..." group)
96 (with-current-buffer (nnimap-buffer)
100 (nnimap-command "STATUS %S (MESSAGES UNSEEN)"
101 (utf7-encode imap-group t))))))
102 (message "Requesting message count for %s...done" group)
104 (mapcar #'string-to-number
106 (nth 1 response) (nth 3 response)))))))))
109 (defun jj-forward-spam ()
111 (gnus-summary-mail-forward 1)
113 (insert "joerg@ganneff.de")
115 (let ((ans (completing-read "Spam / Nospam? "
118 (cond ((string= ans "s")
119 (insert "command ganneffcrm spam"))
121 (insert "command ganneffcrm nonspam"))
123 (error "Invalid choice.")))))
126 (defun jj-forward-ham-lists-debconf ()
128 (gnus-summary-resend-message "mailmansplit-and-learn-as-ham@smithers.debconf.org" 1)
131 (defun jj-forward-spam-lists-debconf ()
133 (gnus-summary-resend-message "mailmansplit-discard-and-learn-as-spam@smithers.debconf.org" 1)
137 (defun jj-forward-ham-lists-oftc ()
139 (gnus-summary-resend-message "mailmansplit-and-learn-as-ham@lists.oftc.net" 1)
143 (defun jj-forward-spam-lists-oftc ()
145 (gnus-summary-resend-message "mailmansplit-discard-and-learn-as-spam@lists.oftc.net" 1)
149 (defun jj-forward-ham-lists-spi ()
151 (gnus-summary-resend-message "mailmansplit-and-learn-as-ham@lists.spi-inc.org" 1)
155 (defun jj-forward-spam-lists-spi ()
157 (gnus-summary-resend-message "mailmansplit-discard-and-learn-as-spam@lists.spi-inc.org" 1)
160 (defun jj-forward-issue ()
162 (gnus-summary-resend-message "ganneff_tm+c57957@rmilk.com" 1)
165 (defun jj-move-mail-spambox ()
167 (gnus-summary-move-article nil "nnfolder+archive:Spam" nil))
168 ; (gnus-summary-move-article nil "nnimap+gkar:learnspam" nil))
171 (defun jj-copy-mail-hambox ()
173 (gnus-summary-copy-article nil "nnfolder+archive:Ham" nil))
175 ;;** Funktion liefert einen korrekten Datumsstring zurueck, fuer Summaryanzeige
177 (defun gnus-user-format-function-y (header)
178 "Convert the DATE to DD.MM.YYYY, HH:MM."
179 (format-time-string "%d.%m.%y, %R"
180 (gnus-date-get-time (mail-header-date header))))
183 (defun gnus-user-format-function-j (headers)
184 (let ((to (gnus-extra-header 'To headers)))
185 (if (string-match gnus-ignored-from-addresses to)
186 (if (string-match "," to) "~" "»")
187 (if (or (string-match gnus-ignored-from-addresses
188 (gnus-extra-header 'Cc headers))
189 (string-match gnus-ignored-from-addresses
190 (gnus-extra-header 'BCc headers)))
194 ;;** Ich will jeder Nachricht/Mail Header beifügen. Dies tu ich mit Aufruf dieser Funktion.
196 (defun my-message-add-content ()
197 (message-add-header "X-GPG-ID: 0xB12525C4")
198 (message-add-header "X-GPG-FP: FBFA BDB5 41B5 DC95 5BD9 BA6E DB16 CF5B B125 25C4")
199 (message-add-header "X-message-flag: Formating hard disk. please wait... 10%... 20%..."))
201 ;;** Und was ich hasse sind Antworten auf Mails in Mailinglisten die auch per CC an mich gesandt wird. Son
202 ;;** Scheiss, ich lese die Listen mit wo ich schreibe !
204 (defun my-message-header-setup-hook ()
205 (let ((group (or gnus-newsgroup-name "")))
206 (when (or (message-fetch-field "newsgroups")
207 (gnus-group-find-parameter group 'to-address)
208 (gnus-group-find-parameter group 'to-list))
209 (insert "Mail-Copies-To: never\n"))))
212 ;;** Automagisch neue Mail/News holen.
214 (defun us-get-only-mail ()
216 (gnus-group-get-new-news))
219 (defun september-citation-line ()
221 (when message-reply-headers
225 (time-to-days (mail-header-parse-date
226 (mail-header-date message-reply-headers)))
227 (time-to-days (encode-time 0 0 0 13 03 1977))))
228 ; (time-to-days (encode-time 0 0 0 01 09 1993))))
230 (let* ((email (mail-header-from message-reply-headers))
231 (data (mail-extract-address-components email))
233 (net (car (cdr data))))
237 ;;** Scorefileeinträge sollen nach bestimmter Zeit automagisch gelöscht werden. Speziell die vom
238 ;;** adaptiven Scoring. Sonst hab ich irgendwann MB grosse Scorefiles.
240 (defun gnus-decay-score (score)
242 This is done according to `gnus-score-decay-constant'
243 and `gnus-score-decay-scale'."
246 (* (if (< score 0) 1 -1)
248 (max gnus-score-decay-constant
250 gnus-score-decay-scale)))))))
252 ;;** Ein Menu für die genialen Message-Utils erstellen.
254 (defun message-utils-setup ()
255 "Add menu-entries for message-utils."
256 (easy-menu-add-item nil '("Message")
257 ["Insert Region Marked" message-mark-inserted-region t] "Spellcheck")
258 (easy-menu-add-item nil '("Message")
259 ["Insert File Marked" message-mark-insert-file t] "Spellcheck")
260 (easy-menu-add-item nil '("Field")
261 ["Crosspost / Followup" message-xpost-fup2 t] "----")
262 (easy-menu-add-item nil '("Field")
263 ["New Subject" message-mark-inserted-region t] "----")
264 (easy-menu-add-item nil '("Field")
265 ["Reduce To: to Cc:" message-reduce-to-to-cc t] "----")
266 (easy-menu-add-item nil '("Field")
267 [ "X-No-Archive:" message-add-archive-header t ]))
269 ;* This function should be called from the summary buffer with point
270 ;* on the article to nuke. It puts a rule in ~/News/FUCKSTAINS to lower
272 ;* It needs an entry in all.SCORE of (files "~/News/FUCKSTAINS").
273 ; I changed it to only add the from line.
275 (defun gnus-scum-expunge ()
276 "Remove this spammer from existance as much as possible."
278 (let* ((hdr (gnus-summary-article-header))
282 (atsign (string-match "@" artid))
283 (host (substring artid (+ atsign 1) (- (length artid) 1)))
284 (oldscfile gnus-current-score-file)
285 (scoredate (time-to-days (current-time))))
286 (gnus-summary-score-entry "references" (concat artid "$") 'R' -1000 scoredate)
287 (gnus-summary-score-entry "references" artid 'S' -500 scoredate)
288 ;; Change to our spammer score file
289 (gnus-score-change-score-file "FUCKSTAINS")
290 ;; Add our horrible spammer scores
291 (gnus-summary-score-entry "Subject" subj 'S' -1000 scoredate)
292 (gnus-summary-score-entry "From" auth 'S' -9999 scoredate)
293 (gnus-summary-score-entry "Message-ID" host 'S' -5 scoredate) ; mild
294 ;; Change back to old current score file
295 (gnus-score-change-score-file oldscfile)
299 (defun lld-notmuch-shortcut ()
300 (define-key gnus-group-mode-map "GG" 'notmuch-search)
304 (defun lld-notmuch-file-to-group (file)
305 "Calculate the Gnus group name from the given file name."
306 (let ((group (file-name-directory (directory-file-name (file-name-directory file)))))
307 (setq group (replace-regexp-in-string ".*/Maildir/" "nnimap+gkar:" group))
308 (setq group (replace-regexp-in-string "/$" "" group))
309 (if (string-match ":$" group)
310 (concat group "INBOX"))
311 (setq group (replace-regexp-in-string ":\\." ":" group))))
312 ;; Seems like we don't even need this part:
313 ; (setq group (replace-regexp-in-string "nnimap\\+gkar:\\.?" "" group))))
316 (defun lld-notmuch-goto-message-in-gnus ()
317 "Open a summary buffer containing the current notmuch article."
319 (unless (gnus-alive-p) (with-temp-buffer (gnus)))
320 (let ((group (lld-notmuch-file-to-group (notmuch-show-get-filename)))
322 (replace-regexp-in-string "\"" ""
323 (replace-regexp-in-string "^id:" ""
324 (notmuch-show-get-message-id)))))
325 (if (and group message-id)
327 (gnus-summary-read-group group 100) ; have to show at least one old message
328 (gnus-summary-refer-article message-id)) ; simpler than org-gnus method?
329 (message "Couldn't get relevant infos for switching to Gnus."))))
331 ;; this corresponds to a topic line format of "%n %A"
333 (defun gnus-user-format-function-topic-line (dummy)
334 (let ((topic-face (if (zerop total-number-of-articles)
335 'gnus-summary-low-ancient
336 'gnus-summary-high-ancient)))
338 (format "%s %d" name total-number-of-articles)
342 (defun sign-or-crypt ()
344 (let ((ans (completing-read "Sign/Inlinesign/Encrypt/Nothing? "
345 '(("s" s) ("i" i) ("e" e) ("n" n))
347 (cond ((string= ans "s")
348 (mml-secure-message mml-default-sign-method 'sign)
350 ;(insert "<#secure method=pgpmime mode=sign>\n")
353 (mml-secure-message "pgp" 'sign))
355 (mml-secure-message-encrypt-pgpmime)
357 ;(insert "<#secure method=pgpmime mode=signencrypt>\n")
360 (message "Message sent unmodified."))
362 (error "Invalid choice.")))))
364 (provide 'ganneff-gnus)