term: implement term.clear() for windows (#8650)

pull/8658/head
Swastik Baranwal 2021-02-09 17:55:31 +05:30 committed by GitHub
parent 5308b63a01
commit 6de78ecb59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 8 deletions

View File

@ -119,11 +119,3 @@ fn supports_escape_sequences(fd int) bool {
return is_atty(fd) > 0 return is_atty(fd) > 0
} }
} }
// clear clears current terminal screen.
pub fn clear() {
$if !windows {
print('\x1b[2J')
print('\x1b[H')
}
}

View File

@ -93,3 +93,9 @@ pub fn set_terminal_title(title string) bool {
print('\033]0;${title}\007') print('\033]0;${title}\007')
return true return true
} }
// clear clears current terminal screen.
pub fn clear() {
print('\x1b[2J')
print('\x1b[H')
}

View File

@ -4,12 +4,14 @@ import os
[typedef] [typedef]
struct C.COORD { struct C.COORD {
mut:
X i16 X i16
Y i16 Y i16
} }
[typedef] [typedef]
struct C.SMALL_RECT { struct C.SMALL_RECT {
mut:
Left u16 Left u16
Top u16 Top u16
Right u16 Right u16
@ -20,6 +22,7 @@ struct C.SMALL_RECT {
// https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str // https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
[typedef] [typedef]
struct C.CONSOLE_SCREEN_BUFFER_INFO { struct C.CONSOLE_SCREEN_BUFFER_INFO {
mut:
dwSize C.COORD dwSize C.COORD
dwCursorPosition C.COORD dwCursorPosition C.COORD
wAttributes u16 wAttributes u16
@ -27,12 +30,31 @@ struct C.CONSOLE_SCREEN_BUFFER_INFO {
dwMaximumWindowSize C.COORD dwMaximumWindowSize C.COORD
} }
union C.uChar {
mut:
UnicodeChar rune
AsciiChar byte
}
[typedef]
struct C.CHAR_INFO {
mut:
Char C.uChar
Attributes u16
}
// ref - https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo // ref - https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
fn C.GetConsoleScreenBufferInfo(handle os.HANDLE, info &C.CONSOLE_SCREEN_BUFFER_INFO) bool fn C.GetConsoleScreenBufferInfo(handle os.HANDLE, info &C.CONSOLE_SCREEN_BUFFER_INFO) bool
// ref - https://docs.microsoft.com/en-us/windows/console/setconsoletitle // ref - https://docs.microsoft.com/en-us/windows/console/setconsoletitle
fn C.SetConsoleTitle(title &u16) bool fn C.SetConsoleTitle(title &u16) bool
// ref - https://docs.microsoft.com/en-us/windows/console/setconsolecursorposition
fn C.SetConsoleCursorPosition(handle os.HANDLE, coord C.COORD) bool
// ref - https://docs.microsoft.com/en-us/windows/console/scrollconsolescreenbuffer
fn C.ScrollConsoleScreenBuffer(output os.HANDLE, scroll_rect &C.SMALL_RECT, clip_rect &C.SMALL_RECT, des C.COORD, fill C.CHAR_INFO) bool
// get_terminal_size returns a number of colums and rows of terminal window. // get_terminal_size returns a number of colums and rows of terminal window.
pub fn get_terminal_size() (int, int) { pub fn get_terminal_size() (int, int) {
if is_atty(1) > 0 && os.getenv('TERM') != 'dumb' { if is_atty(1) > 0 && os.getenv('TERM') != 'dumb' {
@ -64,3 +86,40 @@ pub fn set_terminal_title(title string) bool {
title_change := C.SetConsoleTitle(title.to_wide()) title_change := C.SetConsoleTitle(title.to_wide())
return title_change return title_change
} }
// clear clears current terminal screen.
// Implementation taken from https://docs.microsoft.com/en-us/windows/console/clearing-the-screen#example-2.
pub fn clear() {
hconsole := C.GetStdHandle(C.STD_OUTPUT_HANDLE)
mut csbi := C.CONSOLE_SCREEN_BUFFER_INFO{}
mut scrollrect := C.SMALL_RECT{}
mut scrolltarget := C.COORD{}
mut fill := C.CHAR_INFO{}
// Get the number of character cells in the current buffer.
if !C.GetConsoleScreenBufferInfo(hconsole, &csbi) {
return
}
// Scroll the rectangle of the entire buffer.
scrollrect.Left = 0
scrollrect.Top = 0
scrollrect.Right = u16(csbi.dwSize.X)
scrollrect.Bottom = u16(csbi.dwSize.Y)
// Scroll it upwards off the top of the buffer with a magnitude of the entire height.
scrolltarget.X = 0
scrolltarget.Y = (0 - csbi.dwSize.Y)
// Fill with empty spaces with the buffer's default text attribute.
fill.Char.UnicodeChar = rune(` `)
fill.Attributes = csbi.wAttributes
// Do the scroll
C.ScrollConsoleScreenBuffer(hconsole, &scrollrect, C.NULL, scrolltarget, &fill)
// Move the cursor to the top left corner too.
csbi.dwCursorPosition.X = 0
csbi.dwCursorPosition.Y = 0
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
}