##// END OF EJS Templates
Fixed numerous bugs with tab completion, including the one recently reported by fperez.
Fixed numerous bugs with tab completion, including the one recently reported by fperez.

File last commit:

r2466:d8c93552
r2939:6d047e62
Show More
magic_blueprint.txt
103 lines | 3.3 KiB | text/plain | TextLexer
Fernando Perez
Added notes with ideas about new design for %magics.
r2466 ==============================
The magic commands subsystem
==============================
.. warning::
These are *preliminary* notes and thoughts on the magic system, kept here
for reference so we can come up with a good design now that the major core
refactoring has made so much progress. Do not consider yet any part of this
document final.
Two entry points:
- m.line_eval(self,parameter_s): like today
- m.block_eval(self,code_block): for whole-block evaluation.
This would allow us to have magics that take input, and whose single line form
can even take input and call block_eval later (like %cpaste does, but with a
generalized interface).
Constructor
===========
Suggested syntax::
class MyMagic(BaseMagic):
requires_shell = True/False
def __init__(self,shell=None):
Registering magics
==================
Today, ipapi provides an *expose_magic()* function for making simple magics.
We will probably extend this (in a backwards-compatible manner if possible) to
allow the simplest cases to work as today, while letting users register more
complex ones.
Use cases::
def func(arg): pass # note signature, no 'self'
ip.expose_magic('name',func)
def func_line(arg): pass
def func_block(arg):pass
ip.expose_magic('name',func_line,func_block)
class mymagic(BaseMagic):
"""Magic docstring, used in help messages.
"""
def line_eval(self,arg): pass
def block_eval(self,arg): pass
ip.register_magic(mymagic)
The BaseMagic class will offer common functionality to all, including things
like options handling (via argparse).
Call forms: line and block
==========================
Block-oriented environments will call line_eval() for the first line of input
(the call line starting with '%') and will then feed the rest of the block to
block_eval() if the magic in question has a block mode.
In line environments, by default %foo -> foo.line_eval(), but no block call is
made. Specific implementations of line_eval can decide to then call block_eval
if they want to provide for whole-block input in line-oriented environments.
The api might be adapted for this decision to be made automatically by the
frontend...
Precompiled magics for rapid loading
====================================
For IPython itself, we'll have a module of 'core' magic functions that do not
require run-time registration. These will be the ones contained today in
Magic.py, plus any others we deem worthy of being available by default. This
is a trick to enable faster startup, since once we move to a model where each
magic can in principle be registered at runtime, creating a lot of them can
easily swamp startup time.
The trick is to make a module with a top-level class object that contains
explicit references to all the 'core' magics in its dict. This way, the magic
table can be quickly updated at interpreter startup with a single call, by
doing something along the lines of::
self.magic_table.update(static_magics.__dict__)
The point will be to be able to bypass the explicit calling of whatever
register_magic() API we end up making for users to declare their own magics.
So ultimately one should be able to do either::
ip.register_magic(mymagic) # for one function
or::
ip.load_magics(static_magics) # for a bunch of them
I still need to clarify exactly how this should work though.