* Moving between headers in message-mode @ 2013-06-15 4:00 Emanuel Berg 2013-06-15 12:58 ` Pascal J. Bourguignon 2013-06-19 15:02 ` Stefan Monnier 0 siblings, 2 replies; 10+ messages in thread From: Emanuel Berg @ 2013-06-15 4:00 UTC (permalink / raw) To: help-gnu-emacs 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) ))))) (defun iterate-header-back () "See `iterate-header'." (interactive) (iterate-header t) ) ; t = back (or up) (defun iterate-header-next () "See `iterate-header'." (interactive) (iterate-header nil) ) ; nil = forward (or down) (define-key message-mode-map (kbd "TAB") 'iterate-header-next) (define-key message-mode-map (kbd "<backtab>") 'iterate-header-back) -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-15 4:00 Moving between headers in message-mode Emanuel Berg @ 2013-06-15 12:58 ` Pascal J. Bourguignon 2013-06-15 17:02 ` Emanuel Berg 2013-06-19 15:02 ` Stefan Monnier 1 sibling, 1 reply; 10+ messages in thread From: Pascal J. Bourguignon @ 2013-06-15 12:58 UTC (permalink / raw) To: help-gnu-emacs 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 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-15 12:58 ` Pascal J. Bourguignon @ 2013-06-15 17:02 ` Emanuel Berg 2013-06-15 18:22 ` Pascal J. Bourguignon 0 siblings, 1 reply; 10+ messages in thread From: Emanuel Berg @ 2013-06-15 17:02 UTC (permalink / raw) To: help-gnu-emacs "Pascal J. Bourguignon" <pjb@informatimago.com> writes: First, thanks *a lot*, however, your feedback is above me, I must admit. Perhaps, you can elaborate the four points below a bit? Or perhaps point me to related material? > I would factorize out the body ... > > 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 ... > > 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. -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-15 17:02 ` Emanuel Berg @ 2013-06-15 18:22 ` Pascal J. Bourguignon 2013-06-18 22:17 ` Emanuel Berg 0 siblings, 1 reply; 10+ messages in thread From: Pascal J. Bourguignon @ 2013-06-15 18:22 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg <embe8573@student.uu.se> writes: > "Pascal J. Bourguignon" <pjb@informatimago.com> writes: > > First, thanks *a lot*, however, your feedback is above me, I must > admit. Perhaps, you can elaborate the four points below a bit? Or > perhaps point me to related material? > >> I would factorize out the body ... This is what I've done in the code I included in my message. Now, at first the local function was named body, but then it's good also to try to give more meaningful names to functions, even if they are local functions. Now, the first thing is that in simple cases, you could just use let: Instead of: (let (color) (if prefixp (setf color "red") (setf color "blue")) (set-foreground-color color) (set-cursor-color color)) write: (let ((color (if prefixp "red" "blue"))) (set-foreground-color color) (set-cursor-color color)) but in your case, you have a lot of variables that depend on the same condition, so it would be awkward to repeat it in all initialization expressions. Now one thing is that let is equivalent to an anonymous function call (see: http://home.pipeline.com/~hbaker1/MetaCircular.html ) (let ((a e1) (b e2) (c e3)) (do-something-with a b c) (and-something-with b c)) <=> ((lambda (a b c) (do-something-with a b c) (and-something-with b c)) e1 e2 e3) Of course, we could just give a name to the function, and call it: (defun body (a b c) (do-something-with a b c) (and-something-with b c)) (body e1 e2 e3) or: (if conditionp (body e11 e21 e31) (body e12 e22 e32)) But since your 'body' function is quite specific, there's no reason to give it a global name. Hence using flet, to give it a local name. >> Don't put spaces between openning or closing parentheses (you >> may put a space between a closing and an opening one). Have a look at: http://labs.ariel-networks.com/cl-style-guide.html http://mumble.net/~campbell/scheme/style.txt http://google-styleguide.googlecode.com/svn/trunk/lispguide.xml >> In general use paredit ... It lets you mostly ignore those style questions, since emacs does almost all the work for you. http://www.emacswiki.org/emacs/ParEdit http://www.emacswiki.org/emacs/PareditCheatsheet http://mumble.net/~campbell/emacs/paredit.el >> 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. setf does all that setq does, so you can just always use setf. and you cannot do that with setq: (let ((x (cons 1 2))) (setf (car x) 42) x) --> (42 . 2) this is equivalent to: (let ((x (cons 1 2))) (rplaca x 42) x) --> (42 . 2) But setf is an operator that mutates variables or data objects. Of course, the purpose of an editor is to mutate the state of a buffer, so we're quite far from functional programming. Nonetheless, if you write your emacs lisp code with a mostly functional programming style, it will be good, since this has a lot of advantages: http://www.emacswiki.org/emacs/FunctionalProgramming http://c2.com/cgi/wiki?AdvantagesOfFunctionalProgramming http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf -- __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 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-15 18:22 ` Pascal J. Bourguignon @ 2013-06-18 22:17 ` Emanuel Berg 2013-06-19 0:30 ` Emanuel Berg 0 siblings, 1 reply; 10+ messages in thread From: Emanuel Berg @ 2013-06-18 22:17 UTC (permalink / raw) To: help-gnu-emacs Did I correctly boil it down to: 1) Don't use setq 2) Don't use let let unless you complete the name-value association (i.e., don't set it up to be assigned later) (As for style, I haven't got around to that, will do. I *think* I picked up mine mostly from a book called "The Land of Lisp".) What do you think of: ;; separator (set-variable 'mail-header-separator "---") (set-face-attribute 'message-separator nil :foreground "black") (defun do-nothing () "Do nothing." () ) (defun iterate-header (separator-pos search-fun start-pos end-pos chars-forward-after-hit maybe-beginning-of-line) "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." (interactive) (let ((position (point))) (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) )))) (defun get-separator-pos () "Get the position of `mail-header-separator'." (save-excursion (goto-char (point-min)) (search-forward mail-header-separator) (point) )) (defun iterate-header-back () "See `iterate-header'." (interactive) (let ((separator-pos (get-separator-pos))) (iterate-header separator-pos 'search-backward separator-pos (point-min) 2 'beginning-of-line) )) (defun iterate-header-next () "See `iterate-header'." (interactive) (let ((separator-pos (get-separator-pos))) (iterate-header separator-pos 'search-forward (point-min) separator-pos 1 'do-nothing) )) (define-key message-mode-map (kbd "TAB") 'iterate-header-next) (define-key message-mode-map (kbd "<backtab>") 'iterate-header-back) -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-18 22:17 ` Emanuel Berg @ 2013-06-19 0:30 ` Emanuel Berg 0 siblings, 0 replies; 10+ messages in thread From: Emanuel Berg @ 2013-06-19 0:30 UTC (permalink / raw) To: help-gnu-emacs Wow, I found a huge bug! The whole search-and-skip is based on the position of the separator - but it doesn't take into account, that when you type (fill in the headers), that position changes! How embarrassing... I guess I have to determine the position of "---" before every new search, unless the buffer hasn't been changed. -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 2013-06-15 4:00 Moving between headers in message-mode Emanuel Berg 2013-06-15 12:58 ` Pascal J. Bourguignon @ 2013-06-19 15:02 ` Stefan Monnier 2013-06-20 9:32 ` Emanuel Berg 1 sibling, 1 reply; 10+ messages in thread From: Stefan Monnier @ 2013-06-19 15:02 UTC (permalink / raw) To: help-gnu-emacs > (setq mail-header-separator "---") Other than Pascal's recommendations, I'd recommend you simply use `rfc822-goto-eoh' to find the end of the header. Stefan ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 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> 0 siblings, 2 replies; 10+ messages in thread From: Emanuel Berg @ 2013-06-20 9:32 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier <monnier@iro.umontreal.ca> writes: > Other than Pascal's recommendations, I'd recommend you simply > use `rfc822-goto-eoh' to find the end of the header. Hihi, "simply" this, "simply" that - clearly, I didn't know about that function. But thanks, that's a huge improvement! But, the prefix - rfc822 - and the help section "This function obeys RFC822." - why did they think this to be so important, they actually filed a RFC, and not only that, the implementers (the writers of `simple.el') found it equally important, so they even put it as a prefix in the function *name*? Can I browse those RFCs somehow from Emacs? Does the numbering follow some system (like "e-mail stuff between 700 and 900") or is it just a unique identifier? -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Moving between headers in message-mode 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> 1 sibling, 0 replies; 10+ messages in thread From: Stefan Monnier @ 2013-06-20 13:16 UTC (permalink / raw) To: help-gnu-emacs > - why did they think this to be so important, they actually filed > a RFC, and not only that, the implementers (the writers of > `simple.el') found it equally important, so they even put it as a > prefix in the function *name*? https://www.ietf.org/rfc.html > Can I browse those RFCs somehow from Emacs? http://www.emacswiki.org/emacs/RFC Stefan ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <mailman.2075.1371734198.22516.help-gnu-emacs@gnu.org>]
* Re: Moving between headers in message-mode [not found] ` <mailman.2075.1371734198.22516.help-gnu-emacs@gnu.org> @ 2013-06-20 18:17 ` Emanuel Berg 0 siblings, 0 replies; 10+ messages in thread From: Emanuel Berg @ 2013-06-20 18:17 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier <monnier@iro.umontreal.ca> writes: >> - why did they think this to be so important, they actually >> filed a RFC, and not only that, the implementers (the writers >> of `simple.el') found it equally important, so they even put it >> as a prefix in the function *name*? > > https://www.ietf.org/rfc.html "Standard for the Format of ARPA Internet Text Messages" - 1982 (obsoleted by RFC 2822) :) -- Emanuel Berg - programmer (hire me! CV below) computer projects: http://user.it.uu.se/~embe8573 internet activity: http://home.student.uu.se/embe8573 ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-06-20 18:17 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-06-15 4:00 Moving between headers in message-mode Emanuel Berg 2013-06-15 12:58 ` Pascal J. Bourguignon 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
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.