Skip to content

Commit f1d4ee9

Browse files
committed
Add simple text pager for interactive list commands
When stdin and stdout are both TTYs and a TableConfig is registered, list commands now stream their first page of rows to stdout and prompt: [space] more [enter] all [q|esc] quit Piped output and `--output json` keep the existing behavior. Alternative approach to #4729: instead of a full Bubble Tea TUI with scrolling, search, and cursor navigation, this renders a plain text table page-by-page and reads a single key in raw terminal mode to drive paging. Same TableConfig / Col[T] infrastructure, minus the interactive browser. Wiring: - `libs/tableview/config.go`, `context.go`, `wrap.go`: TableConfig, RowIterator, Col[T]/ColMax[T] generic helpers, cobra PreRunE wiring. - `libs/tableview/common.go`: extracted `computeColumnWidths` and `renderTableToLines` so they can be shared between the existing static aitools browser and the new pager. - `libs/tableview/simple.go`: the pager itself (raw-mode key reader, fetch-on-demand, per-column MaxWidth truncation). - `libs/cmdio/render.go`: `RenderIterator` routes to the pager when `Capabilities.SupportsPager()` returns true. - `cmd/workspace/*/overrides.go`: TableConfigs for the 18 most common list commands. Test plan: - `go test ./libs/tableview/... ./libs/cmdio/... ./cmd/workspace/...` - `make checks` passes - `make lintfull` passes (0 issues) - Manual smoke in a TTY: space pages through, enter drains, q/esc exits. Co-authored-by: Isaac
1 parent bfde237 commit f1d4ee9

30 files changed

Lines changed: 1000 additions & 51 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### CLI
88

99
* Added `--limit` flag to all paginated list commands for client-side result capping ([#4984](https://github.com/databricks/cli/pull/4984)).
10+
* Added simple text pager for interactive list commands. When stdin and stdout are both TTYs, `databricks <resource> list` streams the first page of rows and prompts `[space] more [enter] all [q|esc] quit`. Piped output and `--output json` keep the existing behavior.
1011

1112
### Bundles
1213

cmd/workspace/alerts/overrides.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package alerts
2+
3+
import (
4+
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
6+
"github.com/databricks/databricks-sdk-go/service/sql"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
func listOverride(listCmd *cobra.Command, _ *sql.ListAlertsRequest) {
11+
listCmd.Annotations["template"] = cmdio.Heredoc(`
12+
{{range .}}{{green "%s" .Id}} {{.DisplayName}} {{.State}}
13+
{{end}}`)
14+
15+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
16+
Columns: []tableview.ColumnDef{
17+
tableview.Col("ID", func(a sql.ListAlertsResponseAlert) string { return a.Id }),
18+
tableview.Col("Name", func(a sql.ListAlertsResponseAlert) string { return a.DisplayName }),
19+
tableview.Col("State", func(a sql.ListAlertsResponseAlert) string { return string(a.State) }),
20+
},
21+
})
22+
}
23+
24+
func init() {
25+
listOverrides = append(listOverrides, listOverride)
26+
}

cmd/workspace/apps/overrides.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
appsCli "github.com/databricks/cli/cmd/apps"
77
"github.com/databricks/cli/libs/cmdio"
8+
"github.com/databricks/cli/libs/tableview"
89
"github.com/databricks/databricks-sdk-go/service/apps"
910
"github.com/spf13/cobra"
1011
)
@@ -15,6 +16,25 @@ func listOverride(listCmd *cobra.Command, listReq *apps.ListAppsRequest) {
1516
listCmd.Annotations["template"] = cmdio.Heredoc(`
1617
{{range .}}{{.Name | green}} {{.Url}} {{if .ComputeStatus}}{{if eq .ComputeStatus.State "ACTIVE"}}{{green "%s" .ComputeStatus.State }}{{else}}{{blue "%s" .ComputeStatus.State}}{{end}}{{end}} {{if .ActiveDeployment}}{{if eq .ActiveDeployment.Status.State "SUCCEEDED"}}{{green "%s" .ActiveDeployment.Status.State }}{{else}}{{blue "%s" .ActiveDeployment.Status.State}}{{end}}{{end}}
1718
{{end}}`)
19+
20+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
21+
Columns: []tableview.ColumnDef{
22+
tableview.Col("Name", func(a apps.App) string { return a.Name }),
23+
tableview.Col("URL", func(a apps.App) string { return a.Url }),
24+
tableview.Col("Compute Status", func(a apps.App) string {
25+
if a.ComputeStatus != nil {
26+
return string(a.ComputeStatus.State)
27+
}
28+
return ""
29+
}),
30+
tableview.Col("Deploy Status", func(a apps.App) string {
31+
if a.ActiveDeployment != nil && a.ActiveDeployment.Status != nil {
32+
return string(a.ActiveDeployment.Status.State)
33+
}
34+
return ""
35+
}),
36+
},
37+
})
1838
}
1939

