package formatter import ( "bytes" "fmt" "math" "os" "path/filepath" "strings" "github.com/alecthomas/chroma/v2/formatters" "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" ) type FileHandler func(args []string) error type FileHandlerRegistry struct { handlers map[string]FileHandler } var ReadHandlers = &FileHandlerRegistry{ handlers: make(map[string]FileHandler), } func (r *FileHandlerRegistry) Register(ext string, handler FileHandler) { r.handlers[ext] = handler } func (r *FileHandlerRegistry) GetHandler(filename string) FileHandler { ext := filepath.Ext(filename) if ext == "" || ext == "." { basename := filepath.Base(filename) if strings.HasPrefix(basename, "Dockerfile") { return r.handlers[".dockerfile"] } return nil } if handler, ok := r.handlers[ext]; ok { return handler } return nil } func ReadFileWithHighlight(file *os.File, filePath string) error { content := ReadFileContent(file) lexer := lexers.Match(filepath.Base(filePath)) if lexer == nil { lexer = lexers.Fallback } iterator, err := lexer.Tokenise(nil, content) if err != nil { return fmt.Errorf("error tokenizing: %w", err) } formatter_ := formatters.TTY256 style := styles.Get("monokai") if style == nil { style = styles.Fallback } var buf bytes.Buffer err = formatter_.Format(&buf, style, iterator) if err != nil { return fmt.Errorf("error formatting: %w", err) } lines := strings.Split(buf.String(), "\n") for i, line := range lines { if line != "" { fmt.Printf("%s%4d: %s%s\n", "\033[90m", i+1, "\033[0m", line) } } return nil } // FormatSize converts bytes to human-readable format func FormatSize(bytes int64) string { if bytes == 0 { return "0 B" } const unit = 1024 units := []string{"B", "KB", "MB", "GB", "TB", "PB"} exp := int(math.Log(float64(bytes)) / math.Log(float64(unit))) if exp > len(units)-1 { exp = len(units) - 1 } value := float64(bytes) / math.Pow(float64(unit), float64(exp)) return fmt.Sprintf("%.2f %s", value, units[exp]) } // CenterText centers text within a given width func CenterText(text string, width int) string { if len(text) >= width { return text[:width] } padding := width - len(text) left := padding / 2 right := padding - left return fmt.Sprintf("%s%s%s", repeat(" ", left), text, repeat(" ", right)) } func repeat(s string, count int) string { result := "" for i := 0; i < count; i++ { result += s } return result } func ReadFileContent(file *os.File) string { content := make([]byte, 0) buffer := make([]byte, 4096) for { n, err := file.Read(buffer) if n > 0 { content = append(content, buffer[:n]...) } if err != nil { break } } return string(content) }