this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: `Window.printSegments` correctly prints all non-trailing whitespace

I'm told it's not unusual in the web world for multiple whitespace
characters to be consumed as a single space. If that is the intention
for `.word` wrap, that's fine with me! If not, this PR correctly
prints all non-trailing whitespace.

I also chose to consume a `\r\n` sequence as intending a single newline,
while all other sequences of `\r` and `\n` should produce multiple newlines.

authored by

Rylee Lyman and committed by
Tim Culverhouse
74fb1307 fcb705ad

+55 -75
+55 -75
src/Window.zig
··· 328 328 .word => { 329 329 var col: usize = opts.col_offset; 330 330 var overflow: bool = false; 331 - var soft_wrapped: bool = false; 332 331 for (segments) |segment| { 333 332 var start: usize = 0; 334 - var i: usize = 0; 335 - while (i < segment.text.len) : (i += 1) { 336 - // for (segment.text, 0..) |b, i| { 337 - const b = segment.text[i]; 338 - const end = switch (b) { 339 - ' ', 340 - '\r', 341 - '\n', 342 - => i, 343 - else => if (i != segment.text.len - 1) continue else i + 1, 344 - }; 345 - const word = segment.text[start..end]; 346 - // find the start of the next word 347 - start = while (i + 1 < segment.text.len) : (i += 1) { 348 - if (segment.text[i + 1] == ' ') continue; 349 - break i + 1; 350 - } else i; 351 - const width = self.gwidth(word); 352 - const non_wsp_width: usize = for (word, 0..) |wb, wi| { 353 - if (wb == '\r' or wb == '\n') { 354 - row += 1; 355 - col = 0; 356 - break width -| wi -| 1; 333 + var tokenizer = std.mem.tokenizeAny(u8, segment.text, "\r\n"); 334 + while (tokenizer.peek() != null) { 335 + const returns = segment.text[start..tokenizer.index]; 336 + const line = tokenizer.next().?; 337 + start = tokenizer.index; 338 + var i: usize = 0; 339 + while (i < returns.len) : (i += 1) { 340 + const b = returns[i]; 341 + if (b == '\r' and i + 1 < returns.len and returns[i + 1] == '\n') { 342 + i += 1; 357 343 } 358 - if (wb != ' ') break width - wi; 359 - } else 0; 360 - 361 - if (width + col > self.width and non_wsp_width < self.width) { 362 - // wrap 363 344 row += 1; 364 345 col = 0; 365 - soft_wrapped = true; 366 346 } 367 - if (row >= self.height) { 368 - overflow = true; 369 - break; 370 - } 371 - // if we are soft wrapped, (col == 0 and row > 0), then trim 372 - // leading spaces 373 - const printed_word = if (soft_wrapped) 374 - std.mem.trimLeft(u8, word, " ") 375 - else 376 - word; 377 - defer soft_wrapped = false; 378 - var iter = self.screen.unicode.graphemeIterator(printed_word); 379 - while (iter.next()) |grapheme| { 380 - const s = grapheme.bytes(printed_word); 381 - const w = self.gwidth(s); 382 - if (opts.commit) self.writeCell(col, row, .{ 383 - .char = .{ 384 - .grapheme = s, 385 - .width = w, 386 - }, 387 - .style = segment.style, 388 - .link = segment.link, 389 - }); 390 - col += w; 347 + var iter = std.mem.tokenizeScalar(u8, line, ' '); 348 + var ws_start: usize = 0; 349 + while (iter.peek() != null) { 350 + const whitespace = line[ws_start..iter.index]; 351 + const word = iter.next().?; 352 + ws_start = iter.index; 353 + var j: usize = 0; 354 + while (j < whitespace.len) : (j += 1) { 355 + if (opts.commit) self.writeCell(col, row, .{ 356 + .char = .{ 357 + .grapheme = " ", 358 + .width = 1, 359 + }, 360 + .style = segment.style, 361 + .link = segment.link, 362 + }); 363 + col += 1; 364 + } 391 365 if (col >= self.width) { 366 + col = 0; 367 + row += 1; 368 + } 369 + const width = self.gwidth(word); 370 + if (width + col > self.width and width < self.width) { 392 371 row += 1; 393 372 col = 0; 394 373 } 395 - } 396 - switch (b) { 397 - ' ' => { 398 - if (col > 0) { 399 - if (opts.commit) self.writeCell(col, row, .{ 400 - .char = .{ 401 - .grapheme = " ", 402 - .width = 1, 403 - }, 404 - .style = segment.style, 405 - .link = segment.link, 406 - }); 407 - col += 1; 374 + if (row >= self.height) { 375 + overflow = true; 376 + break; 377 + } 378 + 379 + var grapheme_iterator = self.screen.unicode.graphemeIterator(word); 380 + while (grapheme_iterator.next()) |grapheme| { 381 + const s = grapheme.bytes(word); 382 + const w = self.gwidth(s); 383 + if (opts.commit) self.writeCell(col, row, .{ 384 + .char = .{ 385 + .grapheme = s, 386 + .width = w, 387 + }, 388 + .style = segment.style, 389 + .link = segment.link, 390 + }); 391 + col += w; 392 + if (col >= self.width) { 393 + row += 1; 394 + col = 0; 408 395 } 409 - }, 410 - '\r', 411 - '\n', 412 - => { 413 - col = 0; 414 - row += 1; 415 - }, 416 - else => {}, 396 + } 417 397 } 418 398 } 419 399 }