2040
func listDeploymentsOverride(listDeploymentsCmd *cobra.Command, listDeploymentsReq *apps.ListAppDeploymentsRequest) {

cmd/workspace/catalogs/overrides.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,27 @@ package catalogs
22

33
import (
44
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
56
"github.com/databricks/databricks-sdk-go/service/catalog"
67
"github.com/spf13/cobra"
78
)
89

910
func listOverride(listCmd *cobra.Command, listReq *catalog.ListCatalogsRequest) {
11+
// Template is the fallback for piped / JSON output. The simple pager
12+
// uses the TableConfig when stdin/stdout are TTYs.
1013
listCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
1114
{{header "Name"}} {{header "Type"}} {{header "Comment"}}`)
1215
listCmd.Annotations["template"] = cmdio.Heredoc(`
1316
{{range .}}{{.Name|green}} {{blue "%s" .CatalogType}} {{.Comment}}
1417
{{end}}`)
18+
19+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
20+
Columns: []tableview.ColumnDef{
21+
tableview.Col("Name", func(c catalog.CatalogInfo) string { return c.Name }),
22+
tableview.Col("Type", func(c catalog.CatalogInfo) string { return string(c.CatalogType) }),
23+
tableview.ColMax("Comment", 40, func(c catalog.CatalogInfo) string { return c.Comment }),
24+
},
25+
})
1526
}
1627

1728
func init() {

cmd/workspace/cluster-policies/overrides.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cluster_policies
22

33
import (
44
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
56
"github.com/databricks/databricks-sdk-go/service/compute"
67
"github.com/spf13/cobra"
78
)
@@ -10,6 +11,19 @@ func listOverride(listCmd *cobra.Command, _ *compute.ListClusterPoliciesRequest)
1011
listCmd.Annotations["template"] = cmdio.Heredoc(`
1112
{{range .}}{{.PolicyId | green}} {{.Name}}
1213
{{end}}`)
14+
15+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
16+
Columns: []tableview.ColumnDef{
17+
tableview.Col("Policy ID", func(p compute.Policy) string { return p.PolicyId }),
18+
tableview.Col("Name", func(p compute.Policy) string { return p.Name }),
19+
tableview.Col("Default", func(p compute.Policy) string {
20+
if p.IsDefault {
21+
return "yes"
22+
}
23+
return ""
24+
}),
25+
},
26+
})
1327
}
1428

1529
func getOverride(getCmd *cobra.Command, _ *compute.GetClusterPolicyRequest) {

cmd/workspace/clusters/overrides.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"strings"
55

66
"github.com/databricks/cli/libs/cmdio"
7+
"github.com/databricks/cli/libs/tableview"
78
"github.com/databricks/databricks-sdk-go/service/compute"
89
"github.com/spf13/cobra"
910
)
@@ -17,6 +18,14 @@ func listOverride(listCmd *cobra.Command, listReq *compute.ListClustersRequest)
1718
{{range .}}{{.ClusterId | green}} {{.ClusterName | cyan}} {{if eq .State "RUNNING"}}{{green "%s" .State}}{{else if eq .State "TERMINATED"}}{{red "%s" .State}}{{else}}{{blue "%s" .State}}{{end}}
1819
{{end}}`)
1920

21+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
22+
Columns: []tableview.ColumnDef{
23+
tableview.Col("Cluster ID", func(c compute.ClusterDetails) string { return c.ClusterId }),
24+
tableview.Col("Name", func(c compute.ClusterDetails) string { return c.ClusterName }),
25+
tableview.Col("State", func(c compute.ClusterDetails) string { return string(c.State) }),
26+
},
27+
})
28+
2029
listReq.FilterBy = &compute.ListClustersFilterBy{}
2130
listCmd.Flags().BoolVar(&listReq.FilterBy.IsPinned, "is-pinned", false, "Filter clusters by pinned status")
2231
listCmd.Flags().StringVar(&listReq.FilterBy.PolicyId, "policy-id", "", "Filter clusters by policy id")

