How could I use w3m to render HTML content in RMAIL messages? - email

How could I use w3m or other to display HTML content inline in RMAIL messages or, at least, open its MIME part in a external web browser?
The only solution I found is in EmacsWiki but it is a 1996's code that didn't work for me. At least on Emacs 24.

Ok. How about this?
(defun buffer-html-to-w3m ()
"View HTML in the current rmail using W3M.
You must have W3M installed for this to work."
(interactive)
(let ((subject (mail-fetch-field "Subject")))
(when
(string-match-p
"text/html.*"
(mail-fetch-field "Content-type"))
(save-excursion
(goto-char (point-min))
(let ((pt (re-search-forward "\n<html>" nil t)))
(goto-char pt)
(let ((buf (get-buffer-create (concat "*rmail-" subject "*"))))
(shell-command-on-region
pt (or
(re-search-forward "</html>" nil t)
(point-max))
"w3m -T text/html" buf)
(switch-to-buffer-other-window buf)
(view-mode)))))))
I'm not sure about the name and I only tried one of your emails but, for me, this works.
I put your message into rmail-mode and then wrote this function, which finds the html and pipes it through W3M.
You're switched to the resulting buffer and we put it in view-mode so you can just "q" to stop looking at it.

I'm going to take a shot at this using w3m-emacs.

Related

How can I send messages with 'format=flowed' with the notmuch message client?

I use the latest notmuch emacs client to compose and read my email. (They are sent via msmtp, and pulled with mbsync.)
I would like to have all my newly created messages to be formatted with format=flowed. All answers to this question I could find in the internet refer to Gnus.
Any ideas if it is possible to activate this feature with notmuch-message, or how to add it via elisp?
The following works:
(require 'messages-are-flowing)
(add-hook 'message-mode-hook #'messages-are-flowing-use-and-mark-hard-newlines)
There is no need to use Gnus to send mail.
I wrote some custom elisp to do this:
(defun as-format-as-flowed-text ()
"Format the buffer as flowed text according to RFC 2646.
This ensures that appropriate lines should be terminated with a
single space, and that \"> \" quoting prefixes are replaced with
\">\". Operates on the current region if active, otherwise on
the whole buffer."
(interactive)
(let ((start (if (use-region-p) (region-beginning) (point-min)))
(end (if (use-region-p) (region-end) (point-max))))
(save-excursion
(goto-char start)
;; Ensure appropriate lines end with a space
(while (re-search-forward "^\\(>+ ?\\)?\\S-.*\\S-$" end t)
(replace-match "\\& " t))
;; Replace "> " quoting prefixes with ">"
(goto-char start)
(let ((eol)
(eolm (make-marker)))
(while (setq eol (re-search-forward "^>.*" end t))
(set-marker eolm eol)
(goto-char (match-beginning 0))
(while (looking-at ">")
(if (looking-at "> ")
(replace-match ">")
(forward-char)))
(goto-char (marker-position eolm)))))))
(bind-key "M-s M-m" 'as-format-as-flowed-text)
(You can find the permanent home for this here. I'm pretty sure it could be written more elegantly; suggestions or even pull requests are very welcome.)
A few minutes after writing it, I discovered a certain amount of native support for format=flowed within gnus. Unfortunately that functionality does not seem to be immediately reusable outside gnus at the time of writing.
I have just created https://www.emacswiki.org/emacs/FormatFlowed as a central portal in order to try to collect info on this topic in a single place.

How to write a function that notify me when someone mention me on irc in Emacs

I have this function
(defun mention-notify (match-type nickuserhost msg)
(interactive)
(if (and (eq match-type 'current-nick)
(eq (string-match "^-NickServ-" msg) nil) ;this is probably not needed
(eq (string-match "^\\*\\*\\*" msg) nil))
(progn
(shell-command "mpg123 -q /home/kuba/Pobrane/beep-8.mp3")
(notify "ERC" msg))))
(add-hook 'erc-text-matched-hook 'mention-notify)
But it execute command even it message start from ***. What I'm doing wrong here? How this function should look like?
I read that page but it only show how to send notification for all mentions, even from server. like:
*** Users on #<chanel>: jcubic...
or
*** jcubic has changed mode for jcubic to +i
It seams that when I check for 'current-nick - msg is not the whole message but substring containing my nick, I try to check for keyword instead of current-nick and check if my nick that I always use appear in the text but using keyword doesn't work at all.
You might also want to look at Sauron:
http://www.emacswiki.org/emacs/Sauron
I copied erc-match-message function from erc.el file into my .emacs file and I added one flag to hook
(run-hook-with-args
'erc-text-matched-hook
(intern match-type)
(or nickuserhost
(concat "Server:" (erc-get-parsed-vector-type vector)))
message
(string-match "^\\*\\*\\*"
(buffer-substring (point-min) (point-max)))))))
last flag is set if message is erc system message - starts with *** so now I can check this flag in my hook
(defun mention-notify (match-type nickuserhost msg notification)
(interactive)
(if (and (eq match-type 'current-nick)
(not notification))
(progn
(shell-command "mpg123 -q /home/kuba/Pobrane/beep-8.mp3")
(notify "ERC" msg))))
UPDATE I also didn't want to recive message from -NickServ- so I add this
(run-hook-with-args
'erc-text-matched-hook
(intern match-type)
(or nickuserhost
(concat "Server:" (erc-get-parsed-vector-type vector)))
message
(let ((whole-msg (buffer-substring (point-min) (point-max))))
(or (string-match "^-NickServ-" whole-msg)
(string-match "^\\*\\*\\*" whole-msg)))))))
A quick google search for "erc mention notify" yields a bunch of example code to do exactly what you want.

