help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Moving between headers in message-mode


From: Pascal J. Bourguignon
Subject: Re: Moving between headers in message-mode
Date: Sat, 15 Jun 2013 14:58:14 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

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 via email to

[Prev in Thread] Current Thread [Next in Thread]