diff --git a/IPython/Extensions/ipy_app_completers.py b/IPython/Extensions/ipy_app_completers.py index 831cfd6..0277623 100644 --- a/IPython/Extensions/ipy_app_completers.py +++ b/IPython/Extensions/ipy_app_completers.py @@ -1,21 +1,21 @@ -""" Install various IPython completers - -IPython extension that installs the completers related to external apps. - -The actual implementations are in Extensions/ipy_completers.py - -""" -import IPython.ipapi - -ip = IPython.ipapi.get() - -from ipy_completers import * - -ip.set_hook('complete_command', apt_completers, re_key = '.*apt-get') -ip.set_hook('complete_command', apt_completers, re_key = '.*yum') - -ip.set_hook('complete_command', svn_completer, str_key = 'svn') - -ip.set_hook('complete_command', hg_completer, str_key = 'hg') - -ip.set_hook('complete_command', bzr_completer, str_key = 'bzr') +""" Install various IPython completers + +IPython extension that installs the completers related to external apps. + +The actual implementations are in Extensions/ipy_completers.py + +""" +import IPython.ipapi + +ip = IPython.ipapi.get() + +from ipy_completers import * + +ip.set_hook('complete_command', apt_completers, re_key = '.*apt-get') +ip.set_hook('complete_command', apt_completers, re_key = '.*yum') + +ip.set_hook('complete_command', svn_completer, str_key = 'svn') + +ip.set_hook('complete_command', hg_completer, str_key = 'hg') + +ip.set_hook('complete_command', bzr_completer, str_key = 'bzr') diff --git a/IPython/Extensions/ipy_editors.py b/IPython/Extensions/ipy_editors.py index 6c00d11..09f940e 100644 --- a/IPython/Extensions/ipy_editors.py +++ b/IPython/Extensions/ipy_editors.py @@ -1,80 +1,80 @@ -""" 'editor' hooks for common editors that work well with ipython - -They should honor the line number argument, at least. - -Contributions are *very* welcome. -""" - -import IPython.ipapi -ip = IPython.ipapi.get() - -from IPython.Itpl import itplns -import os - -def install_editor(run_template, wait = False): - """ Gets a template in format "myeditor bah bah $file bah bah $line" - - $file will be replaced by file name, $line by line number (or 0). - Installs the editor that is called by IPython, instead of the default - notepad or vi. - - If wait is true, wait until the user presses enter before returning, - to facilitate non-blocking editors that exit immediately after - the call. - """ - - def call_editor(self, file, line): - if line is None: - line = 0 - cmd = itplns(run_template, locals()) - print ">",cmd - os.system(cmd) - if wait: - raw_input("Press Enter when done editing:") - - ip.set_hook('editor',call_editor) - - -# in these, exe is always the path/name of the executable. Useful -# if you don't have the editor directory in your path - -def komodo(exe = 'komodo'): - """ Activestate Komodo [Edit] """ - install_editor(exe + ' -l $line "$file"', wait = True) - -def scite(exe = "scite"): - """ SciTE or Sc1 """ - install_editor(exe + ' "$file" -goto:$line') - -def notepadplusplus(exe = 'notepad++'): - """ Notepad++ http://notepad-plus.sourceforge.net """ - install_editor(exe + ' -n$line "$file"') - -def jed(exe = 'jed'): - """ JED, the lightweight emacsish editor """ - install_editor(exe + ' +$line "$file"') - -def idle(exe = None): - """ Idle, the editor bundled with python - - Should be pretty smart about finding the executable. - """ - if exe is None: - import idlelib - p = os.path.dirname(idlelib.__file__) - exe = p + '/idle.py' - install_editor(exe + ' "$file"') - - -# these are untested, report any problems - -def emacs(exe = 'emacs'): - install_editor(exe + ' +$line "$file"') - -def gnuclient(exe= 'gnuclient'): - install_editor(exe + ' -nw +$line "$file"') - -def crimson_editor(exe = 'cedt.exe'): - install_editor(exe + ' /L:%line "$file"') - +""" 'editor' hooks for common editors that work well with ipython + +They should honor the line number argument, at least. + +Contributions are *very* welcome. +""" + +import IPython.ipapi +ip = IPython.ipapi.get() + +from IPython.Itpl import itplns +import os + +def install_editor(run_template, wait = False): + """ Gets a template in format "myeditor bah bah $file bah bah $line" + + $file will be replaced by file name, $line by line number (or 0). + Installs the editor that is called by IPython, instead of the default + notepad or vi. + + If wait is true, wait until the user presses enter before returning, + to facilitate non-blocking editors that exit immediately after + the call. + """ + + def call_editor(self, file, line): + if line is None: + line = 0 + cmd = itplns(run_template, locals()) + print ">",cmd + os.system(cmd) + if wait: + raw_input("Press Enter when done editing:") + + ip.set_hook('editor',call_editor) + + +# in these, exe is always the path/name of the executable. Useful +# if you don't have the editor directory in your path + +def komodo(exe = 'komodo'): + """ Activestate Komodo [Edit] """ + install_editor(exe + ' -l $line "$file"', wait = True) + +def scite(exe = "scite"): + """ SciTE or Sc1 """ + install_editor(exe + ' "$file" -goto:$line') + +def notepadplusplus(exe = 'notepad++'): + """ Notepad++ http://notepad-plus.sourceforge.net """ + install_editor(exe + ' -n$line "$file"') + +def jed(exe = 'jed'): + """ JED, the lightweight emacsish editor """ + install_editor(exe + ' +$line "$file"') + +def idle(exe = None): + """ Idle, the editor bundled with python + + Should be pretty smart about finding the executable. + """ + if exe is None: + import idlelib + p = os.path.dirname(idlelib.__file__) + exe = p + '/idle.py' + install_editor(exe + ' "$file"') + + +# these are untested, report any problems + +def emacs(exe = 'emacs'): + install_editor(exe + ' +$line "$file"') + +def gnuclient(exe= 'gnuclient'): + install_editor(exe + ' -nw +$line "$file"') + +def crimson_editor(exe = 'cedt.exe'): + install_editor(exe + ' /L:%line "$file"') + \ No newline at end of file diff --git a/IPython/Extensions/ipy_fsops.py b/IPython/Extensions/ipy_fsops.py index da93eb4..9e5ff9f 100644 --- a/IPython/Extensions/ipy_fsops.py +++ b/IPython/Extensions/ipy_fsops.py @@ -1,173 +1,173 @@ -""" File system operations - -Contains: Simple variants of normal unix shell commands (icp, imv, irm, -imkdir, igrep). - -Some "otherwise handy" utils ('collect' for gathering files to -~/_ipython/collect, 'inote' for collecting single note lines to -~/_ipython/note.txt) - -Mostly of use for bare windows installations where cygwin/equivalent is not -installed and you would otherwise need to deal with dos versions of the -commands (that e.g. don't understand / as path separator). These can -do some useful tricks on their own, though (like use 'mglob' patterns). - -Not to be confused with ipipe commands (ils etc.) that also start with i. -""" - -import IPython.ipapi -ip = IPython.ipapi.get() - -import shutil,os,shlex -from IPython.external import mglob -class IpyShellCmdException(Exception): - pass - -def parse_args(args): - """ Given arg string 'CMD files... target', return ([files], target) """ - - tup = args.split(None, 1) - if len(tup) == 1: - raise IpyShellCmdException("Expected arguments for " + tup[0]) - - tup2 = shlex.split(tup[1]) - - flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] - if not flist: - raise IpyShellCmdException("No files found:" + str(tup2[0:-1])) - return flist, trg - -def icp(ip,arg): - """ icp files... targetdir - - Copy all files to target, creating dirs for target if necessary - - icp srcdir dstdir - - Copy srcdir to distdir - - """ - import distutils.dir_util - - fs, targetdir = parse_args(arg) - if not os.path.isdir(targetdir): - distutils.dir_util.mkpath(targetdir,verbose =1) - for f in fs: - shutil.copy2(f,targetdir) - return fs -ip.defalias("icp",icp) - -def imv(ip,arg): - """ imv src tgt - - Move source to target. - """ - - fs, target = parse_args(arg) - if len(fs) > 1: - assert os.path.isdir(target) - for f in fs: - shutil.move(f, target) - return fs -ip.defalias("imv",imv) - -def irm(ip,arg): - """ irm path[s]... - - Remove file[s] or dir[s] path. Dirs are deleted recursively. - """ - paths = mglob.expand(arg.split(None,1)[1]) - import distutils.dir_util - for p in paths: - print "rm",p - if os.path.isdir(p): - distutils.dir_util.remove_tree(p, verbose = 1) - else: - os.remove(p) - -ip.defalias("irm",irm) - -def imkdir(ip,arg): - """ imkdir path - - Creates dir path, and all dirs on the road - """ - import distutils.dir_util - targetdir = arg.split(None,1)[1] - distutils.dir_util.mkpath(targetdir,verbose =1) - -ip.defalias("imkdir",imkdir) - -def igrep(ip,arg): - """ igrep PAT files... - - Very dumb file scan, case-insensitive. - - e.g. - - igrep "test this" rec:*.py - - """ - elems = shlex.split(arg) - dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) - res = [] - for f in fs: - found = False - for l in open(f): - if pat.lower() in l.lower(): - if not found: - print "[[",f,"]]" - found = True - res.append(f) - print l.rstrip() - return res - -ip.defalias("igrep",igrep) - -def collect(ip,arg): - """ collect foo/a.txt rec:bar=*.py - - Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, - likewise - - Without args, try to open ~/_ipython/collect dir (in win32 at least). - """ - from path import path - basedir = path(ip.options.ipythondir + '/collect') - try: - fs = mglob.expand(arg.split(None,1)[1]) - except IndexError: - os.startfile(basedir) - return - for f in fs: - f = path(f) - trg = basedir / f.splitdrive()[1].lstrip('/\\') - if f.isdir(): - print "mkdir",trg - trg.makedirs() - continue - dname = trg.dirname() - if not dname.isdir(): - dname.makedirs() - print f,"=>",trg - shutil.copy2(f,trg) - -ip.defalias("collect",collect) - -def inote(ip,arg): - """ inote Hello world - - Adds timestamp and Hello world to ~/_ipython/notes.txt - - Without args, opens notes.txt for editing. - """ - import time - fname = ip.options.ipythondir + '/notes.txt' - - try: - entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' - f= open(fname, 'a').write(entry) - except IndexError: - ip.IP.hooks.editor(fname) - -ip.defalias("inote",inote) +""" File system operations + +Contains: Simple variants of normal unix shell commands (icp, imv, irm, +imkdir, igrep). + +Some "otherwise handy" utils ('collect' for gathering files to +~/_ipython/collect, 'inote' for collecting single note lines to +~/_ipython/note.txt) + +Mostly of use for bare windows installations where cygwin/equivalent is not +installed and you would otherwise need to deal with dos versions of the +commands (that e.g. don't understand / as path separator). These can +do some useful tricks on their own, though (like use 'mglob' patterns). + +Not to be confused with ipipe commands (ils etc.) that also start with i. +""" + +import IPython.ipapi +ip = IPython.ipapi.get() + +import shutil,os,shlex +from IPython.external import mglob +class IpyShellCmdException(Exception): + pass + +def parse_args(args): + """ Given arg string 'CMD files... target', return ([files], target) """ + + tup = args.split(None, 1) + if len(tup) == 1: + raise IpyShellCmdException("Expected arguments for " + tup[0]) + + tup2 = shlex.split(tup[1]) + + flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] + if not flist: + raise IpyShellCmdException("No files found:" + str(tup2[0:-1])) + return flist, trg + +def icp(ip,arg): + """ icp files... targetdir + + Copy all files to target, creating dirs for target if necessary + + icp srcdir dstdir + + Copy srcdir to distdir + + """ + import distutils.dir_util + + fs, targetdir = parse_args(arg) + if not os.path.isdir(targetdir): + distutils.dir_util.mkpath(targetdir,verbose =1) + for f in fs: + shutil.copy2(f,targetdir) + return fs +ip.defalias("icp",icp) + +def imv(ip,arg): + """ imv src tgt + + Move source to target. + """ + + fs, target = parse_args(arg) + if len(fs) > 1: + assert os.path.isdir(target) + for f in fs: + shutil.move(f, target) + return fs +ip.defalias("imv",imv) + +def irm(ip,arg): + """ irm path[s]... + + Remove file[s] or dir[s] path. Dirs are deleted recursively. + """ + paths = mglob.expand(arg.split(None,1)[1]) + import distutils.dir_util + for p in paths: + print "rm",p + if os.path.isdir(p): + distutils.dir_util.remove_tree(p, verbose = 1) + else: + os.remove(p) + +ip.defalias("irm",irm) + +def imkdir(ip,arg): + """ imkdir path + + Creates dir path, and all dirs on the road + """ + import distutils.dir_util + targetdir = arg.split(None,1)[1] + distutils.dir_util.mkpath(targetdir,verbose =1) + +ip.defalias("imkdir",imkdir) + +def igrep(ip,arg): + """ igrep PAT files... + + Very dumb file scan, case-insensitive. + + e.g. + + igrep "test this" rec:*.py + + """ + elems = shlex.split(arg) + dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) + res = [] + for f in fs: + found = False + for l in open(f): + if pat.lower() in l.lower(): + if not found: + print "[[",f,"]]" + found = True + res.append(f) + print l.rstrip() + return res + +ip.defalias("igrep",igrep) + +def collect(ip,arg): + """ collect foo/a.txt rec:bar=*.py + + Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, + likewise + + Without args, try to open ~/_ipython/collect dir (in win32 at least). + """ + from path import path + basedir = path(ip.options.ipythondir + '/collect') + try: + fs = mglob.expand(arg.split(None,1)[1]) + except IndexError: + os.startfile(basedir) + return + for f in fs: + f = path(f) + trg = basedir / f.splitdrive()[1].lstrip('/\\') + if f.isdir(): + print "mkdir",trg + trg.makedirs() + continue + dname = trg.dirname() + if not dname.isdir(): + dname.makedirs() + print f,"=>",trg + shutil.copy2(f,trg) + +ip.defalias("collect",collect) + +def inote(ip,arg): + """ inote Hello world + + Adds timestamp and Hello world to ~/_ipython/notes.txt + + Without args, opens notes.txt for editing. + """ + import time + fname = ip.options.ipythondir + '/notes.txt' + + try: + entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' + f= open(fname, 'a').write(entry) + except IndexError: + ip.IP.hooks.editor(fname) + +ip.defalias("inote",inote) diff --git a/IPython/Extensions/ipy_kitcfg.py b/IPython/Extensions/ipy_kitcfg.py index da77bf7..3a7e9f3 100644 --- a/IPython/Extensions/ipy_kitcfg.py +++ b/IPython/Extensions/ipy_kitcfg.py @@ -1,56 +1,56 @@ -import os,sys - -import ipy_rehashdir,glob -from ipy_rehashdir import selflaunch, PyLauncher - -def pylaunchers(): - """Create launchers for python scripts in cwd and store them in alias table - - This is useful if you want to invoke .py scripts from ipykit session, - just adding .py files in PATH does not work without file association. - - .ipy files will be run like macros. - - """ - fs = glob.glob('*.?py*') - for f in fs: - l = PyLauncher(f) - n = os.path.splitext(f)[0] - ip.defalias(n, l) - ip.magic('store '+n) - - -def exta_imports(): - # add some modules that you'd want to be bundled in the ipykit - # library zip file here. Do this if you get ImportErrors from scripts you - # try to launch with 'py' or pylaunchers. In theory you could include - # the whole stdlib here for full script coverage - - # note that this is never run, it's just here for py2exe - import distutils.dir_util - -def main(): - root = os.environ.get('IPYKITROOT', None) - if not root: - print "Can't configure ipykit, IPYKITROOT should be set." - return - - os.environ["PATH"] = os.environ["PATH"] + ";" + root + "\\bin;" - ip.to_user_ns("pylaunchers") - - -def ipython_firstrun(ip): - print "First run of ipykit - configuring" - ip.defalias('py',selflaunch) - ip.defalias('d','ls -F') - ip.defalias('ls','ls') - ip.magic('store py') - ip.magic('store d') - ip.magic('store ls') - -def init_ipython(ipy): - global ip - ip = ipy - main() - - +import os,sys + +import ipy_rehashdir,glob +from ipy_rehashdir import selflaunch, PyLauncher + +def pylaunchers(): + """Create launchers for python scripts in cwd and store them in alias table + + This is useful if you want to invoke .py scripts from ipykit session, + just adding .py files in PATH does not work without file association. + + .ipy files will be run like macros. + + """ + fs = glob.glob('*.?py*') + for f in fs: + l = PyLauncher(f) + n = os.path.splitext(f)[0] + ip.defalias(n, l) + ip.magic('store '+n) + + +def exta_imports(): + # add some modules that you'd want to be bundled in the ipykit + # library zip file here. Do this if you get ImportErrors from scripts you + # try to launch with 'py' or pylaunchers. In theory you could include + # the whole stdlib here for full script coverage + + # note that this is never run, it's just here for py2exe + import distutils.dir_util + +def main(): + root = os.environ.get('IPYKITROOT', None) + if not root: + print "Can't configure ipykit, IPYKITROOT should be set." + return + + os.environ["PATH"] = os.environ["PATH"] + ";" + root + "\\bin;" + ip.to_user_ns("pylaunchers") + + +def ipython_firstrun(ip): + print "First run of ipykit - configuring" + ip.defalias('py',selflaunch) + ip.defalias('d','ls -F') + ip.defalias('ls','ls') + ip.magic('store py') + ip.magic('store d') + ip.magic('store ls') + +def init_ipython(ipy): + global ip + ip = ipy + main() + + diff --git a/IPython/Extensions/ipy_workdir.py b/IPython/Extensions/ipy_workdir.py index 07ae5d4..e27b476 100644 --- a/IPython/Extensions/ipy_workdir.py +++ b/IPython/Extensions/ipy_workdir.py @@ -1,43 +1,43 @@ -#!/usr/bin/env python - -import IPython.ipapi -ip = IPython.ipapi.get() - -import os, subprocess - -workdir = None -def workdir_f(ip,line): - """ Exceute commands residing in cwd elsewhere - - Example:: - - workdir /myfiles - cd bin - workdir myscript.py - - executes myscript.py (stored in bin, but not in path) in /myfiles - """ - global workdir - dummy,cmd = line.split(None,1) - if os.path.isdir(cmd): - workdir = os.path.abspath(cmd) - print "Set workdir",workdir - elif workdir is None: - print "Please set workdir first by doing e.g. 'workdir q:/'" - else: - sp = cmd.split(None,1) - if len(sp) == 1: - head, tail = cmd, '' - else: - head, tail = sp - if os.path.isfile(head): - cmd = os.path.abspath(head) + ' ' + tail - print "Execute command '" + cmd+ "' in",workdir - olddir = os.getcwd() - os.chdir(workdir) - try: - os.system(cmd) - finally: - os.chdir(olddir) - -ip.defalias("workdir",workdir_f) +#!/usr/bin/env python + +import IPython.ipapi +ip = IPython.ipapi.get() + +import os, subprocess + +workdir = None +def workdir_f(ip,line): + """ Exceute commands residing in cwd elsewhere + + Example:: + + workdir /myfiles + cd bin + workdir myscript.py + + executes myscript.py (stored in bin, but not in path) in /myfiles + """ + global workdir + dummy,cmd = line.split(None,1) + if os.path.isdir(cmd): + workdir = os.path.abspath(cmd) + print "Set workdir",workdir + elif workdir is None: + print "Please set workdir first by doing e.g. 'workdir q:/'" + else: + sp = cmd.split(None,1) + if len(sp) == 1: + head, tail = cmd, '' + else: + head, tail = sp + if os.path.isfile(head): + cmd = os.path.abspath(head) + ' ' + tail + print "Execute command '" + cmd+ "' in",workdir + olddir = os.getcwd() + os.chdir(workdir) + try: + os.system(cmd) + finally: + os.chdir(olddir) + +ip.defalias("workdir",workdir_f) diff --git a/IPython/generics.py b/IPython/generics.py index 09a1462..61b11fc 100644 --- a/IPython/generics.py +++ b/IPython/generics.py @@ -1,30 +1,30 @@ -from IPython.ipapi import TryNext -from IPython.external.simplegeneric import generic - -''' 'Generic' functions for extending IPython - -See http://cheeseshop.python.org/pypi/simplegeneric - -Here's an example from genutils.py: - - def print_lsstring(arg): - """ Prettier (non-repr-like) and more informative printer for LSString """ - print "LSString (.p, .n, .l, .s available). Value:" - print arg - - print_lsstring = result_display.when_type(LSString)(print_lsstring) - -(Yes, the nasty syntax is for python 2.3 compatibility. Your own extensions -can use the niftier decorator syntax) - -''' - -def result_display(result): - """ print the result of computation """ - raise TryNext - -result_display = generic(result_display) - -def inspect_object(obj): - """ Called when you do obj? """ - raise TryNext +from IPython.ipapi import TryNext +from IPython.external.simplegeneric import generic + +''' 'Generic' functions for extending IPython + +See http://cheeseshop.python.org/pypi/simplegeneric + +Here's an example from genutils.py: + + def print_lsstring(arg): + """ Prettier (non-repr-like) and more informative printer for LSString """ + print "LSString (.p, .n, .l, .s available). Value:" + print arg + + print_lsstring = result_display.when_type(LSString)(print_lsstring) + +(Yes, the nasty syntax is for python 2.3 compatibility. Your own extensions +can use the niftier decorator syntax) + +''' + +def result_display(result): + """ print the result of computation """ + raise TryNext + +result_display = generic(result_display) + +def inspect_object(obj): + """ Called when you do obj? """ + raise TryNext diff --git a/IPython/history.py b/IPython/history.py index ca2dc22..850095b 100644 --- a/IPython/history.py +++ b/IPython/history.py @@ -1,241 +1,241 @@ -# -*- coding: utf-8 -*- - -""" History related magics and functionality """ - -import fnmatch - -def magic_history(self, parameter_s = ''): - """Print input history (_i variables), with most recent last. - - %history -> print at most 40 inputs (some may be multi-line)\\ - %history n -> print at most n inputs\\ - %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\ - - Each input's number is shown, and is accessible as the - automatically generated variable _i. Multi-line statements are - printed starting at a new line for easy copy/paste. - - - Options: - - -n: do NOT print line numbers. This is useful if you want to get a - printout of many lines which can be directly pasted into a text - editor. - - This feature is only available if numbered prompts are in use. - - -t: (default) print the 'translated' history, as IPython understands it. - IPython filters your input and converts it all into valid Python source - before executing it (things like magics or aliases are turned into - function calls, for example). With this option, you'll see the native - history instead of the user-entered version: '%cd /' will be seen as - '_ip.magic("%cd /")' instead of '%cd /'. - - -r: print the 'raw' history, i.e. the actual commands you typed. - - -g: treat the arg as a pattern to grep for in (full) history. - This includes the "shadow history" (almost all commands ever written). - Use '%hist -g' to show full shadow history (may be very long). - In shadow history, every index nuwber starts with 0. - - - """ - - ip = self.api - shell = self.shell - if not shell.outputcache.do_full_cache: - print 'This feature is only available if numbered prompts are in use.' - return - opts,args = self.parse_options(parameter_s,'gntsr',mode='list') - - if opts.has_key('t'): - input_hist = shell.input_hist - elif opts.has_key('r'): - input_hist = shell.input_hist_raw - else: - input_hist = shell.input_hist - - - default_length = 40 - pattern = None - if opts.has_key('g'): - init = 1 - final = len(input_hist) - parts = parameter_s.split(None,1) - if len(parts) == 1: - parts += '*' - head, pattern = parts - pattern = "*" + pattern + "*" - elif len(args) == 0: - final = len(input_hist) - init = max(1,final-default_length) - elif len(args) == 1: - final = len(input_hist) - init = max(1,final-int(args[0])) - elif len(args) == 2: - init,final = map(int,args) - else: - warn('%hist takes 0, 1 or 2 arguments separated by spaces.') - print self.magic_hist.__doc__ - return - width = len(str(final)) - line_sep = ['','\n'] - print_nums = not opts.has_key('n') - - found = False - if pattern is not None: - sh = ip.IP.shadowhist.all() - for idx, s in sh: - if fnmatch.fnmatch(s, pattern): - print "0%d: %s" %(idx, s) - found = True - - if found: - print "===" - print "^shadow history ends, fetch by %rep (must start with 0)" - print "=== start of normal history ===" - - for in_num in range(init,final): - inline = input_hist[in_num] - if pattern is not None and not fnmatch.fnmatch(inline, pattern): - continue - - multiline = int(inline.count('\n') > 1) - if print_nums: - print '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]), - print inline, - - - -def magic_hist(self, parameter_s=''): - """Alternate name for %history.""" - return self.magic_history(parameter_s) - - - -def rep_f(self, arg): - r""" Repeat a command, or get command to input line for editing - - - %rep (no arguments): - - Place a string version of last computation result (stored in the special '_' - variable) to the next input prompt. Allows you to create elaborate command - lines without using copy-paste:: - - $ l = ["hei", "vaan"] - $ "".join(l) - ==> heivaan - $ %rep - $ heivaan_ <== cursor blinking - - %rep 45 - - Place history line 45 to next input prompt. Use %hist to find out the - number. - - %rep 1-4 6-7 3 - - Repeat the specified lines immediately. Input slice syntax is the same as - in %macro and %save. - - %rep foo - - Place the most recent line that has the substring "foo" to next input. - (e.g. 'svn ci -m foobar'). - - """ - - - opts,args = self.parse_options(arg,'',mode='list') - ip = self.api - if not args: - ip.set_next_input(str(ip.user_ns["_"])) - return - - if len(args) == 1 and not '-' in args[0]: - arg = args[0] - if len(arg) > 1 and arg.startswith('0'): - # get from shadow hist - num = int(arg[1:]) - line = self.shadowhist.get(num) - ip.set_next_input(str(line)) - return - try: - num = int(args[0]) - ip.set_next_input(str(ip.IP.input_hist_raw[num]).rstrip()) - return - except ValueError: - pass - - for h in reversed(self.shell.input_hist_raw): - if 'rep' in h: - continue - if fnmatch.fnmatch(h,'*' + arg + '*'): - ip.set_next_input(str(h).rstrip()) - return - - - try: - lines = self.extract_input_slices(args, True) - print "lines",lines - ip.runlines(lines) - except ValueError: - print "Not found in recent history:", args - - - -_sentinel = object() - -class ShadowHist: - def __init__(self,db): - # cmd => idx mapping - self.curidx = 0 - self.db = db - - def inc_idx(self): - idx = self.db.get('shadowhist_idx', 1) - self.db['shadowhist_idx'] = idx + 1 - return idx - - def add(self, ent): - old = self.db.hget('shadowhist', ent, _sentinel) - if old is not _sentinel: - return - newidx = self.inc_idx() - #print "new",newidx # dbg - self.db.hset('shadowhist',ent, newidx) - - def all(self): - d = self.db.hdict('shadowhist') - items = [(i,s) for (s,i) in d.items()] - items.sort() - return items - - def get(self, idx): - all = self.all() - - for k, v in all: - #print k,v - if k == idx: - return v - -def test_shist(): - from IPython.Extensions import pickleshare - db = pickleshare.PickleShareDB('~/shist') - s = ShadowHist(db) - s.add('hello') - s.add('world') - s.add('hello') - s.add('hello') - s.add('karhu') - print "all",s.all() - print s.get(2) - -def init_ipython(ip): - ip.expose_magic("rep",rep_f) - ip.expose_magic("hist",magic_hist) - ip.expose_magic("history",magic_history) - - import ipy_completers - ipy_completers.quick_completer('%hist' ,'-g -t -r -n') -#test_shist() +# -*- coding: utf-8 -*- + +""" History related magics and functionality """ + +import fnmatch + +def magic_history(self, parameter_s = ''): + """Print input history (_i variables), with most recent last. + + %history -> print at most 40 inputs (some may be multi-line)\\ + %history n -> print at most n inputs\\ + %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\ + + Each input's number is shown, and is accessible as the + automatically generated variable _i. Multi-line statements are + printed starting at a new line for easy copy/paste. + + + Options: + + -n: do NOT print line numbers. This is useful if you want to get a + printout of many lines which can be directly pasted into a text + editor. + + This feature is only available if numbered prompts are in use. + + -t: (default) print the 'translated' history, as IPython understands it. + IPython filters your input and converts it all into valid Python source + before executing it (things like magics or aliases are turned into + function calls, for example). With this option, you'll see the native + history instead of the user-entered version: '%cd /' will be seen as + '_ip.magic("%cd /")' instead of '%cd /'. + + -r: print the 'raw' history, i.e. the actual commands you typed. + + -g: treat the arg as a pattern to grep for in (full) history. + This includes the "shadow history" (almost all commands ever written). + Use '%hist -g' to show full shadow history (may be very long). + In shadow history, every index nuwber starts with 0. + + + """ + + ip = self.api + shell = self.shell + if not shell.outputcache.do_full_cache: + print 'This feature is only available if numbered prompts are in use.' + return + opts,args = self.parse_options(parameter_s,'gntsr',mode='list') + + if opts.has_key('t'): + input_hist = shell.input_hist + elif opts.has_key('r'): + input_hist = shell.input_hist_raw + else: + input_hist = shell.input_hist + + + default_length = 40 + pattern = None + if opts.has_key('g'): + init = 1 + final = len(input_hist) + parts = parameter_s.split(None,1) + if len(parts) == 1: + parts += '*' + head, pattern = parts + pattern = "*" + pattern + "*" + elif len(args) == 0: + final = len(input_hist) + init = max(1,final-default_length) + elif len(args) == 1: + final = len(input_hist) + init = max(1,final-int(args[0])) + elif len(args) == 2: + init,final = map(int,args) + else: + warn('%hist takes 0, 1 or 2 arguments separated by spaces.') + print self.magic_hist.__doc__ + return + width = len(str(final)) + line_sep = ['','\n'] + print_nums = not opts.has_key('n') + + found = False + if pattern is not None: + sh = ip.IP.shadowhist.all() + for idx, s in sh: + if fnmatch.fnmatch(s, pattern): + print "0%d: %s" %(idx, s) + found = True + + if found: + print "===" + print "^shadow history ends, fetch by %rep (must start with 0)" + print "=== start of normal history ===" + + for in_num in range(init,final): + inline = input_hist[in_num] + if pattern is not None and not fnmatch.fnmatch(inline, pattern): + continue + + multiline = int(inline.count('\n') > 1) + if print_nums: + print '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]), + print inline, + + + +def magic_hist(self, parameter_s=''): + """Alternate name for %history.""" + return self.magic_history(parameter_s) + + + +def rep_f(self, arg): + r""" Repeat a command, or get command to input line for editing + + - %rep (no arguments): + + Place a string version of last computation result (stored in the special '_' + variable) to the next input prompt. Allows you to create elaborate command + lines without using copy-paste:: + + $ l = ["hei", "vaan"] + $ "".join(l) + ==> heivaan + $ %rep + $ heivaan_ <== cursor blinking + + %rep 45 + + Place history line 45 to next input prompt. Use %hist to find out the + number. + + %rep 1-4 6-7 3 + + Repeat the specified lines immediately. Input slice syntax is the same as + in %macro and %save. + + %rep foo + + Place the most recent line that has the substring "foo" to next input. + (e.g. 'svn ci -m foobar'). + + """ + + + opts,args = self.parse_options(arg,'',mode='list') + ip = self.api + if not args: + ip.set_next_input(str(ip.user_ns["_"])) + return + + if len(args) == 1 and not '-' in args[0]: + arg = args[0] + if len(arg) > 1 and arg.startswith('0'): + # get from shadow hist + num = int(arg[1:]) + line = self.shadowhist.get(num) + ip.set_next_input(str(line)) + return + try: + num = int(args[0]) + ip.set_next_input(str(ip.IP.input_hist_raw[num]).rstrip()) + return + except ValueError: + pass + + for h in reversed(self.shell.input_hist_raw): + if 'rep' in h: + continue + if fnmatch.fnmatch(h,'*' + arg + '*'): + ip.set_next_input(str(h).rstrip()) + return + + + try: + lines = self.extract_input_slices(args, True) + print "lines",lines + ip.runlines(lines) + except ValueError: + print "Not found in recent history:", args + + + +_sentinel = object() + +class ShadowHist: + def __init__(self,db): + # cmd => idx mapping + self.curidx = 0 + self.db = db + + def inc_idx(self): + idx = self.db.get('shadowhist_idx', 1) + self.db['shadowhist_idx'] = idx + 1 + return idx + + def add(self, ent): + old = self.db.hget('shadowhist', ent, _sentinel) + if old is not _sentinel: + return + newidx = self.inc_idx() + #print "new",newidx # dbg + self.db.hset('shadowhist',ent, newidx) + + def all(self): + d = self.db.hdict('shadowhist') + items = [(i,s) for (s,i) in d.items()] + items.sort() + return items + + def get(self, idx): + all = self.all() + + for k, v in all: + #print k,v + if k == idx: + return v + +def test_shist(): + from IPython.Extensions import pickleshare + db = pickleshare.PickleShareDB('~/shist') + s = ShadowHist(db) + s.add('hello') + s.add('world') + s.add('hello') + s.add('hello') + s.add('karhu') + print "all",s.all() + print s.get(2) + +def init_ipython(ip): + ip.expose_magic("rep",rep_f) + ip.expose_magic("hist",magic_hist) + ip.expose_magic("history",magic_history) + + import ipy_completers + ipy_completers.quick_completer('%hist' ,'-g -t -r -n') +#test_shist()