mirror of
https://github.com/ddworken/hishtory.git
synced 2024-11-23 08:45:16 +01:00
Add support for the TUI displaying custom columns
This commit is contained in:
parent
10d6c97a50
commit
16fa64b7a7
@ -397,7 +397,7 @@ func AddToDbIfNew(db *gorm.DB, entry data.HistoryEntry) {
|
||||
}
|
||||
}
|
||||
|
||||
func getCustomColumnValue(ctx *context.Context, header string, entry *data.HistoryEntry) (string, error) {
|
||||
func getCustomColumnValue(ctx *context.Context, header string, entry data.HistoryEntry) (string, error) {
|
||||
for _, c := range entry.CustomColumns {
|
||||
if strings.EqualFold(c.Name, header) {
|
||||
return c.Val, nil
|
||||
@ -412,6 +412,41 @@ func getCustomColumnValue(ctx *context.Context, header string, entry *data.Histo
|
||||
return "", fmt.Errorf("failed to find a column matching the column name %#v (is there a typo?)", header)
|
||||
}
|
||||
|
||||
func buildTableRow(ctx *context.Context, columnNames []string, entry data.HistoryEntry) ([]string, error) {
|
||||
row := make([]string, 0)
|
||||
for _, header := range columnNames {
|
||||
switch header {
|
||||
case "Hostname":
|
||||
row = append(row, entry.Hostname)
|
||||
case "CWD":
|
||||
row = append(row, entry.CurrentWorkingDirectory)
|
||||
case "Timestamp":
|
||||
row = append(row, entry.StartTime.Format("Jan 2 2006 15:04:05 MST"))
|
||||
case "Runtime":
|
||||
row = append(row, entry.EndTime.Sub(entry.StartTime).Round(time.Millisecond).String())
|
||||
case "Exit Code":
|
||||
row = append(row, fmt.Sprintf("%d", entry.ExitCode))
|
||||
case "Command":
|
||||
row = append(row, entry.Command)
|
||||
default:
|
||||
customColumnValue, err := getCustomColumnValue(ctx, header, entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row = append(row, customColumnValue)
|
||||
}
|
||||
}
|
||||
return row, nil
|
||||
}
|
||||
|
||||
func stringArrayToAnyArray(arr []string) []any {
|
||||
ret := make([]any, 0)
|
||||
for _, item := range arr {
|
||||
ret = append(ret, item)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func DisplayResults(ctx *context.Context, results []*data.HistoryEntry) error {
|
||||
config := hctx.GetConf(ctx)
|
||||
headerFmt := color.New(color.FgGreen, color.Underline).SprintfFunc()
|
||||
@ -424,30 +459,11 @@ func DisplayResults(ctx *context.Context, results []*data.HistoryEntry) error {
|
||||
tbl.WithHeaderFormatter(headerFmt)
|
||||
|
||||
for _, result := range results {
|
||||
row := make([]any, 0)
|
||||
for _, header := range config.DisplayedColumns {
|
||||
switch header {
|
||||
case "Hostname":
|
||||
row = append(row, result.Hostname)
|
||||
case "CWD":
|
||||
row = append(row, result.CurrentWorkingDirectory)
|
||||
case "Timestamp":
|
||||
row = append(row, result.StartTime.Format("Jan 2 2006 15:04:05 MST"))
|
||||
case "Runtime":
|
||||
row = append(row, result.EndTime.Sub(result.StartTime).Round(time.Millisecond).String())
|
||||
case "Exit Code":
|
||||
row = append(row, fmt.Sprintf("%d", result.ExitCode))
|
||||
case "Command":
|
||||
row = append(row, result.Command)
|
||||
default:
|
||||
customColumnValue, err := getCustomColumnValue(ctx, header, result)
|
||||
row, err := buildTableRow(ctx, config.DisplayedColumns, *result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
row = append(row, customColumnValue)
|
||||
}
|
||||
}
|
||||
tbl.AddRow(row...)
|
||||
tbl.AddRow(stringArrayToAnyArray(row))
|
||||
}
|
||||
|
||||
tbl.Print()
|
||||
|
@ -95,7 +95,7 @@ func (m model) Init() tea.Cmd {
|
||||
|
||||
func runQueryAndUpdateTable(m model) model {
|
||||
if m.runQuery != nil && *m.runQuery != m.lastQuery {
|
||||
rows, numEntries, err := getRows(m.ctx, *m.runQuery, PADDED_NUM_ENTRIES)
|
||||
rows, numEntries, err := getRows(m.ctx, hctx.GetConf(m.ctx).DisplayedColumns, *m.runQuery, PADDED_NUM_ENTRIES)
|
||||
if err != nil {
|
||||
m.searchErr = err
|
||||
return m
|
||||
@ -169,7 +169,18 @@ func (m model) View() string {
|
||||
return fmt.Sprintf("An unrecoverable error occured: %v\n", m.err)
|
||||
}
|
||||
if m.selected {
|
||||
selectedRow = m.table.SelectedRow()[4]
|
||||
indexOfCommand := -1
|
||||
for i, columnName := range hctx.GetConf(m.ctx).DisplayedColumns {
|
||||
if columnName == "Command" {
|
||||
indexOfCommand = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if indexOfCommand == -1 {
|
||||
selectedRow = "Error: Table doesn't have a column named `Command`?"
|
||||
return ""
|
||||
}
|
||||
selectedRow = m.table.SelectedRow()[indexOfCommand]
|
||||
return ""
|
||||
}
|
||||
loadingMessage := ""
|
||||
@ -186,7 +197,7 @@ func (m model) View() string {
|
||||
return fmt.Sprintf("\n%s\n%s%s\nSearch Query: %s\n\n%s\n", loadingMessage, warning, m.banner, m.queryInput.View(), baseStyle.Render(m.table.View()))
|
||||
}
|
||||
|
||||
func getRows(ctx *context.Context, query string, numEntries int) ([]table.Row, int, error) {
|
||||
func getRows(ctx *context.Context, columnNames []string, query string, numEntries int) ([]table.Row, int, error) {
|
||||
db := hctx.GetDb(ctx)
|
||||
data, err := data.Search(db, query, numEntries)
|
||||
if err != nil {
|
||||
@ -197,7 +208,10 @@ func getRows(ctx *context.Context, query string, numEntries int) ([]table.Row, i
|
||||
if i < len(data) {
|
||||
entry := data[i]
|
||||
entry.Command = strings.ReplaceAll(entry.Command, "\n", " ") // TODO: handle multi-line commands better here
|
||||
row := table.Row{entry.Hostname, entry.CurrentWorkingDirectory, entry.StartTime.Format("Jan 2 2006 15:04:05 MST"), fmt.Sprintf("%d", entry.ExitCode), entry.Command}
|
||||
row, err := buildTableRow(ctx, columnNames, *entry)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to build row for entry=%#v: %v", entry, err)
|
||||
}
|
||||
rows = append(rows, row)
|
||||
} else {
|
||||
rows = append(rows, table.Row{})
|
||||
@ -230,7 +244,7 @@ func makeTableColumns(ctx *context.Context, columnNames []string, rows []table.R
|
||||
|
||||
// Calculate the maximum column width that is useful for each column if we search for the empty string
|
||||
if bigQueryResults == nil {
|
||||
bigRows, _, err := getRows(ctx, "", 1000)
|
||||
bigRows, _, err := getRows(ctx, columnNames, "", 1000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -243,7 +257,7 @@ func makeTableColumns(ctx *context.Context, columnNames []string, rows []table.R
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get terminal size: %v", err)
|
||||
}
|
||||
for totalWidth < terminalWidth {
|
||||
for totalWidth < (terminalWidth - len(columnNames)) {
|
||||
prevTotalWidth := totalWidth
|
||||
for i := range columnNames {
|
||||
if columnWidths[i] < maximumColumnWidths[i]+5 {
|
||||
@ -256,6 +270,20 @@ func makeTableColumns(ctx *context.Context, columnNames []string, rows []table.R
|
||||
}
|
||||
}
|
||||
|
||||
// And if we are too large from the initial query, let's shrink things to make the table fit. We'll use the heuristic of always shrinking the widest column.
|
||||
for totalWidth > terminalWidth {
|
||||
largestColumnIdx := -1
|
||||
largestColumnSize := -1
|
||||
for i := range columnNames {
|
||||
if columnWidths[i] > largestColumnSize {
|
||||
largestColumnIdx = i
|
||||
largestColumnSize = columnWidths[i]
|
||||
}
|
||||
}
|
||||
columnWidths[largestColumnIdx] -= 2
|
||||
totalWidth -= 2
|
||||
}
|
||||
|
||||
// And finally, create some actual columns!
|
||||
columns := make([]table.Column, 0)
|
||||
for i, name := range columnNames {
|
||||
@ -272,7 +300,8 @@ func max(a, b int) int {
|
||||
}
|
||||
|
||||
func makeTable(ctx *context.Context, rows []table.Row) (table.Model, error) {
|
||||
columns, err := makeTableColumns(ctx, []string{"Hostname", "CWD", "Timestamp", "Exit Code", "Command"}, rows)
|
||||
config := hctx.GetConf(ctx)
|
||||
columns, err := makeTableColumns(ctx, config.DisplayedColumns, rows)
|
||||
if err != nil {
|
||||
return table.Model{}, err
|
||||
}
|
||||
@ -327,7 +356,7 @@ func makeTable(ctx *context.Context, rows []table.Row) (table.Model, error) {
|
||||
|
||||
func TuiQuery(ctx *context.Context, gitCommit, initialQuery string) error {
|
||||
lipgloss.SetColorProfile(termenv.ANSI)
|
||||
rows, numEntries, err := getRows(ctx, initialQuery, PADDED_NUM_ENTRIES)
|
||||
rows, numEntries, err := getRows(ctx, hctx.GetConf(ctx).DisplayedColumns, initialQuery, PADDED_NUM_ENTRIES)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user