5

Some years ago, I was working on a personal project that seemed to work best with Emacs as the user interface, and Common Lisp (SBCL) as the back-end. The accepted answer on How to use SLIME as a proxy between Common Lisp program and Emacs Lisp? talks about how to move code from Common Lisp to Emacs, but I needed to work in the other direction, which the macro below accomplishes. At the time when I wrote this, clsql seemed more mature and usable than any existing Emacs database system. I was also interested in experimenting with elephant. If I was to rewrite the code these days I might use EmacSQL directly within Emacs to connect to the database. Or if I felt like being fancy I might try to bridge to Clojure rather than Common Lisp, and make use of the interesting ideas of software transactional memory, and then try to persist that.

These comments serve to underscore the point that it is potentially useful to bridge to different programming languages for different purposes.

The question I'd like to ask is: Are other people currently doing this sort of bridging, getting Emacs to interoperate programmatically at run time with other platforms (not just over a web API, comint buffer, or shell-command) and if so, how are you going about it? What kind of Emacs-centric applications are you building?

I include the outline of my CL bridge for context.

(defmacro Defun (name arglist &rest body)
  (declare (indent defun))
  `(defun ,name ,arglist
     (let* ((outbound-string
             (translate-emacs-syntax-to-common-syntax
              (format "%S"
                      (append
                       (list
                        (append (list 'lambda ',arglist)
                                ',body))
                       (mapcar
                        (lambda (arg) `',arg)
                        (list
                         ,@(remove-if
                                 (lambda (testelt)
                                   (eq testelt
                                 '&optional))
                                 arglist)))))))
            (returned-string
             (second
              ;; we now specify the right package!
              (slime-eval
               (list 'swank:eval-and-grab-output
                     outbound-string)
               :arxana))))
       (process-slime-output returned-string))))

With these helper functions:

(defun translate-emacs-syntax-to-common-syntax (str)
  (with-temp-buffer
    (insert str)
    (dolist (swap '(("(\\` " "`")
                    ("(\\\, " ",")))
      (goto-char (point-min))
      (while (search-forward (first swap) nil t)
        (goto-char (match-beginning 0))
        (forward-sexp)
        (delete-char -1)
        (goto-char (match-beginning 0))
        (delete-region (match-beginning 0)
                       (match-end 0))
        (insert (second swap))))
    (buffer-substring-no-properties (point-min)
                                    (point-max))))

(defun process-slime-output (str)
  (condition-case nil
      (let ((read-value (read str)))
        (if (symbolp read-value)
            (read (downcase str)))
        (nsubst nil 'NIL read-value))
    (error str)))

In the end, what is achieved is that I can write functions like this, defined in Emacs, but whose bodies are evaluated on Common Lisp:

(Defun article (name contents &optional heading)
  (let ((coordinates (add-triple name
                                 "has content"
                                 contents)))
    (when theory (add-triple coordinates "in" heading))
    (when place (if (numberp place)
                    (put-in-place coordinates place)
                  (put-in-place coordinates)))
    coordinates))
  • 4
    How about posing one or more less broad questions? SE is not the best place for discussion in general, let alone wide-ranging discussion. – Drew Jun 4 '15 at 14:15
  • I honed the question a bit to make it more clear. I'm not trying to start a philosophical discussion, but am looking for interesting examples of Emacs-centric integration work. A valid answer could be a link to a project, for example github.com/novoid/Memacs -- ideally with a little more detail on the bridge or bridges used, as in my question. – Joe Corneli Jun 4 '15 at 17:12
  • Another option would be using an Emacs written in CL for tighter integration, such as climacs or hemlock. – wasamasa Jun 4 '15 at 17:22
  • 2
    It seems hard to justify using a Common Lisp based variant of Emacs since that would presumably render all of the awesome elisp addons people have written incompatible. – Qudit Jun 4 '15 at 17:42
  • 1
    The advantage of GuileEmacs over the others is that (if I recall correctly), it aims to be backwards compatible with elisp, so all of the millions of lines of awesome extensions don't have to be rewritten. – Qudit Jun 5 '15 at 22:50
3

The examples I'm aware of use either XEmacs or SXEmacs (a fork of XEmacs) and their module/FFI support to extend them with C or existing C functions.

  • wand-mode: Combines FFI and the imagemagick library for simple image manipulation, such as red-eyes removal.

  • xwem: Emacs as window manager. Nuff said.

I recall Steve Youngs (the SXEmacs maintainer) speaking of even crazier things, such as putting mplayer or Webkit into it, but don't have anything asides from IRC logs to show as proof. Generally I'm afraid extension of Emacs in such ways is an endeavor only a few motivated individuals (yes, even less than usual) partake in, so that's why there's so little material on it. On the upside, it means that you could be building the next Emacs killer app!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.