| 517 | } |
| 518 | |
| 519 | func getRows(ctx context.Context, columnNames []string, shellName, defaultFilter, query string, numEntries int) ([]table.Row, []*data.HistoryEntry, error) { |
| 520 | db := hctx.GetDb(ctx) |
| 521 | config := hctx.GetConf(ctx) |
| 522 | if config.AiCompletion && strings.HasPrefix(query, "?") && len(query) > 1 { |
| 523 | return getRowsFromAiSuggestions(ctx, columnNames, shellName, query) |
| 524 | } |
| 525 | searchResults, err := lib.SearchWithCache(ctx, db, defaultFilter+" "+query, numEntries) |
| 526 | if err != nil { |
| 527 | return nil, nil, err |
| 528 | } |
| 529 | var rows []table.Row |
| 530 | var filteredData []*data.HistoryEntry |
| 531 | seenCommands := make(map[string]bool) |
| 532 | |
| 533 | for i := 0; i < numEntries; i++ { |
| 534 | if i < len(searchResults) { |
| 535 | entry := searchResults[i] |
| 536 | |
| 537 | if config.FilterDuplicateCommands && entry != nil { |
| 538 | cmd := strings.TrimSpace(entry.Command) |
| 539 | if seenCommands[cmd] { |
| 540 | continue |
| 541 | } |
| 542 | seenCommands[cmd] = true |
| 543 | } |
| 544 | |
| 545 | row, err := lib.BuildTableRow(ctx, columnNames, *entry, commandEscaper) |
| 546 | if err != nil { |
| 547 | return nil, nil, fmt.Errorf("failed to build row for entry=%#v: %w", entry, err) |
| 548 | } |
| 549 | rows = append(rows, row) |
| 550 | filteredData = append(filteredData, entry) |
| 551 | } else { |
| 552 | rows = append(rows, table.Row{}) |
| 553 | } |
| 554 | } |
| 555 | return rows, filteredData, nil |
| 556 | } |
| 557 | |
| 558 | func commandEscaper(cmd string) string { |
| 559 | if !strings.Contains(cmd, "\n") && !strings.Contains(cmd, "\t") { |