(data interface{})
| 115 | } |
| 116 | |
| 117 | func printTable(data interface{}) error { |
| 118 | w := tabwriter.NewWriter(writer, 0, 0, 2, ' ', 0) |
| 119 | defer func() { |
| 120 | _ = w.Flush() |
| 121 | }() |
| 122 | |
| 123 | v := reflect.ValueOf(data) |
| 124 | |
| 125 | // Handle slice |
| 126 | if v.Kind() == reflect.Slice { |
| 127 | if v.Len() == 0 { |
| 128 | if _, err := fmt.Fprintln(writer, "(no results)"); err != nil { |
| 129 | return fmt.Errorf("failed to write table output: %w", err) |
| 130 | } |
| 131 | return nil |
| 132 | } |
| 133 | |
| 134 | // Get headers from first element |
| 135 | first := v.Index(0) |
| 136 | if first.Kind() == reflect.Ptr { |
| 137 | first = first.Elem() |
| 138 | } |
| 139 | |
| 140 | headers := getStructHeaders(first) |
| 141 | if _, err := fmt.Fprintln(w, strings.Join(headers, "\t")); err != nil { |
| 142 | return fmt.Errorf("failed to write table header: %w", err) |
| 143 | } |
| 144 | if _, err := fmt.Fprintln(w, strings.Repeat("-\t", len(headers))); err != nil { |
| 145 | return fmt.Errorf("failed to write table separator: %w", err) |
| 146 | } |
| 147 | |
| 148 | // Print rows |
| 149 | for i := 0; i < v.Len(); i++ { |
| 150 | elem := v.Index(i) |
| 151 | if elem.Kind() == reflect.Ptr { |
| 152 | elem = elem.Elem() |
| 153 | } |
| 154 | values := getStructValues(elem) |
| 155 | if _, err := fmt.Fprintln(w, strings.Join(values, "\t")); err != nil { |
| 156 | return fmt.Errorf("failed to write table row: %w", err) |
| 157 | } |
| 158 | } |
| 159 | } else if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) { |
| 160 | // Single struct |
| 161 | if v.Kind() == reflect.Ptr { |
| 162 | v = v.Elem() |
| 163 | } |
| 164 | headers := getStructHeaders(v) |
| 165 | values := getStructValues(v) |
| 166 | for i, h := range headers { |
| 167 | if _, err := fmt.Fprintf(w, "%s:\t%s\n", h, values[i]); err != nil { |
| 168 | return fmt.Errorf("failed to write table field: %w", err) |
| 169 | } |
| 170 | } |
| 171 | } else { |
| 172 | // Fallback to JSON |
| 173 | return printJSON(data) |
| 174 | } |
no test coverage detected