mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: cub with reverse wrap consumes pending wrap state as one
Related to #1184 See the updated website page and associated test.
This commit is contained in:
@ -1564,18 +1564,23 @@ pub fn cursorLeft(self: *Terminal, count_req: usize) void {
|
||||
break :wrap_mode .none;
|
||||
};
|
||||
|
||||
// Unset the pending wrap state no matter what
|
||||
self.screen.cursor.pending_wrap = false;
|
||||
|
||||
var count: usize = @max(count_req, 1);
|
||||
|
||||
// If we are in no wrap mode, then we move the cursor left and exit
|
||||
// since this is the fastest and most typical path.
|
||||
if (wrap_mode == .none) {
|
||||
self.screen.cursor.x -|= count;
|
||||
self.screen.cursor.pending_wrap = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a pending wrap state and we are in either reverse wrap
|
||||
// modes then we decrement the amount we move by one to match xterm.
|
||||
if (self.screen.cursor.pending_wrap) {
|
||||
count -= 1;
|
||||
self.screen.cursor.pending_wrap = false;
|
||||
}
|
||||
|
||||
// The margins we can move to.
|
||||
const top = self.scrolling_region.top;
|
||||
const bottom = self.scrolling_region.bottom;
|
||||
@ -6265,6 +6270,48 @@ test "Terminal: cursorLeft unsets pending wrap state with longer jump" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: cursorLeft reverse wrap with pending wrap state" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, 5, 5);
|
||||
defer t.deinit(alloc);
|
||||
|
||||
t.modes.set(.wraparound, true);
|
||||
t.modes.set(.reverse_wrap, true);
|
||||
|
||||
for ("ABCDE") |c| try t.print(c);
|
||||
try testing.expect(t.screen.cursor.pending_wrap);
|
||||
t.cursorLeft(1);
|
||||
try testing.expect(!t.screen.cursor.pending_wrap);
|
||||
try t.print('X');
|
||||
|
||||
{
|
||||
const str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("ABCDX", str);
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: cursorLeft reverse wrap extended with pending wrap state" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, 5, 5);
|
||||
defer t.deinit(alloc);
|
||||
|
||||
t.modes.set(.wraparound, true);
|
||||
t.modes.set(.reverse_wrap_extended, true);
|
||||
|
||||
for ("ABCDE") |c| try t.print(c);
|
||||
try testing.expect(t.screen.cursor.pending_wrap);
|
||||
t.cursorLeft(1);
|
||||
try testing.expect(!t.screen.cursor.pending_wrap);
|
||||
try t.print('X');
|
||||
|
||||
{
|
||||
const str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("ABCDX", str);
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: cursorLeft reverse wrap" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, 5, 5);
|
||||
|
@ -51,6 +51,11 @@ is a remaining value of `n`. If the cursor
|
||||
is already on the [top margin](#TODO), do not move the cursor up.
|
||||
This wrapping mode does not wrap the cursor row back to the bottom margin.
|
||||
|
||||
For **extended reverse wrap** or **reverse wrap** modes, if the pending
|
||||
wrap state is set, decrease `n` by 1. In these modes, the initial cursor
|
||||
backward count is consumed by the pending wrap state, as if you pressed
|
||||
"backspace" on an empty newline and the cursor moved back to the previous line.
|
||||
|
||||
## Validation
|
||||
|
||||
### CUB V-1: Pending Wrap is Unset
|
||||
@ -159,3 +164,20 @@ printf "X"
|
||||
|__________|
|
||||
|Xc________|
|
||||
```
|
||||
|
||||
### CUB V-7: Reverse Wrap with Pending Wrap State
|
||||
|
||||
```bash
|
||||
|
||||
cols=$(tput cols)
|
||||
printf "\033[?45h"
|
||||
printf "\033[${cols}G"
|
||||
printf "\033[4D"
|
||||
printf "ABCDE"
|
||||
printf "\033[D"
|
||||
printf "X"
|
||||
```
|
||||
|
||||
```
|
||||
|_____ABCDX|
|
||||
```
|
||||
|
Reference in New Issue
Block a user