Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,20 @@ A tab can hold up to **4 panes**. Instead of a single `command`, give it
`[[tabs.panes]]` entries. Each pane after the first sets `split` to `"down"`
(stacked) or `"right"` (side by side) — how it splits off the previous pane. An
omitted `split` defaults to `"down"`.
Each pane may also set an optional `label` — the name herdr shows on the pane
border (when `show_agent_labels_on_pane_borders` is on). A blank or omitted
`label` leaves the pane's default name untouched.

```toml
[[tabs]]
name = "server"

[[tabs.panes]]
label = "Server"
command = "php artisan serve"

[[tabs.panes]]
label = "Assets"
command = "npm run dev"
split = "down"
```
Expand Down
2 changes: 2 additions & 0 deletions examples/projects/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ command = "spiceedit"
name = "server"

[[tabs.panes]]
label = "Server"
command = "php artisan serve"

[[tabs.panes]]
label = "Assets"
command = "npm run dev"
split = "down"

Expand Down
9 changes: 9 additions & 0 deletions herdr.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,15 @@ func (c *herdrClient) tabRename(tabID, label string) error {
}, nil)
}

// paneRename sets a pane's human label — the name shown on pane borders and
// in pane lists.
func (c *herdrClient) paneRename(paneID, label string) error {
return c.call("pane.rename", map[string]any{
"pane_id": paneID,
"label": label,
}, nil)
}

// workspaceClose tears down a whole workspace and all of its tabs and panes.
func (c *herdrClient) workspaceClose(workspaceID string) error {
return c.call("workspace.close", map[string]any{
Expand Down
1 change: 1 addition & 0 deletions project.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const maxPanesPerTab = 4
type ProjectPane struct {
Command string `toml:"command"`
Split string `toml:"split"`
Label string `toml:"label"`
}

// ProjectTab is one tab in a project's workspace, in the order it should be
Expand Down
16 changes: 16 additions & 0 deletions project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,22 @@ func TestEffectivePanes(t *testing.T) {
if multi[2].Split != SplitRight {
t.Fatalf("pane 3 split = %q, want right", multi[2].Split)
}

// Labels pass through effectivePanes unchanged.
labeled := ProjectTab{Name: "services", Panes: []ProjectPane{
{Command: "make run", Label: "Server"},
{Command: "make minio", Split: "right", Label: "Minio"},
{Command: "", Label: "Empty"},
}}.effectivePanes()
if labeled[0].Label != "Server" {
t.Fatalf("pane 0 label = %q, want Server", labeled[0].Label)
}
if labeled[1].Label != "Minio" {
t.Fatalf("pane 1 label = %q, want Minio", labeled[1].Label)
}
if labeled[2].Label != "Empty" {
t.Fatalf("pane 2 label = %q, want Empty", labeled[2].Label)
}
}

// TestTabLabels confirms split tabs are annotated with a "×N" pane count while
Expand Down
6 changes: 6 additions & 0 deletions projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package main

import (
"fmt"
"log"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -136,6 +137,11 @@ func layoutTabs(client *herdrClient, ws, rootTab, rootPane string, tabs []Projec
return fmt.Errorf("split pane %d in tab %q: %w", j+1, t.Name, err)
}
}
if lbl := strings.TrimSpace(pane.Label); lbl != "" {
if err := client.paneRename(paneID, lbl); err != nil {
log.Printf("warning: failed to label pane %d in tab %q: %v", j+1, t.Name, err)
}
}
if strings.TrimSpace(pane.Command) != "" {
runs = append(runs, pendingRun{pane: paneID, command: pane.Command})
}
Expand Down