Skip to content

Commit

Permalink
Separates selector for unix and windows
Browse files Browse the repository at this point in the history
Signed-off-by: Saahil Bhavsar <[email protected]>
  • Loading branch information
SaahilNotSahil committed Jul 25, 2024
1 parent 58cb8f9 commit 2688142
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build !windows
// +build !windows

package selector

import (
Expand Down Expand Up @@ -81,7 +84,9 @@ func (m *Menu) Display() string {
return ""
} else if keyCode == enter {
menuItem := m.MenuItems[m.CursorPos]

fmt.Println("\r")

return menuItem.ID
} else if keyCode == up {
m.CursorPos = (m.CursorPos + len(m.MenuItems) - 1) % len(m.MenuItems)
Expand Down Expand Up @@ -109,9 +114,8 @@ func getInput() byte {
log.Fatal(err)
}

var read int
readBytes := make([]byte, 3)
read, err = t.Read(readBytes)
read, err := t.Read(readBytes)

t.Restore()
t.Close()
Expand Down
153 changes: 153 additions & 0 deletions internal/pkg/selector/selector_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//go:build windows
// +build windows

package selector

import (
"fmt"
"log"
"os"

"github.com/buger/goterm"
"golang.org/x/sys/windows"
)

type Menu struct {
Prompt string
CursorPos int
MenuItems []*MenuItem
}

type MenuItem struct {
Text string
ID string
}

var up byte = 65
var down byte = 66
var escape byte = 27
var enter byte = 13
var ctrl_c byte = 3

var keys = map[byte]bool{
up: true,
down: true,
}

func (m *Menu) AddItem(option string, id string) *Menu {
menuItem := &MenuItem{
Text: option,
ID: id,
}

m.MenuItems = append(m.MenuItems, menuItem)

return m
}

func (m *Menu) renderMenuItems(redraw bool) {
if redraw {
fmt.Printf("\033[%dA", len(m.MenuItems)-1)
}

for index, menuItem := range m.MenuItems {
var newline = "\n"

if index == len(m.MenuItems)-1 {
newline = ""
}

menuItemText := menuItem.Text
cursor := " "
if index == m.CursorPos {
cursor = goterm.Color("> ", goterm.YELLOW)
menuItemText = goterm.Color(menuItemText, goterm.YELLOW)
}

fmt.Printf("\r%s %s%s", cursor, menuItemText, newline)
}
}

func (m *Menu) Display() string {
defer func() {
fmt.Printf("\033[?25h")
}()

fmt.Printf("%s\n", goterm.Color(goterm.Bold(m.Prompt)+":", goterm.CYAN))

m.renderMenuItems(false)

fmt.Printf("\033[?25l")

for {
keyCode := getInput()
if keyCode == escape {
return ""
} else if keyCode == enter {
menuItem := m.MenuItems[m.CursorPos]

fmt.Println("\r")

return menuItem.ID
} else if keyCode == up {
m.CursorPos = (m.CursorPos + len(m.MenuItems) - 1) % len(m.MenuItems)
m.renderMenuItems(true)
} else if keyCode == down {
m.CursorPos = (m.CursorPos + 1) % len(m.MenuItems)
m.renderMenuItems(true)
} else if keyCode == ctrl_c {
return ""
}
}
}

func (m *Menu) Clear() {
for i := 0; i < (len(m.MenuItems) + 1); i++ {
fmt.Print("\033[F\033[K")
}
}

func getInput() byte {
hConsole := windows.Handle(os.Stdin.Fd())

var originalMode uint32

err := windows.GetConsoleMode(hConsole, &originalMode)
if err != nil {
log.Fatal(err)
}

rawMode := originalMode &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_INPUT)

err = windows.SetConsoleMode(hConsole, rawMode)
if err != nil {
log.Fatal(err)
}

defer func() {
windows.SetConsoleMode(hConsole, originalMode)
}()

readBytes := make([]byte, 3)
read, err := os.Stdin.Read(readBytes)
if err != nil {
log.Fatal(err)
}

if read == 3 {
if _, ok := keys[readBytes[2]]; ok {
return readBytes[2]
}
} else {
return readBytes[0]
}

return 0
}

func NewMenu(prompt string) *Menu {
return &Menu{
Prompt: prompt,
MenuItems: make([]*MenuItem, 0),
}
}

0 comments on commit 2688142

Please sign in to comment.