diff --git a/IPython/genutils.py b/IPython/genutils.py index 4655b17..d9417f1 100644 --- a/IPython/genutils.py +++ b/IPython/genutils.py @@ -5,7 +5,7 @@ General purpose utilities. This is a grab-bag of stuff I find useful in most programs I write. Some of these things are also convenient when working at the command line. -$Id: genutils.py 994 2006-01-08 08:29:44Z fperez $""" +$Id: genutils.py 1007 2006-01-12 17:15:41Z vivainio $""" #***************************************************************************** # Copyright (C) 2001-2006 Fernando Perez. @@ -949,6 +949,40 @@ def esc_quotes(strng): return strng.replace('"','\\"').replace("'","\\'") #---------------------------------------------------------------------------- +def make_quoted_expr(s): + """Return string s in appropriate quotes, using raw string if possible. + + Effectively this turns string: cd \ao\ao\ + to: r"cd \ao\ao\_"[:-1] + + Note the use of raw string and padding at the end to allow trailing backslash. + + """ + + tail = '' + tailpadding = '' + raw = '' + if "\\" in s: + raw = 'r' + if s.endswith('\\'): + tail = '[:-1]' + tailpadding = '_' + if '"' not in s: + quote = '"' + elif "'" not in s: + quote = "'" + elif '"""' not in s and not s.endswith('"'): + quote = '"""' + elif "'''" not in s and not s.endswith("'"): + quote = "'''" + else: + # give up, backslash-escaped string will do + return '"%s"' % esc_quotes(s) + res = itpl("$raw$quote$s$tailpadding$quote$tail") + return res + + +#---------------------------------------------------------------------------- def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'): """Take multiple lines of input. diff --git a/IPython/iplib.py b/IPython/iplib.py index eae2697..196c869 100644 --- a/IPython/iplib.py +++ b/IPython/iplib.py @@ -6,7 +6,7 @@ Requires Python 2.1 or newer. This file contains all the classes and helper functions specific to IPython. -$Id: iplib.py 1005 2006-01-12 08:39:26Z fperez $ +$Id: iplib.py 1007 2006-01-12 17:15:41Z vivainio $ """ #***************************************************************************** @@ -1180,6 +1180,7 @@ want to merge them back into the new files.""" % locals() if e.filename in ('','','', '',None): + return False try: if not ask_yes_no('Return to editor to correct syntax error? ' @@ -1887,7 +1888,7 @@ want to merge them back into the new files.""" % locals() # pre is needed, because it carries the leading whitespace. Otherwise # aliases won't work in indented sections. - line_out = '%sipalias("%s %s")' % (pre,iFun,esc_quotes(theRest)) + line_out = '%sipalias(%s)' % (pre,make_quoted_expr(iFun + " " + theRest)) self.log(line_out,continue_prompt) return line_out @@ -1897,36 +1898,27 @@ want to merge them back into the new files.""" % locals() #print 'line in :', `line` # dbg # Example of a special handler. Others follow a similar pattern. - if continue_prompt: # multi-line statements - if iFun.startswith('!!'): - print 'SyntaxError: !! is not allowed in multiline statements' - return pre - else: - cmd = ("%s %s" % (iFun[1:],theRest)) - line_out = '%sipsystem(r"""%s"""[:-1])' % (pre,cmd + "_") - else: # single-line input - if line.startswith('!!'): - # rewrite iFun/theRest to properly hold the call to %sx and - # the actual command to be executed, so handle_magic can work - # correctly - theRest = '%s %s' % (iFun[2:],theRest) - iFun = 'sx' - return self.handle_magic('%ssx %s' % (self.ESC_MAGIC,line[2:]), - continue_prompt,pre,iFun,theRest) - else: - cmd=line[1:] - line_out = '%sipsystem(r"""%s"""[:-1])' % (pre,cmd +"_") + if line.startswith('!!'): + # rewrite iFun/theRest to properly hold the call to %sx and + # the actual command to be executed, so handle_magic can work + # correctly + theRest = '%s %s' % (iFun[2:],theRest) + iFun = 'sx' + return self.handle_magic('%ssx %s' % (self.ESC_MAGIC,line[2:]), + continue_prompt,pre,iFun,theRest) + else: + cmd=line[1:] + line_out = '%sipsystem(%s)' % (pre,make_quoted_expr(cmd)) # update cache/log and return self.log(line_out,continue_prompt) return line_out def handle_magic(self, line, continue_prompt=None, pre=None,iFun=None,theRest=None): - """Execute magic functions. + """Execute magic functions.""" - Also log them with a prepended # so the log is clean Python.""" - cmd = '%sipmagic("%s")' % (pre,esc_quotes('%s %s' % (iFun,theRest))) + cmd = '%sipmagic(%s)' % (pre,make_quoted_expr(iFun + " " + theRest)) self.log(cmd,continue_prompt) #print 'in handle_magic, cmd=<%s>' % cmd # dbg return cmd diff --git a/doc/ChangeLog b/doc/ChangeLog index 772541e..1885494 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,14 @@ +2006-01-12 Ville Vainio + + * IPython/iplib.py.py (make_quoted_expr,handle_shell_escape): + Prettified and hardened string/backslash quoting with ipsystem(), + ipalias() and ipmagic(). Now even \ characters are passed to + %magics, !shell escapes and aliases exactly as they are in the + ipython command line. Should improve backslash experience, + particularly in Windows. %cd magic still doesn't support backslash + path delimiters, though. Also deleted all pretense of supporting + multiline command strings in !system or %magic commands. + 2006-01-12 Fernando Perez * IPython/ipstruct.py (Struct): Rename IPython.Struct to