Add custom timestamp format as requested in the original HN thread

This commit is contained in:
David Dworken 2022-11-11 17:17:54 -08:00
parent 6f53fdd41e
commit e72ef668ea
No known key found for this signature in database
7 changed files with 81 additions and 5 deletions

View File

@ -114,6 +114,11 @@ But if you'd like to self-host the hishtory backend, you can! The backend is a s
hiSHtory imports your existing shell history by default. If for some reason this didn't work (e.g. you had your shell history in a non-standard file), you can import it by piping it into `hishtory import` (e.g. `cat ~/.my_history | hishtory import`).
</details>
<details>
<summary>Custom timestamp formats</summary>
You can configure a custom timestamp format for hiSHtory via `hishtory config-set timestamp-format '2006/Jan/2 15:04'`. The timestamp format string should be in [the format used by Go's `time.Format(...)`](https://pkg.go.dev/time#Time.Format).
</details>
<details>
<summary>Uninstalling</summary>
If you'd like to uninstall hishtory, just run `hishtory uninstall`. Note that this deletes the SQLite DB storing your history, so consider running a `hishtory export` first.

View File

@ -2098,6 +2098,39 @@ echo bar`)
}
}
func TestTimestampFormat(t *testing.T) {
// Setup
tester := zshTester{}
defer testutils.BackupAndRestore(t)()
userSecret := installHishtory(t, tester, "")
// Add some entries with fixed timestamps
tmz, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
t.Fatalf("failed to load timezone: %v", err)
}
entry1 := testutils.MakeFakeHistoryEntry("table_cmd1")
entry1.StartTime = time.Unix(1650096186, 0).In(tmz)
entry1.EndTime = time.Unix(1650096190, 0).In(tmz)
manuallySubmitHistoryEntry(t, userSecret, entry1)
entry2 := testutils.MakeFakeHistoryEntry("table_cmd2")
entry2.StartTime = time.Unix(1650096196, 0).In(tmz)
entry2.EndTime = time.Unix(1650096220, 0).In(tmz)
entry2.CurrentWorkingDirectory = "~/foo/"
entry2.ExitCode = 3
manuallySubmitHistoryEntry(t, userSecret, entry2)
// Set a custom timestamp format
tester.RunInteractiveShell(t, ` hishtory config-set timestamp-format '2006/Jan/2 15:04'`)
// And check that it is displayed in both the tui and the classic view
out := hishtoryQuery(t, tester, "-pipefail")
compareGoldens(t, out, "TestTimestampFormat-query")
out = captureTerminalOutput(t, tester, []string{"hishtory SPACE tquery SPACE -pipefail ENTER"})
out = strings.TrimSpace(strings.Split(out, "hishtory tquery")[1])
compareGoldens(t, out, "TestTimestampFormat-tquery")
}
func TestRemoveDuplicateRows(t *testing.T) {
// Setup
tester := zshTester{}

View File

@ -174,6 +174,8 @@ type ClientConfig struct {
IsOffline bool `json:"is_offline"`
// Whether duplicate commands should be displayed
FilterDuplicateCommands bool `json:"filter_duplicate_commands"`
// A format string for the timestamp
TimestampFormat string `json:"timestamp_format"`
}
type CustomColumnDefinition struct {
@ -215,6 +217,9 @@ func GetConfig() (ClientConfig, error) {
if config.DisplayedColumns == nil || len(config.DisplayedColumns) == 0 {
config.DisplayedColumns = []string{"Hostname", "CWD", "Timestamp", "Runtime", "Exit Code", "Command"}
}
if config.TimestampFormat == "" {
config.TimestampFormat = "Jan 2 2006 15:04:05 MST"
}
return config, nil
}

View File

@ -0,0 +1,3 @@
Hostname CWD Timestamp Runtime Exit Code Command
localhost ~/foo/ 2022/Apr/16 01:03 24s 3 table_cmd2
localhost /tmp/ 2022/Apr/16 01:03 4s 2 table_cmd1

View File

@ -0,0 +1,30 @@
-pipefail
Search Query: > -pipefail
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Hostname CWD Timestamp Runtime Exit Code Command │
│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│
│ localhost ~/foo/ 2022/Apr/16 01:03 24s 3 table_cmd2 │
│ localhost /tmp/ 2022/Apr/16 01:03 4s 2 table_cmd1 │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

View File

@ -435,7 +435,7 @@ func buildTableRow(ctx *context.Context, columnNames []string, entry data.Histor
case "CWD":
row = append(row, entry.CurrentWorkingDirectory)
case "Timestamp":
row = append(row, entry.StartTime.Format("Jan 2 2006 15:04:05 MST"))
row = append(row, entry.StartTime.Format(hctx.GetConf(ctx).TimestampFormat))
case "Runtime":
row = append(row, entry.EndTime.Sub(entry.StartTime).Round(time.Millisecond).String())
case "Exit Code":

View File

@ -184,6 +184,10 @@ func main() {
vals := os.Args[3:]
config.DisplayedColumns = vals
lib.CheckFatalError(hctx.SetConfig(config))
case "timestamp-format":
val := os.Args[3]
config.TimestampFormat = val
lib.CheckFatalError(hctx.SetConfig(config))
case "custom-columns":
log.Fatalf("Please use config-add and config-delete to interact with custom-columns")
default:
@ -257,7 +261,6 @@ func main() {
default:
log.Fatalf("Unrecognized config key: %s", key)
}
case "reupload":
// Purposefully undocumented since this command is generally not necessary to run
lib.CheckFatalError(lib.Reupload(hctx.MakeContext()))
@ -476,6 +479,3 @@ func export(ctx *context.Context, query string) {
}
// TODO(feature): Add a session_id column that corresponds to the shell session the command was run in
// TODO: add a config option for timestamp formatting
// TODO: handle control-c in the TUI