7 class QuoteError(Exception):
11 def _quotesplit(line):
16 for i in range(len(line)):
19 if inquote == q and c != q:
20 word += '\\' # single-q backslashes can only quote single-q
27 # this is un-sh-like, but do it for sanity when autocompleting
28 yield (wordstart, word)
31 elif not inquote and not word and (c == q or c == qq):
32 # the 'not word' constraint on this is un-sh-like, but do it
33 # for sanity when autocompleting
36 elif not inquote and c in [' ', '\n', '\r', '\t']:
38 yield (wordstart, word)
44 yield (wordstart, word)
45 if inquote or inescape or word:
50 """Split 'line' into a list of offset,word tuples.
52 The words are produced after removing doublequotes, singlequotes, and
55 Note that this implementation isn't entirely sh-compatible. It only
56 dequotes words that *start* with a quote character, that is, a string like
58 will not have its quotes removed, while a string like
60 will be turned into [(0, 'hello'), (6, 'world')] (ie. quotes removed).
64 for i in _quotesplit(line):
71 def unfinished_word(line):
72 """Returns the quotechar,word of any unfinished word at the end of 'line'.
74 You can use this to determine if 'line' is a completely parseable line
75 (ie. one that quotesplit() will finish successfully) or if you need
76 to read more bytes first.
81 quotechar,word: the initial quote char (or None), and the partial word.
84 for (wordstart,word) in _quotesplit(line):
87 firstchar = line[wordstart]
88 if firstchar in [q, qq]:
89 return (firstchar, word)
96 def quotify(qtype, word, terminate):
97 """Return a string corresponding to given word, quoted using qtype.
99 The resulting string is dequotable using quotesplit() and can be
100 joined with other quoted strings by adding arbitrary whitespace
104 qtype: one of '', shquote.qq, or shquote.q
105 word: the string to quote. May contain arbitrary characters.
106 terminate: include the trailing quote character, if any.
111 return qq + word.replace(qq, '\\"') + (terminate and qq or '')
113 return q + word.replace(q, "\\'") + (terminate and q or '')
115 return re.sub(r'([\"\' \t\n\r])', r'\\\1', word)
118 def quotify_list(words):
119 """Return a minimally-quoted string produced by quoting each word.
121 This calculates the qtype for each word depending on whether the word
122 already includes singlequote characters, doublequote characters, both,
126 words: the list of words to quote.
128 The resulting string, with quoted words separated by ' '.
133 if word and not re.search(r'[\s\"\']', word):
135 elif q in word and qq not in word:
137 wordout.append(quotify(qtype, word, True))
138 return ' '.join(wordout)
141 def what_to_add(qtype, origword, newword, terminate):
142 """Return a qtype that is needed to finish a partial word.
144 For example, given an origword of '\"frog' and a newword of '\"frogston',
146 terminate=False: 'ston'
147 terminate=True: 'ston\"'
149 This is useful when calculating tab completion strings for readline.
152 qtype: the type of quoting to use (ie. the first character of origword)
153 origword: the original word that needs completion.
154 newword: the word we want it to be after completion. Must start with
156 terminate: true if we should add the actual quote character at the end.
158 The string to append to origword to produce (quoted) newword.
160 if not newword.startswith(origword):
163 qold = quotify(qtype, origword, terminate=False)
164 return quotify(qtype, newword, terminate=terminate)[len(qold):]