Permalink
Browse files

shquote: add docstrings and a new quotify_list() function.

And associated tests.

Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
  • Loading branch information...
apenwarr committed Sep 5, 2011
1 parent 02bd2b5 commit b87097d8b769e3feb92c83f3556a6df911c32fb1
Showing with 81 additions and 1 deletion.
  1. +77 −0 lib/bup/shquote.py
  2. +4 −1 lib/bup/t/tshquote.py
View
@@ -47,6 +47,18 @@ def _quotesplit(line):
def quotesplit(line):
+ """Split 'line' into a list of offset,word tuples.
+
+ The words are produced after removing doublequotes, singlequotes, and
+ backslash escapes.
+
+ Note that this implementation isn't entirely sh-compatible. It only
+ dequotes words that *start* with a quote character, that is, a string like
+ hello"world"
+ will not have its quotes removed, while a string like
+ hello "world"
+ will be turned into [(0, 'hello'), (6, 'world')] (ie. quotes removed).
+ """
l = []
try:
for i in _quotesplit(line):
@@ -57,6 +69,17 @@ def quotesplit(line):
def unfinished_word(line):
+ """Returns the quotechar,word of any unfinished word at the end of 'line'.
+
+ You can use this to determine if 'line' is a completely parseable line
+ (ie. one that quotesplit() will finish successfully) or if you need
+ to read more bytes first.
+
+ Args:
+ line: an input string
+ Returns:
+ quotechar,word: the initial quote char (or None), and the partial word.
+ """
try:
for (wordstart,word) in _quotesplit(line):
pass
@@ -71,6 +94,19 @@ def unfinished_word(line):
def quotify(qtype, word, terminate):
+ """Return a string corresponding to given word, quoted using qtype.
+
+ The resulting string is dequotable using quotesplit() and can be
+ joined with other quoted strings by adding arbitrary whitespace
+ separators.
+
+ Args:
+ qtype: one of '', shquote.qq, or shquote.q
+ word: the string to quote. May contain arbitrary characters.
+ terminate: include the trailing quote character, if any.
+ Returns:
+ The quoted string.
+ """
if qtype == qq:
return qq + word.replace(qq, '\\"') + (terminate and qq or '')
elif qtype == q:
@@ -79,7 +115,48 @@ def quotify(qtype, word, terminate):
return re.sub(r'([\"\' \t\n\r])', r'\\\1', word)
+def quotify_list(words):
+ """Return a minimally-quoted string produced by quoting each word.
+
+ This calculates the qtype for each word depending on whether the word
+ already includes singlequote characters, doublequote characters, both,
+ or neither.
+
+ Args:
+ words: the list of words to quote.
+ Returns:
+ The resulting string, with quoted words separated by ' '.
+ """
+ wordout = []
+ for word in words:
+ qtype = q
+ if word and not re.search(r'[\s\"\']', word):
+ qtype = ''
+ elif q in word and qq not in word:
+ qtype = qq
+ wordout.append(quotify(qtype, word, True))
+ return ' '.join(wordout)
+
+
def what_to_add(qtype, origword, newword, terminate):
+ """Return a qtype that is needed to finish a partial word.
+
+ For example, given an origword of '\"frog' and a newword of '\"frogston',
+ returns either:
+ terminate=False: 'ston'
+ terminate=True: 'ston\"'
+
+ This is useful when calculating tab completion strings for readline.
+
+ Args:
+ qtype: the type of quoting to use (ie. the first character of origword)
+ origword: the original word that needs completion.
+ newword: the word we want it to be after completion. Must start with
+ origword.
+ terminate: true if we should add the actual quote character at the end.
+ Returns:
+ The string to append to origword to produce (quoted) newword.
+ """
if not newword.startswith(origword):
return ''
else:
View
@@ -2,7 +2,7 @@
from wvtest import *
def qst(line):
- return [s[1] for s in shquote.quotesplit(line)]
+ return [word for offset,word in shquote.quotesplit(line)]
@wvtest
def test_shquote():
@@ -42,3 +42,6 @@ def test_shquote():
WVPASSEQ(word, ' hammer "')
WVPASSEQ(shquote.what_to_add(qtype, word, " hammer \"time\"", True),
"time\\\"")
+
+ WVPASSEQ(shquote.quotify_list(['a', '', '"word"', "'third'", "'", "x y"]),
+ "a '' '\"word\"' \"'third'\" \"'\" 'x y'")

3 comments on commit b87097d

@lelutin

This comment has been minimized.

Show comment Hide comment
@lelutin

lelutin Jul 25, 2012

Contributor

hmm.. the docstrings are a good addition, but since the quotify_list() function is not used anywhere, yet, I'm wondering why it was added. care to share some light on my cluelessness?

Contributor

lelutin replied Jul 25, 2012

hmm.. the docstrings are a good addition, but since the quotify_list() function is not used anywhere, yet, I'm wondering why it was added. care to share some light on my cluelessness?

@apenwarr

This comment has been minimized.

Show comment Hide comment
@apenwarr

apenwarr Jul 25, 2012

Owner
Owner

apenwarr replied Jul 25, 2012

@lelutin

This comment has been minimized.

Show comment Hide comment
@lelutin

lelutin Jul 25, 2012

Contributor

bah fair enough. we'll probably want to rebase the dev branches on top of that just to make sure merging is as painless as possible when we're ready to do it.

Contributor

lelutin replied Jul 25, 2012

bah fair enough. we'll probably want to rebase the dev branches on top of that just to make sure merging is as painless as possible when we're ready to do it.

Please sign in to comment.