os: fixes for os.input(), os.get_raw_stdin(), os.get_raw_line() in case of stdin EOF

pull/9004/head
Delyan Angelov 2021-02-27 12:50:15 +02:00
parent e6b4f9ff09
commit 20f9bdfa8e
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
4 changed files with 42 additions and 21 deletions

View File

@ -263,7 +263,7 @@ fn C._waccess() int
fn C._wremove() int fn C._wremove() int
fn C.ReadConsole() voidptr fn C.ReadConsole(in_input_handle voidptr, out_buffer voidptr, in_chars_to_read u32, out_read_chars &u32, in_input_control voidptr) bool
fn C.WriteConsole() voidptr fn C.WriteConsole() voidptr

View File

@ -200,11 +200,23 @@ pub fn file_name(path string) string {
return path.all_after_last(path_separator) return path.all_after_last(path_separator)
} }
// input returns a one-line string from stdin, after printing a prompt. // input_opt returns a one-line string from stdin, after printing a prompt.
pub fn input(prompt string) string { // In the event of error (end of input), it returns `none`.
pub fn input_opt(prompt string) ?string {
print(prompt) print(prompt)
flush() flush()
return get_line() res := get_raw_line()
if res.len > 0 {
return res.trim_right('\r\n')
}
return none
}
// input returns a one-line string from stdin, after printing a prompt.
// In the event of error (end of input), it returns '<EOF>'.
pub fn input(prompt string) string {
res := input_opt(prompt) or { return '<EOF>' }
return res
} }
// get_line returns a one-line string from stdin // get_line returns a one-line string from stdin
@ -212,9 +224,8 @@ pub fn get_line() string {
str := get_raw_line() str := get_raw_line()
$if windows { $if windows {
return str.trim_right('\r\n') return str.trim_right('\r\n')
} $else {
return str.trim_right('\n')
} }
return str.trim_right('\n')
} }
// get_lines returns an array of strings read from from stdin. // get_lines returns an array of strings read from from stdin.

View File

@ -476,14 +476,20 @@ pub fn get_raw_line() string {
h_input := C.GetStdHandle(C.STD_INPUT_HANDLE) h_input := C.GetStdHandle(C.STD_INPUT_HANDLE)
mut bytes_read := 0 mut bytes_read := 0
if is_atty(0) > 0 { if is_atty(0) > 0 {
C.ReadConsole(h_input, buf, max_line_chars * 2, C.LPDWORD(&bytes_read), x := C.ReadConsole(h_input, buf, max_line_chars * 2, C.LPDWORD(&bytes_read),
0) 0)
if !x {
return tos(buf, 0)
}
return string_from_wide2(&u16(buf), bytes_read) return string_from_wide2(&u16(buf), bytes_read)
} }
mut offset := 0 mut offset := 0
for { for {
pos := buf + offset pos := buf + offset
res := C.ReadFile(h_input, pos, 1, C.LPDWORD(&bytes_read), 0) res := C.ReadFile(h_input, pos, 1, C.LPDWORD(&bytes_read), 0)
if !res && offset == 0 {
return tos(buf, 0)
}
if !res || bytes_read == 0 { if !res || bytes_read == 0 {
break break
} }
@ -497,15 +503,9 @@ pub fn get_raw_line() string {
} }
} $else { } $else {
max := size_t(0) max := size_t(0)
mut buf := charptr(0) buf := charptr(0)
nr_chars := unsafe { C.getline(&buf, &max, C.stdin) } nr_chars := unsafe { C.getline(&buf, &max, C.stdin) }
// defer { unsafe{ free(buf) } } return unsafe { tos(byteptr(buf), if nr_chars < 0 { 0 } else { nr_chars }) }
if nr_chars == 0 || nr_chars == -1 {
return ''
}
return unsafe { tos3(buf) }
// res := tos_clone(buf)
// return res
} }
} }
@ -527,7 +527,6 @@ pub fn get_raw_stdin() []byte {
} }
buf = v_realloc(buf, offset + block_bytes + (block_bytes - bytes_read)) buf = v_realloc(buf, offset + block_bytes + (block_bytes - bytes_read))
} }
C.CloseHandle(h_input)
return array{ return array{
element_size: 1 element_size: 1
data: voidptr(buf) data: voidptr(buf)
@ -536,7 +535,15 @@ pub fn get_raw_stdin() []byte {
} }
} }
} $else { } $else {
panic('get_raw_stdin not implemented on this platform...') max := size_t(0)
buf := charptr(0)
nr_chars := unsafe { C.getline(&buf, &max, C.stdin) }
return array{
element_size: 1
data: voidptr(buf)
len: if nr_chars < 0 { 0 } else { nr_chars }
cap: int(max)
}
} }
} }

View File

@ -22,15 +22,18 @@ fn main() {
term.set_cursor_position(x: width / 2, y: height / 2) // now we point the cursor to the middle of the terminal term.set_cursor_position(x: width / 2, y: height / 2) // now we point the cursor to the middle of the terminal
println(term.strikethrough(term.bright_green('hello world'))) // Print green text println(term.strikethrough(term.bright_green('hello world'))) // Print green text
term.set_cursor_position(x: 0, y: height) // Sets the position of the cursor to the bottom of the terminal term.set_cursor_position(x: 0, y: height) // Sets the position of the cursor to the bottom of the terminal
mut var := os.input('press q to quit: ')
// Keep prompting until the user presses the q key // Keep prompting until the user presses the q key
for { for {
if var == 'q' { if var := os.input_opt('press q to quit: ') {
if var != 'q' {
continue
}
break break
} else {
var = os.input('press q to quit: ')
} }
println('')
break
} }
println('Goodbye.')
} }
``` ```