unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: "Pascal J. Bourguignon" <pjb@informatimago.com>
To: help-gnu-emacs@gnu.org
Subject: Re: Moving between headers in message-mode
Date: Sat, 15 Jun 2013 14:58:14 +0200	[thread overview]
Message-ID: <87vc5ffs49.fsf@kuiper.lan.informatimago.com> (raw)
In-Reply-To: 87wqpwgh03.fsf@VLAN-3434.student.uu.se

Emanuel Berg <embe8573@student.uu.se> writes:

> Hello all. I wrote this tonight. The purpose is defined in the
> docstring. It is supposed to be used in message-mode. I haven't
> done much testing but it seems to work. If you have any
> suggestions how to make it better, please tell me. Cheers.
>
> ;; separator
> (setq mail-header-separator "---")
> (set-face-attribute 'message-separator nil :foreground "black")
>
> (defun do-nothing () "Do nothing." () )
> (defun iterate-header (back)
>   "Unless BACK, go to the next header input field:
> either on the same line as the present point,
> or the next header below.
> If the field has a string, put point to the string's right;
> if the field is empty, put point so that typing will set the header,
> without any prior cursor movement.
> If you move from a header which has data, that data is expanded if
> found to be an `abbrev-mode' abbreviation (possibly setup in
> ~/.mailrc), without need for a whitespace.
> If there are no headers left, `message-goto-body';
> if already in the body, goto the topmost header.
> If BACK, do the same, only in reverse direction."
>   (interactive)
>     (let ((position (point)))
>       (goto-char (point-min))
>       (search-forward mail-header-separator)
>       (let ((separator-pos (point))
>             (search-fun)
>             (start-pos)
>             (end-pos)
>             (chars-forward-after-hit)
>             (maybe-beginning-of-line))
>         (if back
>             (progn
>               (setq search-fun 'search-backward)
>               (setq start-pos separator-pos)
>               (setq end-pos (point-min))
>               (setq chars-forward-after-hit 2)
>               (setq maybe-beginning-of-line 'beginning-of-line) )
>             (progn
>               (setq search-fun 'search-forward)
>               (setq start-pos (point-min))
>               (setq end-pos separator-pos)
>               (setq chars-forward-after-hit 1)
>               (setq maybe-beginning-of-line 'do-nothing) ))
>         (if (< position separator-pos)
>             (progn
>               (goto-char position)
>               (expand-abbrev) )
>           (goto-char start-pos) )
>         (funcall maybe-beginning-of-line)
>         (if (not (funcall search-fun ":" end-pos t))
>             (message-goto-body)
>           (progn
>             (forward-char chars-forward-after-hit)
>             (end-of-line) )))))

I would factorize out the body:

(require 'cl)
(defun iterate-header (back)
  "Unless BACK, go to the next header input field:
either on the same line as the present point,
or the next header below.
If the field has a string, put point to the string's right;
if the field is empty, put point so that typing will set the header,
without any prior cursor movement.
If you move from a header which has data, that data is expanded if
found to be an `abbrev-mode' abbreviation (possibly setup in
~/.mailrc), without need for a whitespace.
If there are no headers left, `message-goto-body';
if already in the body, goto the topmost header.
If BACK, do the same, only in reverse direction."
  (interactive)
  (let ((position (point)))
    (goto-char (point-min))
    (search-forward mail-header-separator)
    (let ((separator-pos (point)))
      (flet ((goto-to-header (search-fun start-pos end-pos chars-forward-after-hit maybe-beginning-of-line)
               (if (< position separator-pos)
                   (progn
                     (goto-char position)
                     (expand-abbrev))
                   (goto-char start-pos))
               (funcall maybe-beginning-of-line)
               (if (funcall search-fun ":" end-pos t)
                   (progn
                     (forward-char chars-forward-after-hit)
                     (end-of-line))
                   (message-goto-body))))
        (if back
            (goto-to-header 'search-backward separator-pos (point-min) 2 'beginning-of-line)
            (goto-to-header 'search-forward (point-min) separator-pos 1 'do-nothing))))))


Don't put spaces between openning or closing parentheses (you may put a
space between a closing and an opening one).  In general use paredit to
edit lisp code.

In general, try to avoid setq, you can only write better code if you can
avoid setq or setf.  Of course, setf is often needed and useful too, you
have to know when ;-)  But a (let (var) (setq var expr)) is almost never
a good expression.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.  
You know you've been lisping too long when you see a recent picture of George 
Lucas and think "Wait, I thought John McCarthy was dead!" -- Dalek_Baldwin


  reply	other threads:[~2013-06-15 12:58 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-15  4:00 Moving between headers in message-mode Emanuel Berg
2013-06-15 12:58 ` Pascal J. Bourguignon [this message]
2013-06-15 17:02   ` Emanuel Berg
2013-06-15 18:22     ` Pascal J. Bourguignon
2013-06-18 22:17       ` Emanuel Berg
2013-06-19  0:30         ` Emanuel Berg
2013-06-19 15:02 ` Stefan Monnier
2013-06-20  9:32   ` Emanuel Berg
2013-06-20 13:16     ` Stefan Monnier
     [not found]     ` <mailman.2075.1371734198.22516.help-gnu-emacs@gnu.org>
2013-06-20 18:17       ` Emanuel Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87vc5ffs49.fsf@kuiper.lan.informatimago.com \
    --to=pjb@informatimago.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).