Merge pull request #629 from mitchellh/xt-cuu

xterm audit: cursor up (CUU)
This commit is contained in:
Mitchell Hashimoto
2023-10-06 22:46:46 -07:00
committed by GitHub
2 changed files with 161 additions and 3 deletions

View File

@ -1474,13 +1474,21 @@ pub fn cursorDown(self: *Terminal, count_req: usize) void {
/// Move the cursor up amount lines. If amount is greater than the maximum
/// move distance then it is internally adjusted to the maximum. If amount is
/// 0, adjust it to 1.
// TODO: test
pub fn cursorUp(self: *Terminal, count: usize) void {
pub fn cursorUp(self: *Terminal, count_req: usize) void {
const tracy = trace(@src());
defer tracy.end();
self.screen.cursor.y -|= if (count == 0) 1 else count;
// Always resets pending wrap
self.screen.cursor.pending_wrap = false;
// The min the cursor can move to depends where the cursor currently is
const min = if (self.screen.cursor.y >= self.scrolling_region.top)
self.scrolling_region.top
else
0;
const count = @max(count_req, 1);
self.screen.cursor.y = @max(min, self.screen.cursor.y -| count);
}
/// Backspace moves the cursor back a column (but not less than 0).
@ -3964,3 +3972,75 @@ test "Terminal: cursorDown resets wrap" {
try testing.expectEqualStrings("ABCDE\n X", str);
}
}
test "Terminal: cursorUp basic" {
const alloc = testing.allocator;
var t = try init(alloc, 5, 5);
defer t.deinit(alloc);
t.setCursorPos(3, 1);
try t.print('A');
t.cursorUp(10);
try t.print('X');
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings(" X\n\nA", str);
}
}
test "Terminal: cursorUp below top scroll margin" {
const alloc = testing.allocator;
var t = try init(alloc, 5, 5);
defer t.deinit(alloc);
t.setScrollingRegion(2, 4);
t.setCursorPos(3, 1);
try t.print('A');
t.cursorUp(5);
try t.print('X');
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("\n X\nA", str);
}
}
test "Terminal: cursorUp above top scroll margin" {
const alloc = testing.allocator;
var t = try init(alloc, 5, 5);
defer t.deinit(alloc);
t.setScrollingRegion(3, 5);
t.setCursorPos(3, 1);
try t.print('A');
t.setCursorPos(2, 1);
t.cursorUp(10);
try t.print('X');
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("X\n\nA", str);
}
}
test "Terminal: cursorUp resets wrap" {
const alloc = testing.allocator;
var t = try init(alloc, 5, 5);
defer t.deinit(alloc);
for ("ABCDE") |c| try t.print(c);
try testing.expect(t.screen.cursor.pending_wrap);
t.cursorUp(1);
try testing.expect(!t.screen.cursor.pending_wrap);
try t.print('X');
{
var str = try t.plainString(testing.allocator);
defer testing.allocator.free(str);
try testing.expectEqualStrings("ABCDX", str);
}
}

View File

@ -0,0 +1,78 @@
import VTSequence from "@/components/VTSequence";
# Cursor Up (CUU)
<VTSequence sequence={["CSI", "Pn", "A"]} />
Move the cursor `n` cells up.
The parameter `n` must be an integer greater than or equal to 1. If `n` is less than
or equal to 0, adjust `n` to be 1. If `n` is omitted, `n` defaults to 1.
This sequence always unsets the pending wrap state.
If the current cursor position is at or below the [top margin](#TODO),
the highest point the cursor can move is the top margin. If the current
cursor position is above the top margin, the highest point the cursor
can move is the first row.
## Validation
### CUU V-1: Cursor Up
```bash
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[3;1H"
printf "A"
printf "\033[2A" # cursor up
printf "X"
```
```
|_Xc_______|
|__________|
|A_________|
```
### CUU V-2: Cursor Up Below Top Margin
```bash
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\n\n\n\n" # screen is 4 high
printf "\033[2;4r" # set scrolling region
printf "\033[3;1H"
printf "A"
printf "\033[5A" # cursor up
printf "X"
```
```
|__________|
|_Xc_______|
|A_________|
|__________|
```
### CUU V-3: Cursor Up Above Top Margin
```bash
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\n\n\n\n\n" # screen is 5 high
printf "\033[3;5r" # set scrolling region
printf "\033[3;1H"
printf "A"
printf "\033[2;1H" # move above region
printf "\033[5A" # cursor up
printf "X"
```
```
|Xc________|
|__________|
|A_________|
|__________|
|__________|
```