Clickable telephone numbers in mu4e messages

2015-11-09 14:01:39来源:作者:The Kitchin Research Group人点击

We recently updated our university phone system to a VoIP system that uses Cisco Jabber. I am excited about that because finally I can make phone calls from Emacs with a little applescript automation! So, spoiler alert, this post mostly only applies to Macs, unless you know how to automate a Jabber client to make calls. How to make the telephone numbers clickable is general though, and could be used to do other things as well.

(defun cisco-call (phone-number) (interactive "sPhone number: ") (do-applescript (format "tell application /"Cisco Jabber/" activate tell application /"System Events/" to keystroke /"n/" using {shift down, command down} tell application /"System Events/" to keystroke /"%s/" tell application /"System Events/" to key code 36 #returnend tell" phone-number))) cisco-call

I would like to go a step further, and make clickable phone numbers in my Emacs buffers. Let's take a look at some options.

1org-mode phone link

This is a no-brainer approach. We can define an org-mode link that runs the cisco-call function.

(org-add-link-type "phone" (lambda (phone-number) (cisco-call phone-number))) lambda (phone-number) (cisco-call phone-number)

This makes simple link that just calls the number in the path of the link.

2Clickable text with button-lock

I have used the button-lock package very often to make clickable text. Here we use it to highlight phone numbers matching a regular expression that seems to match most US numbers. This seems to work great in org-mode buffers.

(require 'rx)(defvar highlight-phone-numbers nil "Button for `highlight-phone-numbers'")(defun highlight-phone-numbers () "Make phone numbers of the following types clickable: (xxx) xxx-xxxx xxxxxxxxxx xxx-xxx-xxxx" (interactive) (let ((inhibit-read-only t)) (setq highlight-phone-numbers (button-lock-set-button (rx ;; optional () around area code (optional "(") (= 3 digit) (optional ")") ;; delimiters (or (optional "-") (optional ".") (optional " ")) (= 3 digit) (or (optional "-") (optional ".") (optional " ")) (= 4 digit)) (lambda () (interactive) (cisco-call (get-surrounding-text-with-property 'phone-number))) :face '((:background "Darkolivegreen2") (:underline t)) :help-echo "click to call" :keyboard-binding (kbd "RET") :additional-property 'phone-number))))(add-hook 'text-mode 'highlight-phone-numbers) highlight-phone-numbers 3Phone numbers in mu4e messages

For some reason, the button-lock package doesn't seem to work in mu4e message buffers, Maybe it is because . The highlight-regexp package does work though, so for these special buffers we use a new approach. We will just put text properties where we want them, and use those properties to make the text clickable.

The messages are in read-only buffers, but we can inhibit that so we can modify the properties. All we need to do is create a little key map as a copy of the existing map, define some keys on it, then search through the buffer adding properties to every phone number we find. I wrote a function that does that, and put that function in a hook to run each time I open a message. Whammo, now I have clickable phone numbers in email! It works pretty well for me.

(defface mu4e-phone-face '((t (:foreground "SteelBlue4" :background "Darkolivegreen2" :underline t))) "Phone number directive face.")(defun mu4e-highlight-phone-numbers () "Make phone numbers clickable in mu4e-view buffers." (interactive) (let ((phone-regex (rx ;; optional () around area code (optional "(") (= 3 digit) (optional ")") ;; delimiters (or (optional "-") (optional ".") (optional " ")) (= 3 digit) (or (optional "-") (optional ".") (optional " ")) (= 4 digit)))) (save-excursion (let ((inhibit-read-only t)) (goto-char (point-min)) (while (re-search-forward phone-regex nil t) (let ((map (copy-keymap mu4e-view-mode-map)) (start (match-beginning 0)) (end (match-end 0))) ;; set file to be clickable to open the source (define-key map [mouse-1] `(lambda () (interactive) (cisco-call ,(match-string 0)))) ;; let letter c also make the call (define-key map "c" `(lambda () (interactive) (cisco-call ,(match-string 0)))) (set-text-properties start end `(local-map, map face mu4e-phone-face mouse-face highlight help-echo "mouse-1: click to call"))))))))(add-hook 'mu4e-view-mode-hook 'mu4e-highlight-phone-numbers) 4Summary

That works pretty well for me overall. The phone number regex is not perfect, e.g. it makes any 10 digit number clickable, and it doesn't recognize international numbers. I am not sure I can call those through the Jabber client anyway. This is purely convenience for me to easily make calls from emails, or other kinds of documents I might read in Emacs.

I don't use phone calls very often, but an interesting thing might be to open a phone log in org-mode, or open the contact that has that phone number to log that you called them, and provide some notes for them. Alternatively, open a new capture for a phone log that could be refiled later.

Copyright (C) 2015 by John Kitchin. See theLicense for information about copying.

org-mode source

Org-mode version = 8.2.10