Files
b64encode/main.go
2024-08-16 19:51:38 +02:00

194 lines
4.7 KiB
Go

package main
import (
"encoding/base64"
"fmt"
"os"
"golang.design/x/clipboard"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/textarea"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
var (
cursorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("212"))
cursorLineStyle = lipgloss.NewStyle().
Background(lipgloss.Color("57")).
Foreground(lipgloss.Color("230"))
placeholderStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("238"))
endOfBufferStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("235"))
focusedPlaceholderStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("99"))
focusedBorderStyle = lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("238"))
blurredBorderStyle = lipgloss.NewStyle().
Border(lipgloss.HiddenBorder())
)
type keymap = struct {
next, copy, clear, quit key.Binding
}
func newTextarea() textarea.Model {
t := textarea.New()
t.Prompt = ""
t.Placeholder = "Type something"
t.ShowLineNumbers = true
t.Cursor.Style = cursorStyle
t.FocusedStyle.Placeholder = focusedPlaceholderStyle
t.BlurredStyle.Placeholder = placeholderStyle
t.FocusedStyle.CursorLine = cursorLineStyle
t.FocusedStyle.Base = focusedBorderStyle
t.BlurredStyle.Base = blurredBorderStyle
t.FocusedStyle.EndOfBuffer = endOfBufferStyle
t.BlurredStyle.EndOfBuffer = endOfBufferStyle
t.KeyMap.DeleteWordBackward.SetEnabled(false)
t.KeyMap.LineNext = key.NewBinding(key.WithKeys("down"))
t.KeyMap.LinePrevious = key.NewBinding(key.WithKeys("up"))
t.CharLimit = (1024 * 8) * 8
t.MaxHeight = 1024 * 8
t.Blur()
return t
}
type model struct {
width int
height int
keymap keymap
help help.Model
decoded textarea.Model
encoded textarea.Model
}
func newModel() model {
m := model{
encoded: newTextarea(),
decoded: newTextarea(),
help: help.New(),
keymap: keymap{
next: key.NewBinding(
key.WithKeys("tab"),
key.WithHelp("tab", "next"),
),
quit: key.NewBinding(
key.WithKeys("esc", "ctrl+c"),
key.WithHelp("esc", "quit"),
),
copy: key.NewBinding(
key.WithKeys("ctrl+x"),
key.WithHelp("ctrl+x", "copy"),
),
clear: key.NewBinding(
key.WithKeys("ctrl+r"),
key.WithHelp("ctrl+r", "clear"),
),
},
}
m.decoded.Focus()
return m
}
func (m model) Init() tea.Cmd {
return textarea.Blink
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch {
case key.Matches(msg, m.keymap.quit):
m.encoded.Blur()
m.decoded.Blur()
return m, tea.Quit
case key.Matches(msg, m.keymap.next):
if m.encoded.Focused() {
cmds = append(cmds, m.decoded.Focus())
m.encoded.Blur()
} else if m.decoded.Focused() {
cmds = append(cmds, m.encoded.Focus())
m.decoded.Blur()
}
case key.Matches(msg, m.keymap.copy):
if m.encoded.Focused() {
clipboard.Write(clipboard.FmtText, []byte(m.encoded.Value()))
} else if m.decoded.Focused() {
clipboard.Write(clipboard.FmtText, []byte(m.decoded.Value()))
}
case key.Matches(msg, m.keymap.clear):
m.encoded.SetValue("")
m.decoded.SetValue("")
}
case tea.WindowSizeMsg:
m.height = msg.Height
m.width = msg.Width
}
m.sizeInputs()
if m.encoded.Focused() {
decoded, err := base64.StdEncoding.DecodeString(m.encoded.Value())
if err != nil {
// log.Printf("failed to decode: %v", err)
} else {
m.decoded.SetValue(string(decoded))
}
} else if m.decoded.Focused() {
encoded := base64.StdEncoding.EncodeToString([]byte(m.decoded.Value()))
m.encoded.SetValue(string(encoded))
}
encoded, cmd := m.encoded.Update(msg)
cmds = append(cmds, cmd)
m.encoded = encoded
decoded, cmd := m.decoded.Update(msg)
cmds = append(cmds, cmd)
m.decoded = decoded
return m, tea.Batch(cmds...)
}
func (m *model) sizeInputs() {
m.encoded.SetHeight(m.height - 5)
m.decoded.SetHeight(m.height - 5)
m.encoded.SetWidth(m.width/2 - 5)
m.decoded.SetWidth(m.width/2 - 5)
}
func (m model) View() string {
help := m.help.ShortHelpView([]key.Binding{
m.keymap.next,
m.keymap.copy,
m.keymap.quit,
})
var views []string
views = append(views, m.decoded.View())
views = append(views, m.encoded.View())
return lipgloss.JoinHorizontal(lipgloss.Top, views...) + "\n" + help
}
func main() {
clipboard.Init()
if _, err := tea.NewProgram(newModel(), tea.WithAltScreen()).Run(); err != nil {
fmt.Println("Error while running program:", err)
os.Exit(1)
}
}