2020-01-28 07:18:19 +03:00
|
|
|
module term
|
|
|
|
|
2020-01-28 22:25:17 +03:00
|
|
|
import os
|
2023-03-30 08:58:52 +03:00
|
|
|
import term.termios
|
2020-01-28 07:18:19 +03:00
|
|
|
|
2020-01-28 22:25:17 +03:00
|
|
|
#include <sys/ioctl.h>
|
2021-03-05 17:41:11 +03:00
|
|
|
|
2020-01-28 22:25:17 +03:00
|
|
|
pub struct C.winsize {
|
|
|
|
pub:
|
|
|
|
ws_row u16
|
|
|
|
ws_col u16
|
|
|
|
ws_xpixel u16
|
|
|
|
ws_ypixel u16
|
2020-01-28 07:18:19 +03:00
|
|
|
}
|
|
|
|
|
2020-01-28 22:25:17 +03:00
|
|
|
fn C.ioctl(fd int, request u64, arg voidptr) int
|
2020-01-28 07:18:19 +03:00
|
|
|
|
2020-01-29 07:12:12 +03:00
|
|
|
// get_terminal_size returns a number of colums and rows of terminal window.
|
2020-09-08 22:00:10 +03:00
|
|
|
pub fn get_terminal_size() (int, int) {
|
2021-04-14 08:50:50 +03:00
|
|
|
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
|
2020-01-29 07:12:12 +03:00
|
|
|
return default_columns_size, default_rows_size
|
2020-01-28 22:25:17 +03:00
|
|
|
}
|
|
|
|
w := C.winsize{}
|
2021-09-06 19:04:14 +03:00
|
|
|
unsafe { C.ioctl(1, u64(C.TIOCGWINSZ), &w) }
|
2020-09-08 22:00:10 +03:00
|
|
|
return int(w.ws_col), int(w.ws_row)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get_cursor_position returns a Coord containing the current cursor position
|
2022-10-26 11:26:28 +03:00
|
|
|
pub fn get_cursor_position() !Coord {
|
2021-04-14 08:50:50 +03:00
|
|
|
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
|
2021-09-06 19:04:14 +03:00
|
|
|
return Coord{0, 0}
|
2021-09-06 17:24:39 +03:00
|
|
|
}
|
2021-09-06 19:04:14 +03:00
|
|
|
|
2023-03-30 08:58:52 +03:00
|
|
|
mut old_state := termios.Termios{}
|
|
|
|
if termios.tcgetattr(0, mut old_state) != 0 {
|
2021-09-06 19:04:14 +03:00
|
|
|
return os.last_error()
|
2021-09-06 17:24:39 +03:00
|
|
|
}
|
2021-09-06 19:04:14 +03:00
|
|
|
defer {
|
|
|
|
// restore the old terminal state:
|
2023-03-30 08:58:52 +03:00
|
|
|
termios.tcsetattr(0, C.TCSANOW, mut old_state)
|
2021-09-06 19:04:14 +03:00
|
|
|
}
|
|
|
|
|
2023-03-30 08:58:52 +03:00
|
|
|
mut state := termios.Termios{}
|
|
|
|
if termios.tcgetattr(0, mut state) != 0 {
|
2021-09-06 19:04:14 +03:00
|
|
|
return os.last_error()
|
|
|
|
}
|
2023-03-30 08:58:52 +03:00
|
|
|
|
|
|
|
state.c_lflag &= termios.invert(u32(C.ICANON) | u32(C.ECHO))
|
|
|
|
termios.tcsetattr(0, C.TCSANOW, mut state)
|
2021-09-06 19:04:14 +03:00
|
|
|
|
|
|
|
print('\e[6n')
|
2022-05-30 19:15:05 +03:00
|
|
|
flush_stdout()
|
2021-09-06 19:04:14 +03:00
|
|
|
|
2020-09-08 22:00:10 +03:00
|
|
|
mut x := 0
|
|
|
|
mut y := 0
|
2022-04-15 14:58:56 +03:00
|
|
|
mut stage := u8(0)
|
2021-09-06 19:04:14 +03:00
|
|
|
|
|
|
|
// ESC [ YYY `;` XXX `R`
|
|
|
|
|
2020-09-08 22:00:10 +03:00
|
|
|
for {
|
2021-09-06 19:04:14 +03:00
|
|
|
w := unsafe { C.getchar() }
|
|
|
|
if w < 0 {
|
|
|
|
return error_with_code('Failed to read from stdin', 888)
|
|
|
|
} else if w == `[` || w == `;` {
|
|
|
|
stage++
|
|
|
|
} else if `0` <= w && w <= `9` {
|
|
|
|
match stage {
|
|
|
|
// converting string values to int:
|
|
|
|
1 { y = y * 10 + int(w - `0`) }
|
|
|
|
2 { x = x * 10 + int(w - `0`) }
|
|
|
|
else {}
|
|
|
|
}
|
|
|
|
} else if w == `R` {
|
2020-09-08 22:00:10 +03:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-09-06 19:04:14 +03:00
|
|
|
return Coord{x, y}
|
2020-09-08 22:00:10 +03:00
|
|
|
}
|
|
|
|
|
2023-01-14 13:00:39 +03:00
|
|
|
// set_terminal_title change the terminal title (usually that is the containing terminal window title)
|
2020-09-08 22:00:10 +03:00
|
|
|
pub fn set_terminal_title(title string) bool {
|
2021-04-14 08:50:50 +03:00
|
|
|
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
|
2023-01-14 13:00:39 +03:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
print('\033]0;')
|
|
|
|
print(title)
|
|
|
|
print('\007')
|
|
|
|
flush_stdout()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// set_tab_title changes the terminal *tab title*, for terminal emulators like Konsole, that support several tabs
|
|
|
|
pub fn set_tab_title(title string) bool {
|
|
|
|
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
|
|
|
|
return false
|
2020-09-08 22:00:10 +03:00
|
|
|
}
|
2023-01-14 12:08:49 +03:00
|
|
|
print('\033]30;')
|
2021-03-08 21:52:13 +03:00
|
|
|
print(title)
|
|
|
|
print('\007')
|
2022-05-30 19:15:05 +03:00
|
|
|
flush_stdout()
|
2020-09-08 22:00:10 +03:00
|
|
|
return true
|
2020-01-28 07:18:19 +03:00
|
|
|
}
|
2021-02-09 15:25:31 +03:00
|
|
|
|
|
|
|
// clear clears current terminal screen.
|
2023-01-14 13:00:39 +03:00
|
|
|
pub fn clear() bool {
|
|
|
|
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
|
|
|
|
return false
|
|
|
|
}
|
2021-02-09 15:25:31 +03:00
|
|
|
print('\x1b[2J')
|
|
|
|
print('\x1b[H')
|
2022-05-30 19:15:05 +03:00
|
|
|
flush_stdout()
|
2023-01-14 13:00:39 +03:00
|
|
|
return true
|
2021-02-09 15:25:31 +03:00
|
|
|
}
|