this repo has no description
13
fork

Configure Feed

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

widgets(terminal): implement escapes, fix scrollDown

+128 -44
-3
src/widgets/terminal/Command.zig
··· 47 47 // exec 48 48 const err = std.posix.execvpeZ(argv_buf.ptr[0].?, argv_buf.ptr, envp); 49 49 _ = err catch {}; 50 - @panic("a"); 51 - // const EOT = "\x04"; 52 - // _ = std.posix.write(self.pty.tty, EOT) catch {}; 53 50 } 54 51 55 52 var act = posix.Sigaction{
+45 -16
src/widgets/terminal/Screen.zig
··· 166 166 self: *Screen, 167 167 grapheme: []const u8, 168 168 width: u8, 169 - ) void { 170 - // TODO: wrap mode handling 171 - if (self.cursor.col + width > self.width) { 172 - self.cursor.col = 0; 173 - self.cursor.row += 1; 169 + wrap: bool, 170 + ) !void { 171 + if (self.cursor.pending_wrap) { 172 + try self.index(); 173 + self.cursor.col = self.scrolling_region.left; 174 174 } 175 175 if (self.cursor.col >= self.width) return; 176 176 if (self.cursor.row >= self.height) return; ··· 195 195 self.buf[i].width = width; 196 196 self.buf[i].dirty = true; 197 197 198 + if (wrap and self.cursor.col >= self.width - 1) self.cursor.pending_wrap = true; 198 199 self.cursor.col += width; 199 200 } 200 201 ··· 333 334 } 334 335 335 336 pub fn cursorRight(self: *Screen, n: usize) void { 337 + self.cursor.pending_wrap = false; 336 338 if (self.withinScrollingRegion()) 337 339 self.cursor.col = @min( 338 340 self.cursor.col + n, ··· 341 343 else 342 344 self.cursor.col = @min( 343 345 self.cursor.col + n, 344 - self.width, 346 + self.width - 1, 345 347 ); 346 348 } 347 349 ··· 418 420 pub fn insertLine(self: *Screen, n: usize) !void { 419 421 if (n == 0) return; 420 422 423 + self.cursor.pending_wrap = false; 421 424 // Don't insert if outside scroll region 422 425 if (!self.withinScrollingRegion()) return; 423 426 424 - self.cursor.pending_wrap = false; 427 + const adjusted_n = @min(self.scrolling_region.bottom - self.cursor.row, n); 428 + const stride = (self.width) * adjusted_n; 425 429 426 - // Number of rows from here to top of scroll region or n 427 - const cnt = @min(self.cursor.row - self.scrolling_region.top + 1, n); 428 - const stride = (self.width) * cnt; 430 + var row: usize = self.scrolling_region.bottom; 431 + while (row >= self.scrolling_region.top + adjusted_n) : (row -|= 1) { 432 + var col: usize = self.scrolling_region.left; 433 + while (col <= self.scrolling_region.right) : (col += 1) { 434 + const i = (row * self.width) + col; 435 + try self.buf[i].copyFrom(self.buf[i - stride]); 436 + } 437 + } 429 438 430 - var row: usize = self.scrolling_region.bottom; 431 - while (row > self.scrolling_region.top) : (row -= 1) { 439 + row = self.scrolling_region.top; 440 + while (row < self.scrolling_region.top + adjusted_n) : (row += 1) { 432 441 var col: usize = self.scrolling_region.left; 433 442 while (col <= self.scrolling_region.right) : (col += 1) { 434 443 const i = (row * self.width) + col; 435 - if (row - cnt < self.scrolling_region.top) 436 - self.buf[i].erase(self.cursor.style.bg) 437 - else 438 - try self.buf[i].copyFrom(self.buf[i - stride]); 444 + self.buf[i].erase(self.cursor.style.bg); 439 445 } 440 446 } 441 447 } ··· 480 486 self.buf[col].erase(self.cursor.style.bg); 481 487 } 482 488 } 489 + 490 + pub fn reverseIndex(self: *Screen) !void { 491 + if (self.cursor.row != self.scrolling_region.top or 492 + self.cursor.col < self.scrolling_region.left or 493 + self.cursor.col > self.scrolling_region.right) 494 + self.cursorUp(1) 495 + else 496 + try self.scrollDown(1); 497 + } 498 + 499 + pub fn scrollDown(self: *Screen, n: usize) !void { 500 + const cur_row = self.cursor.row; 501 + const cur_col = self.cursor.col; 502 + const wrap = self.cursor.pending_wrap; 503 + defer { 504 + self.cursor.row = cur_row; 505 + self.cursor.col = cur_col; 506 + self.cursor.pending_wrap = wrap; 507 + } 508 + self.cursor.col = self.scrolling_region.left; 509 + self.cursor.row = self.scrolling_region.top; 510 + try self.insertLine(n); 511 + }
+59 -25
src/widgets/terminal/Terminal.zig
··· 34 34 35 35 pub const Mode = struct { 36 36 origin: bool = false, 37 + autowrap: bool = true, 37 38 cursor: bool = true, 38 39 sync: bool = false, 39 40 }; ··· 203 204 } 204 205 } 205 206 206 - if (self.mode.cursor) { 207 - win.setCursorShape(self.front_screen.cursor.shape); 208 - win.showCursor(self.front_screen.cursor.col, self.front_screen.cursor.row); 209 - } else win.hideCursor(); 207 + // if (self.mode.cursor) { 208 + win.setCursorShape(self.front_screen.cursor.shape); 209 + win.showCursor(self.front_screen.cursor.col, self.front_screen.cursor.row); 210 + // } else win.hideCursor(); 210 211 } 211 212 212 213 pub fn tryEvent(self: *Terminal) ?Event { ··· 265 266 const gr = g.bytes(str); 266 267 // TODO: use actual instead of .unicode 267 268 const w = try vaxis.gwidth.gwidth(gr, .unicode, &self.unicode.width_data); 268 - self.back_screen.print(gr, @truncate(w)); 269 + try self.back_screen.print(gr, @truncate(w), self.mode.autowrap); 269 270 } 270 271 }, 271 272 .c0 => |b| try self.handleC0(b), 272 - .escape => |_| {}, // std.log.err("unhandled escape: {s}", .{str}), 273 + .escape => |esc| { 274 + const final = esc[esc.len - 1]; 275 + switch (final) { 276 + 'B' => {}, // TODO: handle charsets 277 + // Index 278 + 'D' => try self.back_screen.index(), 279 + // Next Line 280 + 'E' => { 281 + try self.back_screen.index(); 282 + self.carriageReturn(); 283 + }, 284 + // Horizontal Tab Set 285 + 'H' => { 286 + const already_set: bool = for (self.tab_stops.items) |ts| { 287 + if (ts == self.back_screen.cursor.col) break true; 288 + } else false; 289 + if (already_set) continue; 290 + try self.tab_stops.append(@truncate(self.back_screen.cursor.col)); 291 + std.mem.sort(u16, self.tab_stops.items, {}, std.sort.asc(u16)); 292 + }, 293 + // Reverse Index 294 + 'M' => try self.back_screen.reverseIndex(), 295 + else => std.log.err("unhandled escape: {s}", .{esc}), 296 + } 297 + }, 273 298 .ss2 => |ss2| std.log.err("unhandled ss2: {c}", .{ss2}), 274 299 .ss3 => |ss3| std.log.err("unhandled ss3: {c}", .{ss3}), 275 300 .csi => |seq| { ··· 288 313 }, 289 314 // Cursor Right 290 315 'C' => { 291 - self.back_screen.cursor.pending_wrap = false; 292 316 var iter = seq.iterator(u16); 293 317 const delta = iter.next() orelse 1; 294 318 self.back_screen.cursorRight(delta); ··· 318 342 var iter = seq.iterator(u16); 319 343 const col = iter.next() orelse 1; 320 344 self.back_screen.cursor.col = col -| 1; 345 + if (self.back_screen.cursor.col < self.back_screen.scrolling_region.left) 346 + self.back_screen.cursor.col = self.back_screen.scrolling_region.left; 347 + if (self.back_screen.cursor.col > self.back_screen.scrolling_region.right) 348 + self.back_screen.cursor.col = self.back_screen.scrolling_region.right; 349 + self.back_screen.cursor.pending_wrap = false; 321 350 }, 322 351 // Cursor Absolute Position 323 352 'H', 'f' => { ··· 326 355 const col = iter.next() orelse 1; 327 356 self.back_screen.cursor.col = col -| 1; 328 357 self.back_screen.cursor.row = row -| 1; 358 + self.back_screen.cursor.pending_wrap = false; 329 359 }, 330 360 // Cursor Horizontal Tab 331 361 'I' => { ··· 396 426 'T' => { 397 427 var iter = seq.iterator(u16); 398 428 const n = iter.next() orelse 1; 399 - const cur_row = self.back_screen.cursor.row; 400 - const cur_col = self.back_screen.cursor.col; 401 - const wrap = self.back_screen.cursor.pending_wrap; 402 - defer { 403 - self.back_screen.cursor.row = cur_row; 404 - self.back_screen.cursor.col = cur_col; 405 - self.back_screen.cursor.pending_wrap = wrap; 406 - } 407 - self.back_screen.cursor.col = self.back_screen.scrolling_region.left; 408 - self.back_screen.cursor.row = self.back_screen.scrolling_region.top; 409 - try self.back_screen.insertLine(n); 429 + try self.back_screen.scrollDown(n); 410 430 }, 411 431 // Tab Control 412 432 'W' => { ··· 464 484 const w = try vaxis.gwidth.gwidth(self.last_printed, .unicode, &self.unicode.width_data); 465 485 var i: usize = 0; 466 486 while (i < n) : (i += 1) { 467 - self.back_screen.print(self.last_printed, @truncate(w)); 487 + try self.back_screen.print(self.last_printed, @truncate(w), self.mode.autowrap); 468 488 } 469 489 }, 470 490 // Device Attributes ··· 483 503 }, 484 504 // Cursor Vertical Position Absolute 485 505 'd' => { 506 + self.back_screen.cursor.pending_wrap = false; 486 507 var iter = seq.iterator(u16); 487 508 const n = iter.next() orelse 1; 509 + const max = if (self.mode.origin) 510 + self.back_screen.scrolling_region.bottom 511 + else 512 + self.back_screen.height -| 1; 488 513 self.back_screen.cursor.pending_wrap = false; 489 514 self.back_screen.cursor.row = @min( 490 - self.back_screen.height -| 1, 515 + max, 491 516 n -| 1, 492 517 ); 493 518 }, 494 - // Cursor Horizontal Position Absolute 519 + // Cursor Vertical Position Absolute 495 520 'e' => { 496 521 var iter = seq.iterator(u16); 497 522 const n = iter.next() orelse 1; 498 523 self.back_screen.cursor.pending_wrap = false; 499 - self.back_screen.cursor.col = @min( 524 + self.back_screen.cursor.row = @min( 500 525 self.back_screen.width -| 1, 501 526 n -| 1, 502 527 ); ··· 601 626 var iter = seq.iterator(u16); 602 627 const top = iter.next() orelse 1; 603 628 const bottom = iter.next() orelse self.back_screen.height; 604 - self.back_screen.scrolling_region.top = top - 1; 605 - self.back_screen.scrolling_region.bottom = bottom - 1; 629 + self.back_screen.scrolling_region.top = top -| 1; 630 + self.back_screen.scrolling_region.bottom = bottom -| 1; 631 + self.back_screen.cursor.pending_wrap = false; 632 + if (self.mode.origin) { 633 + self.back_screen.cursor.col = self.back_screen.scrolling_region.left; 634 + self.back_screen.cursor.row = self.back_screen.scrolling_region.top; 635 + } else { 636 + self.back_screen.cursor.col = 0; 637 + self.back_screen.cursor.row = 0; 638 + } 606 639 }, 607 640 else => std.log.err("unhandled CSI: {}", .{seq}), 608 641 } ··· 648 681 649 682 pub fn setMode(self: *Terminal, mode: u16, val: bool) void { 650 683 switch (mode) { 684 + 7 => self.mode.autowrap = val, 651 685 25 => self.mode.cursor = val, 652 686 1049 => { 653 687 if (val) ··· 703 737 } else self.back_screen.width - 1; 704 738 705 739 // Move right the delta 706 - self.back_screen.cursorRight(final - col); 740 + self.back_screen.cursorRight(final -| col); 707 741 } 708 742 709 743 pub fn horizontalBackTab(self: *Terminal, n: usize) void {
+24
su.sh
··· 1 + #!/bin/sh 2 + 3 + printf "\x1b[H" 4 + printf "\x1b[2J" 5 + 6 + printf "AAAA\n" 7 + printf "BBBB\n" 8 + printf "CCCC\n" 9 + printf "DDDD\n" 10 + printf "EEEE\n" 11 + printf "FFFF\n" 12 + printf "GGGG\n" 13 + printf "HHHH\n" 14 + sleep 1 15 + 16 + printf "\x1b[T" 17 + sleep 3 18 + printf "\x1b[S" 19 + sleep 3 20 + printf "\x1b[2;4r" 21 + printf "\x1b[T" 22 + sleep 3 23 + printf "\x1b[S" 24 + sleep 3
vaxis.log2

This is a binary file and will not be displayed.