]> arthur.barton.de Git - bup.git/commitdiff
shquote: add docstrings and a new quotify_list() function.
authorAvery Pennarun <apenwarr@gmail.com>
Mon, 5 Sep 2011 03:06:02 +0000 (23:06 -0400)
committerAvery Pennarun <apenwarr@gmail.com>
Wed, 25 Jul 2012 03:11:42 +0000 (23:11 -0400)
And associated tests.

Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
lib/bup/shquote.py
lib/bup/t/tshquote.py

index dc339ec8c1a1ea3dfdac1bbed921f56ee08daafe..a3cd4c4846114d17be481a398b92a84abf047c6c 100644 (file)
@@ -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:
index 15b06ec1a53992435cf91fb529d4f85c77367727..a663453bba84765555f5ce5f3ad6926216b7a8f4 100644 (file)
@@ -2,7 +2,7 @@ from bup import shquote
 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'")