For Mac OS X there is separate package Growl, that provides notification services for different programs. Notifications are represented as floating windows, containing text and icon. There notifications could be very useful for some things, like notifications from org-mode.

After some search, I found information how I can output notifications using AppleSript interface to Growl. To make this work, you need to perform two things — first you need to register your application and notifications types, produced by this application, and then you can send notifications to Growl.

To register application you will need following script, that declares notification types and register them, together with application in Growl:1

tell application "GrowlHelperApp"
 -- Declare a list of notification types
 set the allNotificationsList to {"Emacs Notification"}

 -- Declare a list of active notifications.  If some of them
 -- isn't activated, user can do this later via preferences
 set the enabledNotificationsList to {"Emacs Notification"}

 -- Register our application in Growl.
 register as application "Aquamacs Emacs" all notifications allNotificationsList \
    default notifications enabledNotificationsList \
    icon of application "Aquamacs Emacs"
end tell

You can execute this script with osascript command from command line, or put it into Script Editor and execute it directly. After registration, user can customize look of the registered notification via Applications tab at preference pane of Growl.

And after registration, user can send notifications with following script, that is a base of our Emacs's interface to Growl.

        tell application "GrowlHelperApp"
                notify with name "Emacs Notification" title "Emacs alert" \
       description "Message!!!" application name "Aquamacs Emacs"
        end tell

This script also could be executed via osascript, and it'll output message Message!!! with title Emacs alert, but to output non-Latin1 symbols from AppleScript, you'll need to encode them using UTF-16 and represent them as hexadecimal string, so we'll going to add special code, that will recode message strings to corresponding format.

To interact with AppleScript from Emacs we'll could use do-applescript function, but I found, that it doesn't properly handle multibyte symbols « and », that are used to specify text in multi-byte encoding. So we'll form script in temporary file, and than execute it with osascript, and delete the temporary file. This executed with following function:

(defun output-to-growl (msg)
        (let ((fname (make-temp-file "/tmp/growlXXXXXX")))
                (with-temp-file fname
                        (setq coding-system-for-write 'utf-16)
                        (insert (format "tell application \"GrowlHelperApp\"
     notify with name \"Emacs Notification\" title \"Emacs alert\" \
       description «data utxt%s» as Unicode text \
       application name \"Aquamacs Emacs\"
   end tell"  (osd-text-to-utf-16-hex msg))))
                (shell-command (format "osascript %s" fname))
                (delete-file fname)))

To proper output of strings, containing Cyrillic & other non-Latin1 symbols, AppleScript requires, that data should be encoded in UTF-16, and presented as string data utxtXXXXXX, where utxtXXXXXXX — hexadecimal representation of corresponding bytes of string in UTF-16 encoding. To do this task, I wrote function osd-text-to-utf-16-hex, that is called from output-to-growl function:

(defun osd-text-to-utf-16-hex (text)
        (let* ((utext (encode-coding-string text 'utf-16))
                                 (ltext (string-to-list utext)))
                (apply #'concat
                 (mapcar (lambda (x) (format "%02x" x)) ltext))))

And that's all. Now you can call output-to-growl from any place. I use it to get notifications from org-mode.

1. I need to mention, that long lines were split with \ just to get proper formatting on the screen. In script, you need to combine them into one long line!

Last change: 25.09.2021 14:14

blog comments powered by Disqus