Why doesn't font-lock-fontify-buffer work from elisp when it works from the minibuffer?

So I'm hacking up some elisp to test a web service, and I'm running into trouble with syntax highlighting. I'm using url-retrieve-synchronously to get an HTTP response, then editing the text to get down to just the XML I need to see. Unfortunately, syntax highlighting doesn't work in the returned buffer, even though I've set it to nxml-mode and used "font-lock-fontify-buffer" in the script. However, if I do "M-x font-lock-fontify-buffer", the highlighting works as I would expect. Is there some difference between using it in elisp and from inside emacs?
Here are the relevant parts of the script I'm putting together. I admit up front that this is the first elisp scripting I've ever done, and I'm probably doing things in a ludicrously incorrect manner, but it's all worked thus far.
(defun modality-http-request (url args request-type)
(let ((url-request-method request-type)
(url-request-extra-headers '(("Content-Type" . "application/x-www-form-urlencoded")))
(url-request-data
(mapconcat (lambda (arg)
(concat (url-hexify-string (car arg))
"="
(url-hexify-string (cdr arg))))
args
"&")))
(url-retrieve-synchronously url)))
(defun modality-http-get (url args)
(modality-http-request url args "GET"))
(defun modality-http-post (url args)
(modality-http-request url args "POST"))
(defun test-modality (test)
(interactive "s\Test: ")
(let ((buffer (modality-http-get (concat (get-modality-path) test) nil)))
(set-buffer buffer)
(setq modality-beginning (point))
(forward-paragraph)
(next-line)
(beginning-of-line)
(setq modality-end (point))
(delete-region modality-beginning modality-end)
(bf-pretty-print-xml-region)
(switch-to-buffer buffer)
(font-lock-fontify-buffer)))
(defun bf-pretty-print-xml-region ()
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char (point-min))
(while (search-forward-regexp "\>[ \\t]*\<" nil t)
(backward-char) (insert "\n"))
(indent-region (point-min) (point-max))
))
URL uses temporary/internal buffers (recognized by the fact that their name starts with a space). They're plain normal, but some functions treat them specially: font-lock will not be activated, and the buffer will usually not be shown to the user (e.g. C-x b TAB will not show those buffers).
So either rename the buffer before enabling font-lock, or copy the text you need into another buffer whose name doesn't start with a space.

Is there a urlview (a la mutt) for gnus? Or just elisp for extracting urls?

