summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/util
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-07-02 16:08:06 -0500
committeradamdottv <[email protected]>2025-07-02 16:08:11 -0500
commitc82a060eca41b990b4dd89cecffb874b2133af6f (patch)
treec3bb84aee2e621da9feb18f866c88fc51da0e7c1 /packages/tui/internal/util
parent63e783ef795d91c745733b945247e917f1683d31 (diff)
downloadopencode-c82a060eca41b990b4dd89cecffb874b2133af6f.tar.gz
opencode-c82a060eca41b990b4dd89cecffb874b2133af6f.zip
feat(tui): file viewer, select messages
Diffstat (limited to 'packages/tui/internal/util')
-rw-r--r--packages/tui/internal/util/file.go109
1 files changed, 109 insertions, 0 deletions
diff --git a/packages/tui/internal/util/file.go b/packages/tui/internal/util/file.go
new file mode 100644
index 000000000..2c0987dcf
--- /dev/null
+++ b/packages/tui/internal/util/file.go
@@ -0,0 +1,109 @@
+package util
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+ "unicode"
+
+ "github.com/charmbracelet/lipgloss/v2/compat"
+ "github.com/charmbracelet/x/ansi"
+ "github.com/sst/opencode/internal/styles"
+ "github.com/sst/opencode/internal/theme"
+)
+
+var RootPath string
+var CwdPath string
+
+type fileRenderer struct {
+ filename string
+ content string
+ height int
+}
+
+type fileRenderingOption func(*fileRenderer)
+
+func WithTruncate(height int) fileRenderingOption {
+ return func(c *fileRenderer) {
+ c.height = height
+ }
+}
+
+func RenderFile(
+ filename string,
+ content string,
+ width int,
+ options ...fileRenderingOption) string {
+ t := theme.CurrentTheme()
+ renderer := &fileRenderer{
+ filename: filename,
+ content: content,
+ }
+ for _, option := range options {
+ option(renderer)
+ }
+
+ lines := []string{}
+ for line := range strings.SplitSeq(content, "\n") {
+ line = strings.TrimRightFunc(line, unicode.IsSpace)
+ line = strings.ReplaceAll(line, "\t", " ")
+ lines = append(lines, line)
+ }
+ content = strings.Join(lines, "\n")
+
+ if renderer.height > 0 {
+ content = TruncateHeight(content, renderer.height)
+ }
+ content = fmt.Sprintf("```%s\n%s\n```", Extension(renderer.filename), content)
+ content = ToMarkdown(content, width, t.BackgroundPanel())
+ return content
+}
+
+func TruncateHeight(content string, height int) string {
+ lines := strings.Split(content, "\n")
+ if len(lines) > height {
+ return strings.Join(lines[:height], "\n")
+ }
+ return content
+}
+
+func Relative(path string) string {
+ path = strings.TrimPrefix(path, CwdPath+"/")
+ return strings.TrimPrefix(path, RootPath+"/")
+}
+
+func Extension(path string) string {
+ ext := filepath.Ext(path)
+ if ext == "" {
+ ext = ""
+ } else {
+ ext = strings.ToLower(ext[1:])
+ }
+ return ext
+}
+
+func ToMarkdown(content string, width int, backgroundColor compat.AdaptiveColor) string {
+ r := styles.GetMarkdownRenderer(width-7, backgroundColor)
+ content = strings.ReplaceAll(content, RootPath+"/", "")
+ rendered, _ := r.Render(content)
+ lines := strings.Split(rendered, "\n")
+
+ if len(lines) > 0 {
+ firstLine := lines[0]
+ cleaned := ansi.Strip(firstLine)
+ nospace := strings.ReplaceAll(cleaned, " ", "")
+ if nospace == "" {
+ lines = lines[1:]
+ }
+ if len(lines) > 0 {
+ lastLine := lines[len(lines)-1]
+ cleaned = ansi.Strip(lastLine)
+ nospace = strings.ReplaceAll(cleaned, " ", "")
+ if nospace == "" {
+ lines = lines[:len(lines)-1]
+ }
+ }
+ }
+ content = strings.Join(lines, "\n")
+ return strings.TrimSuffix(content, "\n")
+}