qr.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package qr
  2. import (
  3. "strings"
  4. "github.com/charmbracelet/lipgloss"
  5. "github.com/sst/opencode/internal/theme"
  6. "rsc.io/qr"
  7. )
  8. var tops_bottoms = []rune{' ', '▀', '▄', '█'}
  9. // Generate a text string to a QR code, which you can write to a terminal or file.
  10. func Generate(text string) (string, int, error) {
  11. code, err := qr.Encode(text, qr.Level(0))
  12. if err != nil {
  13. return "", 0, err
  14. }
  15. t := theme.CurrentTheme()
  16. if t == nil {
  17. return "", 0, err
  18. }
  19. // Create lipgloss style for QR code with theme colors
  20. qrStyle := lipgloss.NewStyle().
  21. Foreground(t.Text()).
  22. Background(t.Background())
  23. var result strings.Builder
  24. // content
  25. for y := 0; y < code.Size-1; y += 2 {
  26. var line strings.Builder
  27. for x := 0; x < code.Size; x += 1 {
  28. var num int8
  29. if code.Black(x, y) {
  30. num += 1
  31. }
  32. if code.Black(x, y+1) {
  33. num += 2
  34. }
  35. line.WriteRune(tops_bottoms[num])
  36. }
  37. result.WriteString(qrStyle.Render(line.String()) + "\n")
  38. }
  39. // add lower border when required (only required when QR size is odd)
  40. if code.Size%2 == 1 {
  41. var borderLine strings.Builder
  42. for range code.Size {
  43. borderLine.WriteRune('▀')
  44. }
  45. result.WriteString(qrStyle.Render(borderLine.String()) + "\n")
  46. }
  47. return result.String(), code.Size, nil
  48. }