diff options
| author | adamdottv <[email protected]> | 2025-07-02 16:08:06 -0500 |
|---|---|---|
| committer | adamdottv <[email protected]> | 2025-07-02 16:08:11 -0500 |
| commit | c82a060eca41b990b4dd89cecffb874b2133af6f (patch) | |
| tree | c3bb84aee2e621da9feb18f866c88fc51da0e7c1 /packages/tui/internal/util | |
| parent | 63e783ef795d91c745733b945247e917f1683d31 (diff) | |
| download | opencode-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.go | 109 |
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") +} |
