Hi there, Today I'm going to write a small example on connecting the Sawfish window manager to the Emacs text editor.

Why might you want to do this? Well mostly I just wanted to further my usage of Emacs, and thought the idea of being able to clock in and out of tasks in org-mode whenever I change workspace or window would be pretty cool. Of course both Sawfish and Emacs make extensive use of the Lisp programming language) so it is a natural fit :)

To start off, you'll want to be using the Sawfish window manager, and you'll want to have emacs.jl somewhere in your lisp path. From there you can put something like the following in your ~/.sawfish/rc:

;; Require emacs.jl for emacs functions
(require 'emacs)

;; Define a hook to be run on workspace change, utilizes the emacs-eval function defined in emacs.jl
(define (my-enter-workspace-hook)
  (emacs-eval (format nil "(org-clock-in-on-workspace-change %S)" (nth current-workspace workspace-names))))

;; Add our hook!
(add-hook 'enter-workspace-hook my-enter-workspace-hook)

You will need to reload Sawfish for these changes to take effect (or you can eval them from Emacs).

Our hook makes Sawfish tell Emacs to run the org-clock-in-on-workspace-change function, passing the workspace name to it. We will define this now, open up your ~/.emacs and place this somewhere:

;; The function that Sawfish calls
(defun org-clock-in-on-workspace-change (workspace)
  (org-clock-out t) ; The t will silence the error that appears if no task is clocked
  (org-map-entries ; Loop over org headings
   'org-clock-in ; Clock in to this task ..
   workspace 'agenda)) ; .. if the tag has same name as current workspace
; Now press C-x C-e here to load this function into emacs

Now that this is done, we have what is needed for this to function, and in fact, if all has gone well, Sawfish should now be communicating and running this Emacs function each time you switch workspace!

Now, to make this useful, open up one of your agenda files, and add a tag to it, such as :Web: or :Emacs: etc. When that workspace is switched to in Sawfish, the task will be clocked in and out of automatically!

Hope you find this useful, I'm sure I will! :D

Edit: Changed to use workspace names instead of number. This can be coupled with the function below to quickly rename workspaces:

;; Bind this to a key like (rename-workspace current-workspace (prompt #:title "Workspace Name:"))
(define (rename-workspace n name)
  "Rename the Nth workspace to NAME"
  (setq workspace-names
        (let ((i -1))
          (mapcar #'(lambda (item)
                      (if (= n (setq i (1+ i)))
                        item)) workspace-names))))

(Maybe) Related posts: