Could Emacs be rewritten in Python?

Patrick K. O'Brien pobrien at
Thu Apr 17 18:17:40 CEST 2003

"Greg Ewing (using" <ckea25d02 at> writes:

> Patrick K. O'Brien wrote:
> > I suppose one could bind attributes (current frame, current buffer,
> > point) to a module and then import that module everywhere that needed
> > access to these attributes
> That's no better, because they're still global -- there's
> still only *one* of each of them, whereas there really
> needs to be different ones in different contexts.
> A function which needs to operate on a frame should be
> passed a frame. Some buffer will be displayed in that
> frame: frame.buffer. That buffer will have a point:
> frame.buffer.point. Etcetera.

That's easy enough for functions/methods/commands that are part of the
base package.  What I was thinking about were functions/commands that
were written by users to extend the base package.  I haven't figured
out a good way to determine the context they need and be able to pass
that object to them.  For example, let's say someone wanted to create
a new command that operated on the current buffer.  Assuming I had the
mechanism in place to bind keystrokes to a user-created command, how
would I know what parameters that command expected?

Does anyone know of a Python program of any kind that comes close to
having this ability to be extended by users?

Now that I think about it, my dispatcher module does poke into
handlers/receivers to see what parameters they are expecting (based on
parameter name) and only calls the handler with the parameters it
wants.  So I suppose I could do something similar, using a naming
convention for all the objects that are available as parameters, which
should be a reasonably small number.

Here is the relevant code from

def _call(receiver, **kwds):
    """Call receiver with only arguments it can accept."""
    if hasattr(receiver, '__call__') and \
       (hasattr(receiver.__call__, 'im_func') or hasattr(receiver.__call__, 'im_code')):
        # receiver is a class instance; assume it is callable.
        # Reassign receiver to the actual method that will be called.
        receiver = receiver.__call__
    if hasattr(receiver, 'im_func'):
        # receiver is a method. Drop the first argument, usually 'self'.
        fc = receiver.im_func.func_code
        acceptable = fc.co_varnames[1:fc.co_argcount]
    elif hasattr(receiver, 'func_code'):
        # receiver is a function.
        fc = receiver.func_code
        acceptable = fc.co_varnames[0:fc.co_argcount]
        raise DispatcherError, 'Unknown receiver %s of type %s' % (receiver, type(receiver))
    if not (fc.co_flags & 8):
        # fc does not have a **kwds type parameter, therefore 
        # remove unacceptable arguments.
        for arg in kwds.keys():
            if arg not in acceptable:
                del kwds[arg]
    return receiver(**kwds)

Patrick K. O'Brien
"Your source for Python programming expertise."

More information about the Python-list mailing list