diff options
-rw-r--r-- | misc/ninja_syntax.py | 55 | ||||
-rwxr-xr-x | misc/ninja_test.py | 18 |
2 files changed, 60 insertions, 13 deletions
diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py index 6e8a87c..06fe3cb 100644 --- a/misc/ninja_syntax.py +++ b/misc/ninja_syntax.py @@ -8,6 +8,10 @@ use Python. """ import textwrap +import re + +def escape_spaces(word): + return word.replace('$ ','$$ ').replace(' ','$ ') class Writer(object): def __init__(self, output, width=78): @@ -43,15 +47,19 @@ class Writer(object): variables=None): outputs = self._as_list(outputs) all_inputs = self._as_list(inputs)[:] + out_outputs = map(escape_spaces, outputs) + all_inputs = map(escape_spaces, all_inputs) if implicit: + implicit = map(escape_spaces, self._as_list(implicit)) all_inputs.append('|') - all_inputs.extend(self._as_list(implicit)) + all_inputs.extend(implicit) if order_only: + order_only = map(escape_spaces, self._as_list(order_only)) all_inputs.append('||') - all_inputs.extend(self._as_list(order_only)) + all_inputs.extend(order_only) - self._line('build %s: %s %s' % (' '.join(outputs), + self._line('build %s: %s %s' % (' '.join(out_outputs), rule, ' '.join(all_inputs))) @@ -76,22 +84,43 @@ class Writer(object): while len(text) > self.width: # The text is too wide; wrap if possible. - # Find the rightmost space that would obey our width constraint. + self.output.write(leading_space) + available_space = self.width - len(leading_space) - len(' $') - space = text.rfind(' ', 0, available_space) - if space < 0: - # No such space; just use the first space we can find. - space = text.find(' ', available_space) - if space < 0: - # Give up on breaking. - break - self.output.write(leading_space + text[0:space] + ' $\n') - text = text[space+1:] + # Write as much as we can into this line. + done = False + written_stuff = False + while available_space > 0: + space = re.search('((\$\$)+([^$]|^)|[^$]|^) ', text) + if space: + space_idx = space.start() + 1 + else: + # No spaces left. + done = True + break + + if space_idx > available_space: + # We're out of space. + if written_stuff: + # See if we can fit it on the next line. + break + # If we haven't written anything yet on this line, don't + # try to wrap. + self.output.write(text[0:space_idx] + ' ') + written_stuff = True + text = text[space_idx+1:] + available_space -= space_idx+1 + + self.output.write('$\n') # Subsequent lines are continuations, so indent them. leading_space = ' ' * (indent+2) + if done: + # No more spaces, so bail. + break + self.output.write(leading_space + text + '\n') def _as_list(self, input): diff --git a/misc/ninja_test.py b/misc/ninja_test.py index 762fe16..481912e 100755 --- a/misc/ninja_test.py +++ b/misc/ninja_test.py @@ -20,6 +20,7 @@ from StringIO import StringIO import ninja_syntax LONGWORD = 'a' * 10 +LONGWORDWITHSPACES = 'a'*5 + '$ ' + 'a'*5 INDENT = ' ' class TestLineWordWrap(unittest.TestCase): @@ -48,5 +49,22 @@ class TestLineWordWrap(unittest.TestCase): ' ' + INDENT + 'y']) + '\n', self.out.getvalue()) + def test_escaped_spaces(self): + self.n._line(' '.join(['x', LONGWORDWITHSPACES, 'y'])) + self.assertEqual(' $\n'.join(['x', + INDENT + LONGWORDWITHSPACES, + INDENT + 'y']) + '\n', + self.out.getvalue()) + + def test_fit_many_words(self): + self.n = ninja_syntax.Writer(self.out, width=78) + self.n._line('command = cd ../../chrome; python ../tools/grit/grit/format/repack.py ../out/Debug/obj/chrome/chrome_dll.gen/repack/theme_resources_large.pak ../out/Debug/gen/chrome/theme_resources_large.pak', 1) + self.assertEqual('''\ + command = cd ../../chrome; python ../tools/grit/grit/format/repack.py $ + ../out/Debug/obj/chrome/chrome_dll.gen/repack/theme_resources_large.pak $ + ../out/Debug/gen/chrome/theme_resources_large.pak +''', + self.out.getvalue()) + if __name__ == '__main__': unittest.main() |