;;; moggle.el --- iterate headers and body in message-mode -*- lexical-binding: t -*- ;; ;; Author: Emanuel Berg ;; Created: 2014-07-04 ;; Keywords: news, mail ;; License: GPL3+ ;; URL: https://dataswamp.org/~incal/emacs-init/gnus/moggle.el ;; Version: 2.2.4 ;; ;;; Commentary: ;; ;; In the current message, hit one (1) key to go to the next ;; field to type. The first fields in a message are the ;; headers -- "To", "Subject", and so on -- and the last one ;; is the body. ;; ;; And, there is another key to do the exact same thing, only ;; in the opposite direction! ;; ;; By default, `next-header' is bound to TAB ("\t"), and ;; `previous-header' to BACKTAB (; i.e., right-shift ;; and TAB). ;; ;; This also plays seamlessly with the abbrevs of the ;; ~/.mailrc file. Try it: setup an alias, type it in the ;; "To" header, and hit TAB. ;; ;; For example, for mail addresses, ~/.mailrc can look like ;; this: ;; ;; alias john "John DiFool " ;; alias kate "Katherine Moss " ;; alias friends john kate ;; ;; (For Usenet/Gmane groups, ordinary abbrevs are setup: geh ;; -> gnu.emacs.help (gmane.emacs.help) and so on.) ;; ;; All in all, this makes for rapid, mouse-free editing of ;; mails and Usenet/Gmane posts. ;; ;;; Code: (require 'message) (defun get-header-separator-pos () "Get the position of `mail-header-separator'." (save-excursion (rfc822-goto-eoh) (point) )) (defun at-end-of-line-p () "True iff point is at the end of the current line." (looking-at "$")) (defun next-line-header-or-body () "Go to the next header field. If already at the last header field go to the message body." (if (re-search-forward ": " (get-header-separator-pos) t) (end-of-line) (message-goto-body) )) (defun end-of-line-or-next-line () "If not at the end of a line go there. Else got to the next header field if it exists." (if (at-end-of-line-p) (next-line-header-or-body) (end-of-line) )) (defun next-header () "Go to the next header field. If already at the last one go to the message body." (interactive) (if (< (point) (get-header-separator-pos)) (progn (expand-abbrev) (end-of-line-or-next-line) ) (goto-char (point-min)) (end-of-line-or-next-line) )) (defun prev-header () "Go to the previous header field. If already at the first one got to the message body." (interactive) (if (< (point) (get-header-separator-pos)) (progn (expand-abbrev) (if (= 1 (line-number-at-pos)) (message-goto-body) (forward-line -1) ) (end-of-line) ) (goto-char (get-header-separator-pos)) (backward-char 1) )) (define-key message-mode-map "\t" #'next-header) (define-key message-mode-map [backtab] #'prev-header) (provide 'moggle) ;;; moggle.el ends here