wrapText quebra o texto em linhas que não excedem o limite. Versão production-ready: - Preserva quebras de linha originais - Faz word-wrap por largura visível (ignora ANSI) - Não destrói formatação do markdown renderizado (ANSI + linhas)
(text string, limit int)
| 779 | // - Faz word-wrap por largura visível (ignora ANSI) |
| 780 | // - Não destrói formatação do markdown renderizado (ANSI + linhas) |
| 781 | func wrapText(text string, limit int) []string { |
| 782 | if limit <= 0 { |
| 783 | return []string{text} |
| 784 | } |
| 785 | |
| 786 | var finalLines []string |
| 787 | paragraphs := strings.Split(text, "\n") |
| 788 | |
| 789 | for _, p := range paragraphs { |
| 790 | // Preserva linha vazia |
| 791 | if p == "" { |
| 792 | finalLines = append(finalLines, "") |
| 793 | continue |
| 794 | } |
| 795 | |
| 796 | // Word wrap baseado em largura visível |
| 797 | words := strings.Fields(p) |
| 798 | if len(words) == 0 { |
| 799 | finalLines = append(finalLines, "") |
| 800 | continue |
| 801 | } |
| 802 | |
| 803 | var line strings.Builder |
| 804 | curLen := 0 |
| 805 | |
| 806 | flushLine := func() { |
| 807 | finalLines = append(finalLines, line.String()) |
| 808 | line.Reset() |
| 809 | curLen = 0 |
| 810 | } |
| 811 | |
| 812 | // emitLongWord quebra uma palavra maior que o limite em pedaços |
| 813 | // (rune-aware), empurra os pedaços completos para finalLines e |
| 814 | // deixa o último pedaço como início da linha corrente. |
| 815 | emitLongWord := func(w string) { |
| 816 | chunks := hardBreakWord(w, limit) |
| 817 | for i := 0; i < len(chunks)-1; i++ { |
| 818 | finalLines = append(finalLines, chunks[i]) |
| 819 | } |
| 820 | last := chunks[len(chunks)-1] |
| 821 | line.WriteString(last) |
| 822 | curLen = VisibleLen(last) |
| 823 | } |
| 824 | |
| 825 | for _, w := range words { |
| 826 | wLen := VisibleLen(w) |
| 827 | if curLen == 0 { |
| 828 | // Palavra única maior que o limite (ex.: o JSON de |
| 829 | // `last-applied-configuration` sem espaços) precisa ser |
| 830 | // quebrada aqui também — caso contrário ela é escrita |
| 831 | // inteira e estoura a largura do box. |
| 832 | if wLen > limit { |
| 833 | emitLongWord(w) |
| 834 | } else { |
| 835 | line.WriteString(w) |
| 836 | curLen = wLen |
| 837 | } |
| 838 | continue |