Skip to content

Loading…

Dollar escape #1025

Merged
merged 3 commits into from

2 participants

@takluyver
IPython member

As pointed out by @stefanv and @minrk on #822, it should be possible to use a raw $ in shell commands, e.g. for environment variables. This allows that, with the "$$HOME" syntax.

@minrk
IPython member

Looks good to me. Do you want to add a test to cover '${foo}' -> '$bar'? That's one probably quite rare use case that I've had to deal with long ago, where the shell variable name is a Python variable you want to expand. This works just fine right now with the syntax above, but we might add the test case anyway.

@takluyver
IPython member

Yep, good idea. Done.

@minrk
IPython member

Thanks, I say go ahead and merge.

@takluyver takluyver merged commit aa30a66 into ipython:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 17 additions and 4 deletions.
  1. +4 −1 IPython/core/tests/test_interactiveshell.py
  2. +4 −0 IPython/utils/tests/test_text.py
  3. +9 −3 IPython/utils/text.py
View
5 IPython/core/tests/test_interactiveshell.py
@@ -201,7 +201,10 @@ def test_drop_by_id(self):
def test_var_expand(self):
ip = get_ipython()
- ip.user_ns['f'] = 'Ca\xc3\xb1o'
+ ip.user_ns['f'] = u'Ca\xf1o'
+ self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
+
+ ip.user_ns['f'] = b'Ca\xc3\xb1o'
# This should not raise any exception:
ip.var_expand(u'echo $f')
View
4 IPython/utils/tests/test_text.py
@@ -107,3 +107,7 @@ def test_dollar_formatter():
nt.assert_equals(s, "12")
s = f.format("$n/{stuff[:5]}", **ns)
nt.assert_equals(s, "12/hello")
+ s = f.format("$n $$HOME", **ns)
+ nt.assert_equals(s, "12 $HOME")
+ s = f.format("${foo}", foo="HOME")
+ nt.assert_equals(s, "$HOME")
View
12 IPython/utils/text.py
@@ -663,20 +663,26 @@ class DollarFormatter(FullEvalFormatter):
In [4]: f.format('$a or {b}', a=1, b=2)
Out[4]: u'1 or 2'
"""
- _dollar_pattern = re.compile("(.*)\$([\w\.]+)")
+ _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
def parse(self, fmt_string):
for literal_txt, field_name, format_spec, conversion \
in Formatter.parse(self, fmt_string):
# Find $foo patterns in the literal text.
continue_from = 0
+ txt = ""
for m in self._dollar_pattern.finditer(literal_txt):
new_txt, new_field = m.group(1,2)
- yield (new_txt, new_field, "", None)
+ # $$foo --> $foo
+ if new_field.startswith("$"):
+ txt += new_txt + new_field
+ else:
+ yield (txt + new_txt, new_field, "", None)
+ txt = ""
continue_from = m.end()
# Re-yield the {foo} style pattern
- yield (literal_txt[continue_from:], field_name, format_spec, conversion)
+ yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
def columnize(items, separator=' ', displaywidth=80):
Something went wrong with that request. Please try again.