Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library source_writer; | 5 library source_writer; |
| 6 | 6 |
| 7 | 7 |
| 8 class Line { | 8 class Line { |
| 9 | 9 |
| 10 final tokens = <LineToken>[]; | 10 final tokens = <LineToken>[]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 56 | 56 |
| 57 /// A simple line breaking [LinePrinter] | 57 /// A simple line breaking [LinePrinter] |
| 58 class SimpleLineBreaker extends LinePrinter { | 58 class SimpleLineBreaker extends LinePrinter { |
| 59 | 59 |
| 60 final chunks = <Chunk>[]; | 60 final chunks = <Chunk>[]; |
| 61 final int maxLength; | 61 final int maxLength; |
| 62 | 62 |
| 63 SimpleLineBreaker(this.maxLength); | 63 SimpleLineBreaker(this.maxLength); |
| 64 | 64 |
| 65 String printLine(Line line) { | 65 String printLine(Line line) { |
| 66 //TODO(pquitslund): implement | 66 var buf = new StringBuffer(); |
| 67 var chunks = breakLine(line); | |
| 68 for (var i = 0; i < chunks.length; ++i) { | |
| 69 if (i > 0) { | |
| 70 buf.write(indent(chunks[i])); | |
| 71 } else { | |
| 72 buf.write(chunks[i]); | |
| 73 } | |
| 74 } | |
| 75 return buf.toString(); | |
| 76 } | |
| 77 | |
| 78 String indent(Chunk chunk) { | |
| 79 return '\n' + chunk.toString(); | |
| 67 } | 80 } |
| 68 | 81 |
| 69 List<Chunk> breakLine(Line line) { | 82 List<Chunk> breakLine(Line line) { |
| 70 | 83 |
| 71 var chunks = <Chunk>[]; | 84 var chunks = <Chunk>[]; |
| 72 | 85 |
| 73 // The current unbroken line | 86 // The current unbroken line |
| 74 var current = new Chunk(maxLength: maxLength); | 87 var current = new Chunk(maxLength: maxLength); |
| 75 | 88 |
| 76 // A tentative working chunk that will either start a new line or get | 89 // A tentative working chunk that will either start a new line or get |
| 77 // absorbed into 'current' | 90 // absorbed into 'current' |
| 78 var work = new Chunk(maxLength: maxLength); | 91 var work = new Chunk(maxLength: maxLength); |
| 79 | 92 |
| 80 line.tokens.forEach((tok) { | 93 line.tokens.forEach((tok) { |
| 81 | 94 |
| 82 if (goodStart(tok, work)) { | 95 if (goodStart(tok, work)) { |
| 83 if (current.fits(work)) { | 96 if (current.fits(work)) { |
| 84 current.add(work); | 97 current.add(work); |
| 85 } else { | 98 } else { |
| 86 if (current.length > 0) { | 99 if (current.length > 0) { |
| 87 chunks.add(current); | 100 chunks.add(current); |
| 88 } | 101 } |
| 89 current = work; | 102 current = work; |
| 90 } | 103 } |
| 91 work = new Chunk(start: tok, maxLength: maxLength - current.length); | 104 work = new Chunk(start: tok, maxLength: maxLength - current.length); |
| 92 } else { | 105 } else { |
| 93 if (work.fits(tok)) { | 106 if (work.fits(tok)) { |
| 94 work.add(tok); | 107 work.add(tok); |
| 95 } else { | 108 } else { |
| 96 current.add(work); | 109 if (!isWhitespace(work)) { |
| 110 current.add(work); | |
| 111 } | |
| 97 if (current.length > 0) { | 112 if (current.length > 0) { |
| 98 chunks.add(current); | 113 chunks.add(current); |
| 99 current = new Chunk(maxLength: maxLength); | 114 current = new Chunk(maxLength: maxLength); |
| 100 } | 115 } |
| 101 work = new Chunk(maxLength: maxLength); | 116 work = new Chunk(maxLength: maxLength); |
| 102 work.add(tok); | 117 work.add(tok); |
| 103 } | 118 } |
| 104 } | 119 } |
| 105 | 120 |
| 106 }); | 121 }); |
| 107 | 122 |
| 108 current.add(work); | 123 current.add(work); |
| 109 if (current.length > 0) { | 124 if (current.length > 0) { |
| 110 chunks.add(current); | 125 chunks.add(current); |
| 111 } | 126 } |
| 112 return chunks; | 127 return chunks; |
| 113 } | 128 } |
| 114 | 129 |
| 130 bool isWhitespace(Chunk chunk) { | |
|
pquitslund
2014/01/13 16:39:55
This *can't* be the best way to test this... Idea
| |
| 131 var str = chunk.buffer.toString(); | |
| 132 return str.lastIndexOf(new RegExp(r"(\w+)")) == str.length - 1; | |
| 133 } | |
| 134 | |
| 115 /// Test whether this token is a good start for a new working chunk | 135 /// Test whether this token is a good start for a new working chunk |
| 116 bool goodStart(LineToken tok, Chunk workingChunk) => | 136 bool goodStart(LineToken tok, Chunk workingChunk) => |
| 117 tok is SpaceToken && tok.breakWeight >= workingChunk.start.breakWeight; | 137 tok is SpaceToken && tok.breakWeight >= workingChunk.start.breakWeight; |
| 118 | 138 |
| 119 } | 139 } |
| 120 | 140 |
| 121 | 141 |
| 122 /// Special token indicating a line start | 142 /// Special token indicating a line start |
| 123 final LINE_START = new SpaceToken(0); | 143 final LINE_START = new SpaceToken(0); |
| 124 | 144 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 141 /// Describes a piece of text in a [Line]. | 161 /// Describes a piece of text in a [Line]. |
| 142 abstract class LineText { | 162 abstract class LineText { |
| 143 int get length; | 163 int get length; |
| 144 void addTo(Chunk chunk); | 164 void addTo(Chunk chunk); |
| 145 } | 165 } |
| 146 | 166 |
| 147 | 167 |
| 148 /// A working piece of text used in calculating line breaks | 168 /// A working piece of text used in calculating line breaks |
| 149 class Chunk implements LineText { | 169 class Chunk implements LineText { |
| 150 | 170 |
| 151 final buffer = new StringBuffer(); | 171 final StringBuffer buffer = new StringBuffer(); |
| 152 | 172 |
| 153 int maxLength; | 173 int maxLength; |
| 154 SpaceToken start; | 174 SpaceToken start; |
| 155 | 175 |
| 156 Chunk({this.start, this.maxLength}) { | 176 Chunk({this.start, this.maxLength}) { |
| 157 if (start == null) { | 177 if (start == null) { |
| 158 start = LINE_START; | 178 start = LINE_START; |
| 159 } | 179 } |
| 160 } | 180 } |
| 161 | 181 |
| 162 bool fits(LineText text) => length + text.length < maxLength; | 182 bool fits(LineText text) => length + text.length < maxLength; |
| 163 | 183 |
| 164 int get length => start.value.length + buffer.length; | 184 int get length => start.value.length + buffer.length; |
| 165 | 185 |
| 166 void add(LineText text) { | 186 void add(LineText text) { |
| 167 text.addTo(this); | 187 text.addTo(this); |
| 168 } | 188 } |
| 169 | 189 |
| 170 String toString() => buffer.toString().trim(); | 190 String toString() => buffer.toString(); |
| 171 | 191 |
| 172 void addTo(Chunk chunk) { | 192 void addTo(Chunk chunk) { |
| 173 chunk.buffer.write(start.value); | 193 chunk.buffer.write(start.value); |
| 174 chunk.buffer.write(buffer.toString()); | 194 chunk.buffer.write(buffer.toString()); |
| 175 } | 195 } |
| 176 } | 196 } |
| 177 | 197 |
| 178 | 198 |
| 179 class LineToken implements LineText { | 199 class LineToken implements LineText { |
| 180 | 200 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 Line currentLine; | 239 Line currentLine; |
| 220 | 240 |
| 221 final String lineSeparator; | 241 final String lineSeparator; |
| 222 int indentCount = 0; | 242 int indentCount = 0; |
| 223 | 243 |
| 224 LinePrinter linePrinter; | 244 LinePrinter linePrinter; |
| 225 LineToken _lastToken; | 245 LineToken _lastToken; |
| 226 | 246 |
| 227 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE, | 247 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE, |
| 228 int maxLineLength: 80}) { | 248 int maxLineLength: 80}) { |
| 229 linePrinter = new SimpleLinePrinter(); | 249 linePrinter = new SimpleLineBreaker(maxLineLength); |
| 230 currentLine = new Line(indent: indentCount, printer: linePrinter); | 250 currentLine = new Line(indent: indentCount, printer: linePrinter); |
| 231 } | 251 } |
| 232 | 252 |
| 233 LineToken get lastToken => _lastToken; | 253 LineToken get lastToken => _lastToken; |
| 234 | 254 |
| 235 _addToken(LineToken token) { | 255 _addToken(LineToken token) { |
| 236 _lastToken = token; | 256 _lastToken = token; |
| 237 currentLine.addToken(token); | 257 currentLine.addToken(token); |
| 238 } | 258 } |
| 239 | 259 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 262 | 282 |
| 263 void println(String s) { | 283 void println(String s) { |
| 264 print(s); | 284 print(s); |
| 265 newline(); | 285 newline(); |
| 266 } | 286 } |
| 267 | 287 |
| 268 void space() { | 288 void space() { |
| 269 spaces(1); | 289 spaces(1); |
| 270 } | 290 } |
| 271 | 291 |
| 272 void spaces(n, {breakWeight: null}) { | 292 void spaces(n, {breakWeight: DEFAULT_SPACE_WEIGHT}) { |
| 273 currentLine.addSpaces(n, breakWeight: breakWeight); | 293 currentLine.addSpaces(n, breakWeight: breakWeight); |
| 274 } | 294 } |
| 275 | 295 |
| 276 void unindent() { | 296 void unindent() { |
| 277 --indentCount; | 297 --indentCount; |
| 278 } | 298 } |
| 279 | 299 |
| 280 String toString() { | 300 String toString() { |
| 281 var source = new StringBuffer(buffer.toString()); | 301 var source = new StringBuffer(buffer.toString()); |
| 282 if (!currentLine.isWhitespace()) { | 302 if (!currentLine.isWhitespace()) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 | 354 |
| 335 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); | 355 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); |
| 336 | 356 |
| 337 String repeat(String ch, int times) { | 357 String repeat(String ch, int times) { |
| 338 var sb = new StringBuffer(); | 358 var sb = new StringBuffer(); |
| 339 for (var i = 0; i < times; ++i) { | 359 for (var i = 0; i < times; ++i) { |
| 340 sb.write(ch); | 360 sb.write(ch); |
| 341 } | 361 } |
| 342 return sb.toString(); | 362 return sb.toString(); |
| 343 } | 363 } |
| OLD | NEW |