cmd/workspace/external-locations/overrides.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package external_locations
22

33
import (
44
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
56
"github.com/databricks/databricks-sdk-go/service/catalog"
67
"github.com/spf13/cobra"
78
)
@@ -12,6 +13,14 @@ func listOverride(listCmd *cobra.Command, listReq *catalog.ListExternalLocations
1213
listCmd.Annotations["template"] = cmdio.Heredoc(`
1314
{{range .}}{{.Name|green}} {{.CredentialName|cyan}} {{.Url}}
1415
{{end}}`)
16+
17+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
18+
Columns: []tableview.ColumnDef{
19+
tableview.Col("Name", func(l catalog.ExternalLocationInfo) string { return l.Name }),
20+
tableview.Col("Credential", func(l catalog.ExternalLocationInfo) string { return l.CredentialName }),
21+
tableview.Col("URL", func(l catalog.ExternalLocationInfo) string { return l.Url }),
22+
},
23+
})
1524
}
1625

1726
func init() {

cmd/workspace/instance-pools/overrides.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@ package instance_pools
22

33
import (
44
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
6+
"github.com/databricks/databricks-sdk-go/service/compute"
57
"github.com/spf13/cobra"
68
)
79

810
func listOverride(listCmd *cobra.Command) {
911
listCmd.Annotations["template"] = cmdio.Heredoc(`
1012
{{range .}}{{.InstancePoolId|green}} {{.InstancePoolName}} {{.NodeTypeId}} {{.State}}
1113
{{end}}`)
14+
15+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
16+
Columns: []tableview.ColumnDef{
17+
tableview.Col("Pool ID", func(p compute.InstancePoolAndStats) string { return p.InstancePoolId }),
18+
tableview.Col("Name", func(p compute.InstancePoolAndStats) string { return p.InstancePoolName }),
19+
tableview.Col("Node Type", func(p compute.InstancePoolAndStats) string { return p.NodeTypeId }),
20+
tableview.Col("State", func(p compute.InstancePoolAndStats) string { return string(p.State) }),
21+
},
22+
})
1223
}
1324

1425
func init() {

cmd/workspace/jobs/overrides.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package jobs
22

33
import (
4+
"strconv"
5+
46
"github.com/databricks/cli/libs/cmdio"
7+
"github.com/databricks/cli/libs/tableview"
58
"github.com/databricks/databricks-sdk-go/service/jobs"
69
"github.com/spf13/cobra"
710
)
@@ -10,6 +13,18 @@ func listOverride(listCmd *cobra.Command, listReq *jobs.ListJobsRequest) {
1013
listCmd.Annotations["template"] = cmdio.Heredoc(`
1114
{{range .}}{{green "%d" .JobId}} {{.Settings.Name}}
1215
{{end}}`)
16+
17+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
18+
Columns: []tableview.ColumnDef{
19+
tableview.Col("Job ID", func(j jobs.BaseJob) string { return strconv.FormatInt(j.JobId, 10) }),
20+
tableview.Col("Name", func(j jobs.BaseJob) string {
21+
if j.Settings != nil {
22+
return j.Settings.Name
23+
}
24+
return ""
25+
}),
26+
},
27+
})
1328
}
1429

