6

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))
Joe Corneli
  • 1,786
  • 1
  • 14
  • 27
  • 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 04 '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 https://github.com/novoid/Memacs -- ideally with a little more detail on the bridge or bridges used, as in my question. – Joe Corneli Jun 04 '15 at 17:12
  • Another option would be using an Emacs written in CL for tighter integration, such as [climacs](http://dept-info.labri.fr/~strandh/Teaching/PdP/2004-2005/climacs-en.html) or [hemlock](http://www.cons.org/cmucl/hemlock/index.html). – wasamasa Jun 04 '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 04 '15 at 17:42
  • I think [pymacs](https://github.com/pinard/Pymacs) is something like this for python. Unfortunately it was pretty buggy when I tried to use it a few years ago, and it seems to have died since then. – dshepherd Jun 04 '15 at 18:39
  • dshepherd, thanks, that certainly seems like it could be an answer to the question if you or another pymacs user would like to flesh it out. – Joe Corneli Jun 04 '15 at 20:34
  • http://emacswiki.org/emacs/GuileEmacs is an interesting option, similar to @wasamasa's comment. Relative to the theme of my question, this example is particularly interesting in light of the following: _One of the goals of Guile is to allow other languages to be used alongside Scheme, such that Guile would effectively be a language-neutral runtime environment._ - https://en.wikipedia.org/wiki/GNU_Guile – Joe Corneli Jun 05 '15 at 20:55
  • one more reimplementation-in-progress, in Clojure... https://github.com/hraberg/deuce ... but maybe we need a "Emacs reimplementations" question to collect these, because that's not what I was really asking about in the OP. – Joe Corneli Jun 05 '15 at 21:39
  • 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 05 '15 at 22:50
  • An actual example: https://github.com/skeeto/elisp-ffi @wasamasa makes some comments here, http://nullprogram.com/blog/2014/04/26/ maybe those could be expanded into an answer? – Joe Corneli Jun 07 '15 at 02:00

1 Answers1

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!

wasamasa
  • 21,803
  • 1
  • 65
  • 97