Skip to content

Commit 6de78ec

Browse files
authored
term: implement term.clear() for windows (#8650)
1 parent 5308b63 commit 6de78ec

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

vlib/term/term.v

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,3 @@ fn supports_escape_sequences(fd int) bool {
119119
return is_atty(fd) > 0
120120
}
121121
}
122-
123-
// clear clears current terminal screen.
124-
pub fn clear() {
125-
$if !windows {
126-
print('\x1b[2J')
127-
print('\x1b[H')
128-
}
129-
}

vlib/term/term_nix.c.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,9 @@ pub fn set_terminal_title(title string) bool {
9393
print('\033]0;${title}\007')
9494
return true
9595
}
96+
97+
// clear clears current terminal screen.
98+
pub fn clear() {
99+
print('\x1b[2J')
100+
print('\x1b[H')
101+
}

vlib/term/term_windows.c.v

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import os
44

55
[typedef]
66
struct C.COORD {
7+
mut:
78
X i16
89
Y i16
910
}
1011

1112
[typedef]
1213
struct C.SMALL_RECT {
14+
mut:
1315
Left u16
1416
Top u16
1517
Right u16
@@ -20,19 +22,39 @@ struct C.SMALL_RECT {
2022
// https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
2123
[typedef]
2224
struct C.CONSOLE_SCREEN_BUFFER_INFO {
25+
mut:
2326
dwSize C.COORD
2427
dwCursorPosition C.COORD
2528
wAttributes u16
2629
srWindow C.SMALL_RECT
2730
dwMaximumWindowSize C.COORD
2831
}
2932

33+
union C.uChar {
34+
mut:
35+
UnicodeChar rune
36+
AsciiChar byte
37+
}
38+
39+
[typedef]
40+
struct C.CHAR_INFO {
41+
mut:
42+
Char C.uChar
43+
Attributes u16
44+
}
45+
3046
// ref - https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
3147
fn C.GetConsoleScreenBufferInfo(handle os.HANDLE, info &C.CONSOLE_SCREEN_BUFFER_INFO) bool
3248

3349
// ref - https://docs.microsoft.com/en-us/windows/console/setconsoletitle
3450
fn C.SetConsoleTitle(title &u16) bool
3551

52+
// ref - https://docs.microsoft.com/en-us/windows/console/setconsolecursorposition
53+
fn C.SetConsoleCursorPosition(handle os.HANDLE, coord C.COORD) bool
54+
55+
// ref - https://docs.microsoft.com/en-us/windows/console/scrollconsolescreenbuffer
56+
fn C.ScrollConsoleScreenBuffer(output os.HANDLE, scroll_rect &C.SMALL_RECT, clip_rect &C.SMALL_RECT, des C.COORD, fill C.CHAR_INFO) bool
57+
3658
// get_terminal_size returns a number of colums and rows of terminal window.
3759
pub fn get_terminal_size() (int, int) {
3860
if is_atty(1) > 0 && os.getenv('TERM') != 'dumb' {
@@ -64,3 +86,40 @@ pub fn set_terminal_title(title string) bool {
6486
title_change := C.SetConsoleTitle(title.to_wide())
6587
return title_change
6688
}
89+
90+
// clear clears current terminal screen.
91+
// Implementation taken from https://docs.microsoft.com/en-us/windows/console/clearing-the-screen#example-2.
92+
pub fn clear() {
93+
hconsole := C.GetStdHandle(C.STD_OUTPUT_HANDLE)
94+
mut csbi := C.CONSOLE_SCREEN_BUFFER_INFO{}
95+
mut scrollrect := C.SMALL_RECT{}
96+
mut scrolltarget := C.COORD{}
97+
mut fill := C.CHAR_INFO{}
98+
99+
// Get the number of character cells in the current buffer.
100+
if !C.GetConsoleScreenBufferInfo(hconsole, &csbi) {
101+
return
102+
}
103+
// Scroll the rectangle of the entire buffer.
104+
scrollrect.Left = 0
105+
scrollrect.Top = 0
106+
scrollrect.Right = u16(csbi.dwSize.X)
107+
scrollrect.Bottom = u16(csbi.dwSize.Y)
108+
109+
// Scroll it upwards off the top of the buffer with a magnitude of the entire height.
110+
scrolltarget.X = 0
111+
scrolltarget.Y = (0 - csbi.dwSize.Y)
112+
113+
// Fill with empty spaces with the buffer's default text attribute.
114+
fill.Char.UnicodeChar = rune(` `)
115+
fill.Attributes = csbi.wAttributes
116+
117+
// Do the scroll
118+
C.ScrollConsoleScreenBuffer(hconsole, &scrollrect, C.NULL, scrolltarget, &fill)
119+
120+
// Move the cursor to the top left corner too.
121+
csbi.dwCursorPosition.X = 0
122+
csbi.dwCursorPosition.Y = 0
123+
124+
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
125+
}

0 commit comments

Comments
 (0)