pymacs! :-)
François Pinard
pinard at iro.umontreal.ca
Tue Sep 4 11:14:13 EDT 2001
Hello, my friends.
It was an holiday yesterday, and I dived into writing `pymacs'. This tool
allows for using Python as if it were part of Emacs LISP. I merely revisited
a good idea from Cedric Adjih, who published `pyemacs' about three years
ago, and spiced with a few simplification ideas on my own. It seems to work!
The whole thing currently stands in three files:
pymacs.el (176 lines) the Emacs side
pymacs.py (124 lines) the Python side
pymacs-services (11 lines) a small bootstrap
Well, well, there also are 3 autloload lines in my ".emacs" file :-).
The thing being simpler, I removed the `e', so `pyemacs' became `pymacs'!
Here is a short example. In Emacs "*scratch*", I can do:
---------------------------------------------------------------------->
(import-python "os")
nil
(os-listdir ".")
[".nnmail-cache" "wdiff" "emacs" "struct" "dmf" "suse" "perl2py" "po-mode" ".gdb_history" ".xsession-errors" "po-utils" ".kermit" ...]
----------------------------------------------------------------------<
So, I may import a module directly within Emacs, after which I can refer to
it using some prefix. A second argument to `import-python' would allow
for choosing a specific prefix. That `os-listdir' command returns an
Emacs LISP vector, which is consequently usable on the Emacs side.
In LISP, I also gave me some more direct tools:
(exec-python "PYTHON-STATEMENTS")
(eval-python "PYTHON-EXPRESSION")
(apply-python FUNCTION ARGUMENTS)
>From the Python side, I may also call Emacs for help:
eval_lisp("LISP-EXPRESSION")
This last function is only usable when the original call, or control of
initiative, comes from Emacs; it would not allow an autonomous Python
program to call Emacs as a sub-routine. Here is a more hairy example:
---------------------------------------------------------------------->
(eval-python "eval_lisp('(eval-python \"`2L**111`\")')")
"2596148429267413814265248164610048L"
----------------------------------------------------------------------<
Here, I'm asking Emacs to ask Python to ask Emacs to ask Python for a simple
bignum computation! Note that Emacs does not natively know how to handle
big integers, nor has an internal representation for them. This is why
I use backticks, so Python returns a string representation of the result,
instead of the result itself.
The thing seems to be fast enough! Here is a trace for the last example.
The `<' symbol flags a message going from Python to Emacs, the '>' from
Emacs to Python. The small number gives the length of the message.
---------------------------------------------------------------------->
<9 (started)
>49 eval("eval_lisp('(eval-python \"`2L**111`\")')")
<25 (eval-python "`2L**111`")
>18 eval("`2L**111`")
<47 (reply . "2596148429267413814265248164610048L")
>45 reply("2596148429267413814265248164610048L")
<47 (reply . "2596148429267413814265248164610048L")
----------------------------------------------------------------------<
My real end goal is using Python instead of LISP for an extension language
for Emacs, as needed. I'm jealous of "vim" users! :-)
Two things are missing before I'm happy. First, this is all too fragile
to errors: a Python exception should properly be seen on the Emacs side,
and vice-versa. Second, I'd like to find a way for any function or variable
which is not defined in Python to be resolved within Emacs if possible: the
idea is to use Emacs elegantly from Python, using Python syntax for function
calls, without explicitly resorting to `eval_lisp("LISP-EXPRESSION")'.
We could progressively build a cache about whether LISP symbols are `boundp'
or `fboundp' or not, and use that information afterwards. (Underlines would
be translated to dashes, of course.) For the rest, I wonder if I could not
replace __builtins__ with an instance of a class of my own. Any other idea?
--
François Pinard http://www.iro.umontreal.ca/~pinard
More information about the Python-list
mailing list