this repo has no description
13
fork

Configure Feed

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

widgets(terminal): handle horizontal tabs

+52 -12
+13
src/widgets/terminal/Screen.zig
··· 332 332 self.cursor.col = self.cursor.col -| n; 333 333 } 334 334 335 + pub fn cursorRight(self: *Screen, n: usize) void { 336 + if (self.withinScrollingRegion()) 337 + self.cursor.col = @min( 338 + self.cursor.col + n, 339 + self.scrolling_region.right, 340 + ) 341 + else 342 + self.cursor.col = @min( 343 + self.cursor.col + n, 344 + self.width, 345 + ); 346 + } 347 + 335 348 pub fn cursorDown(self: *Screen, n: usize) void { 336 349 self.cursor.pending_wrap = false; 337 350 if (self.withinScrollingRegion())
+39 -12
src/widgets/terminal/Terminal.zig
··· 67 67 68 68 mode: Mode = .{}, 69 69 70 + tab_stops: std.ArrayList(u16), 71 + 70 72 event_queue: Queue = .{}, 71 73 72 74 /// initialize a Terminal. This sets the size of the underlying pty and allocates the sizes of the ··· 85 87 .env_map = env, 86 88 .pty = pty, 87 89 }; 90 + var tabs = try std.ArrayList(u16).initCapacity(allocator, opts.winsize.cols / 8); 91 + var col: u16 = 0; 92 + while (col < opts.winsize.cols) : (col += 8) { 93 + try tabs.append(col); 94 + } 88 95 return .{ 89 96 .allocator = allocator, 90 97 .pty = pty, ··· 94 101 .back_screen_pri = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows + opts.scrollback_size), 95 102 .back_screen_alt = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows), 96 103 .unicode = unicode, 104 + .tab_stops = tabs, 97 105 }; 98 106 } 99 107 ··· 124 132 self.front_screen.deinit(self.allocator); 125 133 self.back_screen_pri.deinit(self.allocator); 126 134 self.back_screen_alt.deinit(self.allocator); 135 + self.tab_stops.deinit(); 127 136 } 128 137 129 138 pub fn spawn(self: *Terminal) !void { ··· 275 284 self.back_screen.cursor.pending_wrap = false; 276 285 var iter = seq.iterator(u16); 277 286 const delta = iter.next() orelse 1; 278 - const within = self.back_screen.withinScrollingRegion(); 279 - if (within) 280 - self.back_screen.cursor.col = @min( 281 - self.back_screen.cursor.col + delta, 282 - self.back_screen.scrolling_region.right, 283 - ) 284 - else 285 - self.back_screen.cursor.col = @min( 286 - self.back_screen.cursor.col + delta, 287 - self.back_screen.width, 288 - ); 287 + self.back_screen.cursorRight(delta); 289 288 }, 290 289 // Cursor Left 291 290 'D', 'j' => { ··· 307 306 self.back_screen.cursorUp(delta); 308 307 self.carriageReturn(); 309 308 }, 309 + // Horizontal Positional Absolute 310 + 'G', '`' => { 311 + var iter = seq.iterator(u16); 312 + const col = iter.next() orelse 1; 313 + self.back_screen.cursor.col = col -| 1; 314 + }, 315 + // Cursor Absolute Position 310 316 'H', 'f' => { 311 317 var iter = seq.iterator(u16); 312 318 const row = iter.next() orelse 1; 313 319 const col = iter.next() orelse 1; 314 320 self.back_screen.cursor.col = col -| 1; 315 321 self.back_screen.cursor.row = row -| 1; 322 + }, 323 + 'I' => { 324 + var iter = seq.iterator(u16); 325 + const n = iter.next() orelse 1; 326 + self.horizontalTab(n); 316 327 }, 317 328 'K' => { 318 329 // TODO selective erase (private_marker == '?') ··· 392 403 .ENQ => {}, 393 404 .BEL => self.event_queue.push(.bell), 394 405 .BS => self.back_screen.cursorLeft(1), 395 - .HT => {}, // TODO: HT 406 + .HT => self.horizontalTab(1), 396 407 .LF, .VT, .FF => try self.back_screen.index(), 397 408 .CR => self.carriageReturn(), 398 409 .SO => {}, // TODO: Charset shift out ··· 444 455 else 445 456 0; 446 457 } 458 + 459 + pub fn horizontalTab(self: *Terminal, n: usize) void { 460 + // Get the current cursor position 461 + const col = self.back_screen.cursor.col; 462 + 463 + // Find desired final position 464 + var i: usize = 0; 465 + const final = for (self.tab_stops.items) |ts| { 466 + if (ts <= col) continue; 467 + i += 1; 468 + if (i == n) break ts; 469 + } else self.back_screen.width - 1; 470 + 471 + // Move right the delta 472 + self.back_screen.cursorRight(final - col); 473 + }