package main import ( "context" "fmt" "io" "log" "os" "strings" "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 { 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 out textarea.Model } func newModel() model { m := model{ out: newTextarea(), help: help.New(), keymap: keymap{ 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.out.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.out.Blur() return m, tea.Quit case key.Matches(msg, m.keymap.copy): clipboard.Write(clipboard.FmtText, []byte(m.out.Value())) case key.Matches(msg, m.keymap.clear): m.out.SetValue("") lines = lines[:0] } case tea.WindowSizeMsg: m.height = msg.Height m.width = msg.Width } m.sizeInputs() encoded, cmd := m.out.Update(msg) cmds = append(cmds, cmd) m.out = encoded return m, tea.Batch(cmds...) } func (m *model) sizeInputs() { m.out.SetHeight(m.height - 5) m.out.SetWidth(m.width - 5) } var lines []string func (m model) View() string { help := m.help.ShortHelpView([]key.Binding{ m.keymap.copy, m.keymap.quit, }) var views []string m.out.SetValue(strings.Join(lines, "\n")) views = append(views, m.out.View()) return lipgloss.JoinHorizontal(lipgloss.Top, views...) + "\n" + help } var Error *log.Logger var Warning *log.Logger func init() { log.SetFlags(log.Lmicroseconds | log.Lshortfile) logFile, err := os.Create("main.log") if err != nil { log.Printf("Error creating log file: %v", err) os.Exit(1) } logger := io.MultiWriter(logFile) log.SetOutput(logger) Error = log.New(io.MultiWriter(logFile, os.Stderr), fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) Warning = log.New(io.MultiWriter(logFile), fmt.Sprintf("%sWarning:%s ", "\033[0;93m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) } func main() { err := clipboard.Init() if err != nil { panic(err) } go func() { ch := clipboard.Watch(context.TODO(), clipboard.FmtText) for data := range ch { // log.Printf("%#v", m.out.Value() + "\n" + string(data)) // m.out.SetValue(m.out.Value() + "\n" + string(data)) lines = append(lines, string(data)) } }() if _, err := tea.NewProgram(newModel(), tea.WithAltScreen()).Run(); err != nil { fmt.Println("Error while running program:", err) os.Exit(1) } }