commit fda86a519e22051317e398ef8b2de048acb7973a
parent 005551137577929740796b239f33928b61245bd4
Author: dwrz <dwrz@dwrz.net>
Date: Fri, 2 Dec 2022 16:20:54 +0000
Add terminal pkg
Diffstat:
A | pkg/terminal/key.go | | | 137 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | pkg/terminal/terminal.go | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 247 insertions(+), 0 deletions(-)
diff --git a/pkg/terminal/key.go b/pkg/terminal/key.go
@@ -0,0 +1,137 @@
+package terminal
+
+const (
+ // Control Characters
+ Null rune = 0
+ StartOfHeading rune = 1
+ StartOfText rune = 2
+ EndOfText rune = 3
+ EndOfTransmission rune = 4
+ Enquiry rune = 5
+ Acknowledgment rune = 6
+ Bell rune = 7
+ Backspace rune = 8
+ HorizontalTab rune = 9
+ LineFeed rune = 10
+ VerticalTab rune = 11
+ FormFeed rune = 12
+ CarriageReturn rune = 13
+ ShiftOut rune = 14
+ ShiftIn rune = 15
+ DataLineEscape rune = 16
+ DeviceControl1 rune = 17
+ DeviceControl2 rune = 18
+ DeviceControl3 rune = 19
+ DeviceControl4 rune = 20
+ NegativeAcknowledgment rune = 21
+ SynchronousIdle rune = 22
+ EndOfTransmitBlock rune = 23
+ Cancel rune = 24
+ EndOfMedium rune = 25
+ Substitute rune = 26
+ Escape rune = 27
+ FileSeparator rune = 28
+ GroupSeparator rune = 29
+ RecordSeparator rune = 30
+ UnitSeparator rune = 31
+
+ // Printable Characters
+ Space rune = 32
+ ExclamationMark rune = 33
+ DoubleQuote rune = 34
+ Number rune = 35
+ Dollar rune = 36
+ Percentage rune = 37
+ Ampersand rune = 38
+ SingleQuote rune = 39
+ LeftParenthesis rune = 40
+ RightParenthesis rune = 41
+ Asterisk rune = 42
+ Plus rune = 43
+ Comma rune = 44
+ Hyphen rune = 45
+ Period rune = 46
+ ForwardSlash rune = 47
+ Zero rune = 48
+ One rune = 49
+ Two rune = 50
+ Three rune = 51
+ Four rune = 52
+ Five rune = 53
+ Six rune = 54
+ Seven rune = 55
+ Eight rune = 56
+ Nine rune = 57
+ Colon rune = 58
+ Semicolon rune = 59
+ LessThan rune = 60
+ Equals rune = 61
+ GreaterThan rune = 62
+ QuestionMark rune = 63
+ At rune = 64
+ UpperA rune = 65
+ UpperB rune = 66
+ UpperC rune = 67
+ UpperD rune = 68
+ UpperE rune = 69
+ UpperF rune = 70
+ UpperG rune = 71
+ UpperH rune = 72
+ UpperI rune = 73
+ UpperJ rune = 74
+ UpperK rune = 75
+ UpperL rune = 76
+ UpperM rune = 77
+ UpperN rune = 78
+ UpperO rune = 79
+ UpperP rune = 80
+ UpperQ rune = 81
+ UpperR rune = 82
+ UpperS rune = 83
+ UpperT rune = 84
+ UpperU rune = 85
+ UpperV rune = 86
+ UpperW rune = 87
+ UpperX rune = 88
+ UpperY rune = 89
+ UpperZ rune = 90
+ LeftBracket rune = 91
+ Backslash rune = 92
+ RightBracket rune = 93
+ Caret rune = 94
+ Underscore rune = 95
+ Grave rune = 96
+ LowerA rune = 97
+ LowerB rune = 98
+ LowerC rune = 99
+ LowerD rune = 100
+ LowerE rune = 101
+ LowerF rune = 102
+ LowerG rune = 103
+ LowerH rune = 104
+ LowerI rune = 105
+ LowerJ rune = 106
+ LowerK rune = 107
+ LowerL rune = 108
+ LowerM rune = 109
+ LowerN rune = 110
+ LowerO rune = 111
+ LowerP rune = 112
+ LowerQ rune = 113
+ LowerR rune = 114
+ LowerS rune = 115
+ LowerT rune = 116
+ LowerU rune = 117
+ LowerV rune = 118
+ LowerW rune = 119
+ LowerX rune = 120
+ LowerY rune = 121
+ LowerZ rune = 122
+ LeftBrace rune = 123
+ VerticalBar rune = 124
+ RightBrace rune = 125
+ Tilde rune = 126
+ Delete rune = 127
+)
+
+const Control = 0x1f
diff --git a/pkg/terminal/terminal.go b/pkg/terminal/terminal.go
@@ -0,0 +1,110 @@
+package terminal
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+const (
+ ClearScreen = "\u001Bc"
+ CursorHide = "\u001B[?25l"
+ CursorShow = "\u001B[?25h"
+ CursorTopLeft = "\u001B[H"
+ EraseLine = "\u001B[K"
+
+ SetCursorFmt = "\u001B[%d;%dH"
+)
+
+type Terminal struct {
+ fd uintptr
+ termios *syscall.Termios
+}
+
+type Size struct {
+ Rows uint16
+ Columns uint16
+ XPixels uint16
+ YPixels uint16
+}
+
+func New(fd uintptr) (*Terminal, error) {
+ var t = &Terminal{
+ termios: &syscall.Termios{},
+ }
+
+ if _, _, err := syscall.Syscall(
+ syscall.SYS_IOCTL,
+ fd,
+ syscall.TCGETS,
+ uintptr(unsafe.Pointer(t.termios)),
+ ); err != 0 {
+ return nil, fmt.Errorf("ioctl syscall: %w", err)
+ }
+
+ return t, nil
+}
+
+// Reset the terminal into the original termios.
+func (t *Terminal) Reset() error {
+ if _, _, err := syscall.Syscall(
+ syscall.SYS_IOCTL,
+ t.fd,
+ uintptr(syscall.TCSETS),
+ uintptr(unsafe.Pointer(t.termios)),
+ ); err != 0 {
+ return fmt.Errorf("ioctl syscall: %w", err)
+ }
+
+ return nil
+}
+
+// SetRaw enables raw mode.
+func (t *Terminal) SetRaw() error {
+ var termios = *t.termios
+ termios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+ termios.Oflag &^= syscall.OPOST
+ termios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+ termios.Cflag &^= syscall.CSIZE | syscall.PARENB
+ termios.Cflag |= syscall.CS8
+ termios.Cc[syscall.VMIN] = 1
+ termios.Cc[syscall.VTIME] = 0
+
+ if _, _, err := syscall.Syscall(
+ syscall.SYS_IOCTL,
+ t.fd,
+ uintptr(syscall.TCSETS),
+ uintptr(unsafe.Pointer(&termios)),
+ ); err != 0 {
+ return fmt.Errorf("ioctl syscall: %w", err)
+ }
+
+ return nil
+}
+
+func (t *Terminal) size() (*Size, error) {
+ var s = &Size{}
+ if _, _, err := syscall.Syscall(
+ syscall.SYS_IOCTL,
+ t.fd,
+ syscall.TIOCGWINSZ,
+ uintptr(unsafe.Pointer(s)),
+ ); err != 0 {
+ return nil, fmt.Errorf("ioctl syscall: %w", err)
+ }
+
+ return s, nil
+}
+
+// Size returns the zero-indexed size of the terminal.
+func (t *Terminal) Size() (*Size, error) {
+ size, err := t.size()
+ if err != nil {
+ return nil, err
+ }
+
+ size.Columns--
+ size.Rows--
+
+ return size, nil
+}