2

Under GNU Emacs 24.4.1, in Message Mode, C-c C-w runs message-insert-signature, which inserts the file message-signature-file at the end of the buffer, if such a signature is not already present.

How can I extend the function message-insert-signature so that to maintain its current functionalities but add one such that, when prefixing the command with C-u (which gives C-u C-c C-w), the signature is rather inserted at point (e.g. for mails where there are attachments which I wish to be AFTER the signature)?

It would be easy to define a function to insert "\n-- \n" and perform (insert-file-contents signature-file) at point, and to bind it to a new key combination, but my muscle memory is set to C-u C-c C-w from my previous use of VM, and I thought it could be the same for other users.


EDIT:

The code of the function message-insert-signature bound by default to C-c C-w is interactive with parameters (&optional force), which suggests that one could "force" the signature to be inserted, but I don't understand how the (interactive (list 0)) works:

(defun message-insert-signature (&optional force)
  "Insert a signature.  See documentation for variable `message-signature'."
  (interactive (list 0))
  (let* ((signature
      (cond
       ((and (null message-signature)
         (eq force 0))
        (save-excursion
          (goto-char (point-max))
          (not (re-search-backward message-signature-separator nil t))))
       ((and (null message-signature)
         force)
        t)
       ((functionp message-signature)
        (funcall message-signature))
       ((listp message-signature)
        (eval message-signature))
       (t message-signature)))
     signature-file)
    (setq signature
      (cond ((stringp signature)
         signature)
        ((and (eq t signature) message-signature-file)
         (setq signature-file
               (if (and message-signature-directory
                ;; don't actually use the signature directory
                ;; if message-signature-file contains a path.
                (not (file-name-directory
                      message-signature-file)))
               (expand-file-name message-signature-file
                         message-signature-directory)
             message-signature-file))
         (file-exists-p signature-file))))
    (when signature
      (goto-char (point-max))
      ;; Insert the signature.
      (unless (bolp)
    (insert "\n"))
      (when message-signature-insert-empty-line
    (insert "\n"))
      (insert "-- \n")
      (if (eq signature t)
      (insert-file-contents signature-file)
    (insert signature))
      (goto-char (point-max))
      (or (bolp) (insert "\n")))))
J..y B..y
  • 158
  • 2
  • 9
  • From what I understand, your question is more about how to bind something to the C-u prefix, rather than how to write the actual function. Is that correct? – Malabarba Apr 02 '15 at 20:47
  • It is my understanding that the C-u prefix to any short cut X calling function F should be "caught" by the function F, hence the question? – J..y B..y Apr 06 '15 at 18:51
  • Yes. I mean that your question is saying *"I know how to insert signature. How can I capture C-u in a function"*. Meanwhile, your title is asking *"how do I insert signature"*. You should change the title to match the question. – Malabarba Apr 06 '15 at 19:07
  • Agreed: made the title more explicit. – J..y B..y Apr 06 '15 at 19:22

2 Answers2

5

What you need to do is write a new interactive function that receives the optional prefix argument and runs either the "insert here" or "insert at bottom" functions. For your function to receive the prefix, it needs to have (interactive "P"). A single C-u prefix will be received as the list (4). Below is the general sort of thing you have to do.

(defun my/insert-signature (&optional arg)
  (interactive "P")
  (if (equal arg '(4))
      (progn
        (insert "\n--\n")
        (insert-file-contents mail-signature-file))
    (message-insert-signature)))
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
erikstokes
  • 12,686
  • 2
  • 34
  • 56
  • 2
    Instead of `(equal arg '(4))` it's best to just use `arg` itself. This way it will also work with numeric prefixes (which might be more convenient to time depending on the keybind). – Malabarba Apr 06 '15 at 19:10
0

Here is my solution, based on the original function called by C-c C-w in message mode, message-insert-signature, and on @erikstokes's answer and @malabarba's comment, followed by the instruction to bind it to C-c C-w.

It works as I wished: it inserts the signature at the end of the email via C-c C-w, and at point when called via C-u C-c C-w. As the original function, it does not insert the signature if one is already present in the email.

(defun jyby/insert-signature (&optional arg)
  "Insert a signature.
  If prefixed with C-u, inserts it at point,
  otherwise inserts it at the end of the buffer."
  (interactive "P")
  (let* ((signature
      (cond
       ((null message-signature)     
        (save-excursion
          (goto-char (point-max))
          (not (re-search-backward message-signature-separator nil t))))
       ((null message-signature) t)
       ((functionp message-signature)
        (funcall message-signature))
       ((listp message-signature)
        (eval message-signature))
       (t message-signature)))
     signature-file)
    (setq signature
      (cond ((stringp signature)
         signature)
        ((and (eq t signature) message-signature-file)
         (setq signature-file
               (if (and message-signature-directory
                ;; don't actually use the signature directory
                ;; if message-signature-file contains a path.
                (not (file-name-directory
                      message-signature-file)))
               (expand-file-name message-signature-file
                         message-signature-directory)
             message-signature-file))
         (file-exists-p signature-file))))
    (when signature 
     (save-excursion
      (if (not arg)
        (goto-char (point-max))
      )
      ;; Insert the signature.
      (unless (bolp)
    (insert "\n"))
      (when message-signature-insert-empty-line
    (insert "\n"))
      (insert "-- \n")
      (if (eq signature t)
      (insert-file-contents signature-file)
    (insert signature))
      (goto-char (point-max))
      (or (bolp) (insert "\n"))))))

(local-unset-key (kbd "C-c C-w"))  (local-set-key (kbd "C-c C-w") 'jyby/insert-signature)    

I might modify it later so that it ignores existing signatures when called with a prefix.

J..y B..y
  • 158
  • 2
  • 9