1530
func listRunsOverride(listRunsCmd *cobra.Command, listRunsReq *jobs.ListRunsRequest) {
@@ -18,6 +33,20 @@ func listRunsOverride(listRunsCmd *cobra.Command, listRunsReq *jobs.ListRunsRequ
1833
listRunsCmd.Annotations["template"] = cmdio.Heredoc(`
1934
{{range .}}{{green "%d" .JobId}} {{cyan "%d" .RunId}} {{if eq .State.ResultState "SUCCESS"}}{{"SUCCESS"|green}}{{else}}{{red "%s" .State.ResultState}}{{end}} {{.RunPageUrl}}
2035
{{end}}`)
36+
37+
tableview.SetTableConfigOnCmd(listRunsCmd, &tableview.TableConfig{
38+
Columns: []tableview.ColumnDef{
39+
tableview.Col("Job ID", func(r jobs.BaseRun) string { return strconv.FormatInt(r.JobId, 10) }),
40+
tableview.Col("Run ID", func(r jobs.BaseRun) string { return strconv.FormatInt(r.RunId, 10) }),
41+
tableview.Col("Result State", func(r jobs.BaseRun) string {
42+
if r.State != nil {
43+
return string(r.State.ResultState)
44+
}
45+
return ""
46+
}),
47+
tableview.Col("URL", func(r jobs.BaseRun) string { return r.RunPageUrl }),
48+
},
49+
})
2150
}
2251

2352
func init() {

cmd/workspace/lakeview/overrides.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
package lakeview
22

33
import (
4+
"github.com/databricks/cli/libs/cmdio"
5+
"github.com/databricks/cli/libs/tableview"
46
"github.com/databricks/databricks-sdk-go/service/dashboards"
57
"github.com/spf13/cobra"
68
)
79

10+
func listOverride(listCmd *cobra.Command, _ *dashboards.ListDashboardsRequest) {
11+
listCmd.Annotations["headerTemplate"] = cmdio.Heredoc(`
12+
{{header "Dashboard ID"}} {{header "Name"}} {{header "State"}}`)
13+
listCmd.Annotations["template"] = cmdio.Heredoc(`
14+
{{range .}}{{green "%s" .DashboardId}} {{.DisplayName}} {{blue "%s" .LifecycleState}}
15+
{{end}}`)
16+
17+
tableview.SetTableConfigOnCmd(listCmd, &tableview.TableConfig{
18+
Columns: []tableview.ColumnDef{
19+
tableview.Col("Dashboard ID", func(d dashboards.Dashboard) string { return d.DashboardId }),
20+
tableview.Col("Name", func(d dashboards.Dashboard) string { return d.DisplayName }),
21+
tableview.Col("State", func(d dashboards.Dashboard) string { return string(d.LifecycleState) }),
22+
},
23+
})
24+
}
25+
826
func publishOverride(cmd *cobra.Command, req *dashboards.PublishRequest) {
927
originalRunE := cmd.RunE
1028
cmd.RunE = func(cmd *cobra.Command, args []string) error {
@@ -15,5 +33,6 @@ func publishOverride(cmd *cobra.Command, req *dashboards.PublishRequest) {
1533
}
1634

1735
func init() {
36+
listOverrides = append(listOverrides, listOverride)
1837
publishOverrides = append(publishOverrides, publishOverride)
1938
}

0 commit comments

Comments
 (0)