I switched from mutt to gnus and would like to extract urls from emails and be able to launch a new buffer that contains all urls in a given email. Urlview does this for mutt as a frame of reference for what I am looking for.
I wrote the following and tested it to work on a couple of articles. Maybe it will be a good starting point for you.
(defun gnus-article-extract-url-into-buffer ()
(interactive)
(let ((simple-url-regexp "https?://")
urls)
(save-excursion
;; collect text URLs
(while (search-forward-regexp simple-url-regexp nil t)
(when-let (url (thing-at-point 'url))
(setq urls (cons url urls))))
(beginning-of-buffer)
;; collect widget URLs
(while (not (eobp))
(goto-char (next-overlay-change (point)))
(when-let (link (get-text-property (point) 'gnus-string))
(and (string-match simple-url-regexp link)
(setq urls (cons link urls))))
(goto-char (next-overlay-change (point)))))
(when urls
(switch-to-buffer-other-window "*gnus-article-urls*")
(dolist (url urls)
(insert url))
(beginning-of-buffer))))
I should clarify that this is intended to be run from within the article buffer.
Also, I may have missed the point by taking what you said literally about launching a new buffer containing the urls, in which case you can change the last form to:
(when urls
(dolist (url urls)
(browse-url url)))
Or, Tyler's approach is simpler if you don't need to parse widget urls.
I don't think that function is built-in. The following code will do what you want. From the summary buffer, call M-x urlview, or bind it to a convenient key. The save-excursion wrapper should drop you back in the summary buffer, but for some reason it leaves you in the article buffer. Just hitting the h key will put you back, but you shouldn't need to do that. Maybe someone else can clarify that part?
(defun urlview ()
(interactive)
(save-excursion
(gnus-summary-select-article-buffer)
(beginning-of-buffer)
(while
(re-search-forward "https?://" nil t)
(browse-url-at-point))))
Edit: Joseph's answer works for both http and https, which I had overlooked. So I swiped that part of his code.

Emacs Lisp buffer not running font lock mode until opened by user

My problem is I am opening a buffer using (set-buffer (find-tag-noselect (current-word))) and then I try to copy some text out of that buffer. The text that I get back has only the properties (fontified nil). find-tag-noselect automatically opens the buffer found in the TAGS file but it seems it does not run the font lock mode over it. When I manually switch to this buffer after it has been opened and then run the function again when it copies the text it has all the correct text properties attached. So what do I need to do to have this buffer completely initialized so that the correct syntax highlighting will be copied in?
(defvar newline-string "
")
(defun get-initial-indent-regexp-python()
"Gets the initial amount of spaces for the function we are looking at, does not account for tabs"
(concat "^" (get-current-indent-string) (concat "[^ #" newline-string "]")))
(defun get-end-of-function-python(spaces-regex)
"Gets the point at the end of a python block"
(save-excursion
(forward-line 1)
(while (and (not (looking-at spaces-regex)) (equal (forward-line 1) 0)))
(point)))
(defun get-point-at-end-of-function ()
"This might be better served checking the major mode."
(setq extension (file-name-extension (buffer-file-name)))
(if (equal extension "py")
(get-end-of-function-python (get-initial-indent-regexp-python))))
(defun inline-function ()
"Must change to overlays, be able to toggle visibility"
(interactive)
(let (text indent-string)
; clean all overlays without attached buffer
(save-excursion
(set-buffer (find-tag-noselect (current-word)))
(setq text (buffer-substring (point) (get-point-at-end-of-function))))
(setq text (concat newline-string text))
(save-excursion
(move-end-of-line nil)
(let (overlay)
(setq overlay (make-overlay (point) (+ (point) 1) (current-buffer)))
(overlay-put overlay 'display text)
(setq inline-func-overlays (cons overlay inline-func-overlays))))))
What's happening is that font-lock is done on-the-fly, so only the displayed parts of the buffer get "fontified". If you want/need to overrule this optimization, you need different functions depending on the circumstance (depending on how font-lock happens to be configured). We should add a new font-lock-ensure-fontified function for that, but in the mean time, you can take ps-print-.el as an example:
(defun ps-print-ensure-fontified (start end)
(cond ((and (boundp 'jit-lock-mode) (symbol-value 'jit-lock-mode))
(jit-lock-fontify-now start end))
((and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode))
(lazy-lock-fontify-region start end))))
I'm not exactly sure what you're trying to do, but set-buffer does not display the buffer, so its effect ends when the current command terminates. It's generally useful only for temporary buffer switches inside a function and I guess this is the reason it doesn't run font-lock on the buffer. When you manually go to the buffer you're probably using a different function - switch-to-buffer.
Try explicitly calling 'font-lock-fontify-buffer'.