From 1e2d60b0d5c80f7825d165ea2b71eb19b732c593 Mon Sep 17 00:00:00 2001 From: surdeus Date: Fri, 26 Jul 2024 23:13:04 +0500 Subject: [PATCH] feat: tx: started implementing cursor stuff. --- aes/colors.go | 4 +++ aes/es.go | 60 ++++++++++++++++++++++++++++++++++++++++++++ aes/shortcut.go | 8 ++++++ btest.sh => btest | 0 cmd/termsize/main.go | 38 +++++++++++++++++++++++++--- tx/aes.go | 5 ++++ tx/term.go | 34 +++++++++++++++++++++++++ 7 files changed, 145 insertions(+), 4 deletions(-) rename btest.sh => btest (100%) diff --git a/aes/colors.go b/aes/colors.go index 8577f40..2dbdffe 100644 --- a/aes/colors.go +++ b/aes/colors.go @@ -14,6 +14,7 @@ func (effects Effects) Format() string { return strings.Join(intStrs, ";") } +// Effect codes. const ( EffectReset Effect = iota EffectBold @@ -23,6 +24,7 @@ const ( EffectBlinking ) +// Keep effect codes. const ( EffectInverse Effect = 7 + iota EffectHidden @@ -30,6 +32,7 @@ const ( EffectStirke ) +// Foreground effect codes. const ( EffectBlackFG = 30 + iota EffectRedFG @@ -42,6 +45,7 @@ const ( EffectDefaultFG ) +// Background effect codes. const ( EffectBlackBG Effect = 40 + iota EffectRedBG diff --git a/aes/es.go b/aes/es.go index 20838a2..e429c3f 100644 --- a/aes/es.go +++ b/aes/es.go @@ -1,5 +1,9 @@ package aes +const ( + KeyESC = '\x1B' +) + const ( // Start. ESC = "\x1B" @@ -14,6 +18,7 @@ const ( OSC = ESC+"]" ) +// Special control sequences. const ( BEL = "\a" BS = "\b" @@ -25,3 +30,58 @@ const ( DEL = "\x7F" ) +// Erasing control sequences. +// Names are self describing. +const ( + EraseInDisplay = CSI+"J" + EraseFromCursorToEndOfScreen = CSI+"0J" + EraseFromCursorToBeginOfScreen = CSI+"1J" + EraseEntireScreen = CSI+"2J" + EraseSavedLines = CSI+"3J" + EraseInLine = CSI+"K" + EraseFromCursorToEndOfLine = CSI+"0K" + EraseFromStartOfLineToCursor = CSI+"1K" + EraseEntireLine = CSI+"2K" +) + +// Cursor control sequences. +// Any that ends with the "Format" means that +// the format is meant to be used via fmt.Sprintf +// or any fitting function to provide arguments +// into the escape code. +const ( + MoveCursorHome = CSI+"H" + + // Line, column (both int). + MoveCursorToFormat = CSI+"%d;%dH" + SecondaryMoveCursorToFormat = CSI+"%d;%df" + MoveCursorUpFormat = CSI+"%dA" + MoveCursorDownFormat = CSI+"%dB" + MoveCursorRightFormat = CSI+"%dC" + MoveCursorLeftFormat = CSI+"%dD" + MoveCursorToBeginOfNextLineDownFormat = CSI+"%dE" + MoveCursorToBeginOfPrevLineUpFormat = CSI+"%dF" + MoveCursorToColumnFormat = CSI+"%dG" + + RequestCursorPositionReportFormat =CSI+"%d;%dR" + RequestCursorPosition = CSI+"6n" + + SaveCursorPositionDEC = ESC+" 7" + UnodCursorPositionDEC = ESC+" 8" + + SaveCursorPositionSCO = CSI+"s" + UndoCursorPositionSCO = CSI+"u" +) + +// Common private modes. +const ( + MakeCursorInvisible = CSI+"?25l" + MakeCursorVisible = CSI+"?25h" + + UndoScreen = CSI+"?47l" + SaveScreen = CSI+"?47h" + + EnableAltBuffer = CSI+"?1049h" + DisableAltBuffer = CSI+"?1049l" +) + diff --git a/aes/shortcut.go b/aes/shortcut.go index 683589d..3166ac2 100644 --- a/aes/shortcut.go +++ b/aes/shortcut.go @@ -2,6 +2,7 @@ package aes import "fmt" +// The type implements more or less type EffectText struct { Effects Effects Text string @@ -13,17 +14,24 @@ func (et EffectText) String() string { et.Effects.Format(), et.Text, ) } + +// Create new EffectText with formatted +// by the fmt.Sprintf string as text data. func ETF(format string, v ...any) EffectText { ret := EffectText{} ret.Text = fmt.Sprintf(format, v...) return ret } +// Returns the new EffectText with specified +// effects appended. func (et EffectText) With(effects ...Effect) EffectText { et.Effects = append(et.Effects, effects...) return et } +// Add the bold effect and return +// the resulting EffectText. func (et EffectText) Bold() EffectText { return et.With(EffectBold) } diff --git a/btest.sh b/btest similarity index 100% rename from btest.sh rename to btest diff --git a/cmd/termsize/main.go b/cmd/termsize/main.go index 2a480eb..5031766 100644 --- a/cmd/termsize/main.go +++ b/cmd/termsize/main.go @@ -8,12 +8,14 @@ import "surdeus.su/core/cli/aes" //import "fmt" func main() { + normalMode := true term, err := tx.NewTerminal(os.Stdin) if err != nil { // Some not terminal handling. log.Fatal("tx.NewTerminal(...): %s\n", err) } term.MakeRaw() + term.EnableAltBuffer() defer term.Restore() w, h, err := term.GetSize() @@ -24,17 +26,45 @@ func main() { for { key, _, err := term.ReadKey() + + if key == tx.KeyControlC { + break + } + if !normalMode && key == tx.KeyESC { + normalMode = true + continue + } + if normalMode { switch key { + case 'j': + term.MoveCursorDown(1) + case 'k': + term.MoveCursorUp(1) + case 'h': + term.MoveCursorLeft(1) + case 'l' : + term.MoveCursorRight(1) + case tx.KeyESC : + case 'i' : + normalMode = false + } + continue } + + if key == tx.KeyEnter { + term.NextLine(1) + //term.Print("enter") + continue + } + if err != nil { if err == io.EOF { break } log.Fatalf("term.ReadLine(...): %s\n", err) } - if key == tx.KeyControlC { - break - } term.Print( - "shit:", aes.ETF("%q", key).Bold().With(aes.EffectRedFG), "\r\n", + aes.ETF("%s", string(key)). + Bold(). + With(aes.EffectRedFG), ) } } diff --git a/tx/aes.go b/tx/aes.go index aa7a446..f895a21 100644 --- a/tx/aes.go +++ b/tx/aes.go @@ -1,8 +1,13 @@ package tx +import "surdeus.su/core/cli/aes" + type Key rune const ( KeyControlC Key = '\x03' + KeyESC = aes.KeyESC + KeyReturn = '\r' + KeyEnter = KeyReturn ) diff --git a/tx/term.go b/tx/term.go index 965d9e3..da51019 100644 --- a/tx/term.go +++ b/tx/term.go @@ -1,6 +1,7 @@ package tx import "golang.org/x/term" +import "surdeus.su/core/cli/aes" import "bufio" import "fmt" import "os" @@ -43,6 +44,7 @@ func (t *Terminal) MakeRaw() error { } func (t *Terminal) Restore() error { + t.DisableAltBuffer() if t == nil || t.prevState == nil { return nil } @@ -83,3 +85,35 @@ func (t *Terminal) Print(v ...any) (int, error) { str := fmt.Sprint(v...) return t.Write([]byte(str)) } + +func (t *Terminal) MoveCursorRight(n int) { + t.Printf(aes.MoveCursorRightFormat, n) +} + +func (t *Terminal) MoveCursorLeft(n int) { + t.Printf(aes.MoveCursorLeftFormat, n) +} + +func (t *Terminal) MoveCursorUp(n int) { + t.Printf(aes.MoveCursorUpFormat, n) +} + +func (t *Terminal) MoveCursorDown(n int) { + t.Printf(aes.MoveCursorDownFormat, n) +} + +func (t *Terminal) NextLine(n int) { + t.Printf( + aes.MoveCursorToBeginOfNextLineDownFormat, + n, + ) +} + +func (t *Terminal) EnableAltBuffer() { + t.Printf("%s", aes.EnableAltBuffer) +} + +func (t *Terminal) DisableAltBuffer() { + t.Printf("%s", aes.DisableAltBuffer) +} +