## Clickable telephone numbers in mu4e messages

| categories: emacs | tags: | View Comments

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 #return
end 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.

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

"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.

## 2 Clickable 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
xxx.xxx.xxx
xxxxxxxxxx
xxx-xxx-xxxx"
(interactive)
(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")

 highlight-phone-numbers

## 3 Phone 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
(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"))))))))

## 4 Summary

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.