diff --git a/IPython/Extensions/ipy_greedycompleter.py b/IPython/Extensions/ipy_greedycompleter.py new file mode 100644 index 0000000..3b44751 --- /dev/null +++ b/IPython/Extensions/ipy_greedycompleter.py @@ -0,0 +1,75 @@ +""" Greedy completer extension for IPython + +Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate +everything, so you need to consider the consequences of pressing tab +yourself! + +Note that this extension simplifies readline interaction by setting +only whitespace as completer delimiter. If this works well, we will +do the same in default completer. + +""" +from IPython import generics,ipapi +from IPython.genutils import dir2 + +def attr_matches(self, text): + """Compute matches when text contains a dot. + + MONKEYPATCHED VERSION (ipy_greedycompleter.py) + + Assuming the text is of the form NAME.NAME....[NAME], and is + evaluatable in self.namespace or self.global_namespace, it will be + evaluated and its attributes (as revealed by dir()) are used as + possible completions. (For class instances, class members are are + also considered.) + + WARNING: this can still invoke arbitrary C code, if an object + with a __getattr__ hook is evaluated. + + """ + import re + + force_complete = 1 + # Another option, seems to work great. Catches things like ''. + m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) + + if m: + expr, attr = m.group(1, 3) + else: + # force match - eval anything that ends with colon + if not force_complete: + return [] + + m2 = re.match(r"(.+)\.(\w*)$", self.lbuf) + if not m2: + return [] + expr, attr = m2.group(1,2) + + + try: + obj = eval(expr, self.namespace) + except: + try: + obj = eval(expr, self.global_namespace) + except: + return [] + + words = dir2(obj) + + try: + words = generics.complete_object(obj, words) + except ipapi.TryNext: + pass + # Build match list to return + n = len(attr) + res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] + return res + +def main(): + import readline + readline.set_completer_delims(" \n\t") + # monkeypatch - the code will be folded to normal completer later on + import IPython.completer + IPython.completer.Completer.attr_matches = attr_matches + +main() \ No newline at end of file diff --git a/IPython/Itpl.py b/IPython/Itpl.py index ce21a87..0003e30 100644 --- a/IPython/Itpl.py +++ b/IPython/Itpl.py @@ -94,8 +94,16 @@ def matchorfail(text, pos): match = tokenprog.match(text, pos) if match is None: raise ItplError(text, pos) + return match, match.end() +try: + itpl_encoding = sys.stdin.encoding or 'ascii' +except AttributeError: + itpl_encoding = 'ascii' + + + class Itpl: """Class representing a string with interpolation abilities. @@ -104,7 +112,7 @@ class Itpl: evaluation and substitution happens in the namespace of the caller when str(instance) is called.""" - def __init__(self, format,codec=sys.stdin.encoding,encoding_errors='backslashreplace'): + def __init__(self, format,codec=itpl_encoding,encoding_errors='backslashreplace'): """The single mandatory argument to this constructor is a format string. diff --git a/IPython/UserConfig/ipy_user_conf.py b/IPython/UserConfig/ipy_user_conf.py index 55049ba..2500a18 100644 --- a/IPython/UserConfig/ipy_user_conf.py +++ b/IPython/UserConfig/ipy_user_conf.py @@ -87,6 +87,11 @@ def main(): # For bzr completer, requires bzrlib (the python installation of bzr) #ip.load('ipy_bzr') + # Tab completer that is not quite so picky (i.e. + # "foo". and str(2). will work). Complete + # at your own risk! + #import ipy_greedycompleter + # some config helper functions you can use diff --git a/doc/ChangeLog b/doc/ChangeLog index 1e40aae..7d435ae 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,10 @@ +2008-05-14 Ville Vainio + + * Extensions/ipy_greedycompleter.py: + New extension that enables a bit more "relaxed" tab + completer that evaluates code without safety checks + (i.e. there can be side effects like function calls) + 2008-04-20 Ville Vainio * Extensions/ipy_lookfor.py: add %lookfor magic command diff --git a/doc/do_sphinx.py b/doc/do_sphinx.py index 77d7481..6a1455a 100644 --- a/doc/do_sphinx.py +++ b/doc/do_sphinx.py @@ -13,9 +13,43 @@ if sys.platform != 'win32': # Produce pdf. os.chdir('build/latex') - # Change chapter style to section style: allows chapters to start on the current page. Works much better for the short chapters we have. + # Change chapter style to section style: allows chapters to start on + # the current page. Works much better for the short chapters we have. + # This must go in the class file rather than the preamble, so we modify + # manual.cls at runtime. + chapter_cmds=r''' +% Local changes. +\renewcommand\chapter{ + \thispagestyle{plain} + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter +} +\def\@makechapterhead#1{ + \vspace*{10\p@} + {\raggedright \reset@font \Huge \bfseries \thechapter \quad #1} + \par\nobreak + \hrulefill + \par\nobreak + \vspace*{10\p@} +} +\def\@makeschapterhead#1{ + \vspace*{10\p@} + {\raggedright \reset@font \Huge \bfseries #1} + \par\nobreak + \hrulefill + \par\nobreak + \vspace*{10\p@} +} +''' + + unmodified=True for line in fileinput.FileInput('manual.cls',inplace=1): - line=line.replace('py@OldChapter=\chapter','py@OldChapter=\section') + if 'Support for module synopsis' in line and unmodified: + line=chapter_cmds+line + elif 'makechapterhead' in line: + # Already have altered manual.cls: don't need to again. + unmodified=False print line, # Copying the makefile produced by sphinx... diff --git a/doc/source/conf.py b/doc/source/conf.py index 24ac6de..0270b6e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -123,7 +123,7 @@ latex_font_size = '10pt' latex_documents = [('ipython','ipython.tex','IPython Documentation','IPython developers','manual')] # Additional stuff for the LaTeX preamble. -latex_preamble = '\\def\\thesection{\\arabic{section}}' +#latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = []