Update ninja_syntax.py and tests to reflect '$ ' syntax.
authorJeremy Apthorp <jeremya@chromium.org>
Mon, 28 Nov 2011 03:27:02 +0000 (14:27 +1100)
committerJeremy Apthorp <jeremya@chromium.org>
Tue, 29 Nov 2011 05:36:33 +0000 (16:36 +1100)
misc/ninja_syntax.py
misc/ninja_test.py

index 6e8a87c..06fe3cb 100644 (file)
@@ -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):
index 762fe16..481912e 100755 (executable)
@@ -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()