fix(tabs): show renamed tabs consistently
- commit
- c8d167ec624f8909365962f14e44816edd969af8
- author
- brice · · 2026-07-09 18:12 UTC
- parent
- 4b56f28
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +16 -5
M internal/usecase/daemon/input_test.go +5 -2
| @@ -176,10 +176,13 @@ func TestRNTOpensPromptAndRenamesActiveTab(t *testing.T) { | |||
| 176 | 176 | d.handleInput(sess, ac, []byte("\x1b ")) | |
| 177 | 177 | awaitFrame(t, sends, ports.MsgOutput) | |
| 178 | 178 | d.handleInput(sess, ac, []byte("RNT\r")) | |
| 179 | - | awaitFrame(t, sends, ports.MsgOutput) | |
| 179 | + | out := awaitFrame(t, sends, ports.MsgOutput) | |
| 180 | 180 | require.True(t, ac.promptActive()) | |
| 181 | + | msg, err := ports.UnmarshalOutput(out.Payload) | |
| 182 | + | require.NoError(t, err) | |
| 183 | + | require.Contains(t, string(msg.Data), "> 2") | |
| 181 | 184 | ||
| 182 | - | d.handleInput(sess, ac, []byte("logs\r")) | |
| 185 | + | d.handleInput(sess, ac, []byte("\x7flogs\r")) | |
| 183 | 186 | awaitFrame(t, sends, ports.MsgOutput) | |
| 184 | 187 | ||
| 185 | 188 | require.False(t, ac.promptActive()) | |
| @@ -176,10 +176,13 @@ func TestRNTOpensPromptAndRenamesActiveTab(t *testing.T) { | |||||
| 176 | d.handleInput(sess, ac, []byte("\x1b ")) | 176 | d.handleInput(sess, ac, []byte("\x1b ")) | ||
| 177 | awaitFrame(t, sends, ports.MsgOutput) | 177 | awaitFrame(t, sends, ports.MsgOutput) | ||
| 178 | d.handleInput(sess, ac, []byte("RNT\r")) | 178 | d.handleInput(sess, ac, []byte("RNT\r")) | ||
| 179 | - | awaitFrame(t, sends, ports.MsgOutput) | 179 | + | out := awaitFrame(t, sends, ports.MsgOutput) |
| 180 | require.True(t, ac.promptActive()) | 180 | require.True(t, ac.promptActive()) | ||
| 181 | + | msg, err := ports.UnmarshalOutput(out.Payload) | |||
| 182 | + | require.NoError(t, err) | |||
| 183 | + | require.Contains(t, string(msg.Data), "> 2") | |||
| 181 | 184 | ||||
| 182 | - | d.handleInput(sess, ac, []byte("logs\r")) | 185 | + | d.handleInput(sess, ac, []byte("\x7flogs\r")) |
| 183 | awaitFrame(t, sends, ports.MsgOutput) | 186 | awaitFrame(t, sends, ports.MsgOutput) | ||
| 184 | 187 | ||||
| 185 | require.False(t, ac.promptActive()) | 188 | require.False(t, ac.promptActive()) | ||
M internal/usecase/daemon/palette.go +5 -0
| @@ -1,6 +1,8 @@ | |||
| 1 | 1 | package daemon | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "strconv" | |
| 5 | + | ||
| 4 | 6 | "github.com/bnema/vev/internal/domain" | |
| 5 | 7 | "github.com/bnema/vev/internal/usecase/command" | |
| 6 | 8 | "github.com/bnema/vev/internal/usecase/palette" | |
| @@ -154,6 +156,9 @@ func (e paletteExec) RenameTab() error { | |||
| 154 | 156 | } | |
| 155 | 157 | e.sess.mu.Lock() | |
| 156 | 158 | currentName := tb.name | |
| 159 | + | if currentName == "" { | |
| 160 | + | currentName = strconv.Itoa(e.sess.active + 1) | |
| 161 | + | } | |
| 157 | 162 | e.sess.mu.Unlock() | |
| 158 | 163 | e.d.enterPrompt(e.sess, e.ac, " Rename tab ", currentName, func(name string) error { | |
| 159 | 164 | return e.d.renameTab(e.sess, tb, name) | |
| @@ -1,6 +1,8 @@ | |||||
| 1 | package daemon | 1 | package daemon | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "strconv" | |||
| 5 | + | ||||
| 4 | "github.com/bnema/vev/internal/domain" | 6 | "github.com/bnema/vev/internal/domain" | ||
| 5 | "github.com/bnema/vev/internal/usecase/command" | 7 | "github.com/bnema/vev/internal/usecase/command" | ||
| 6 | "github.com/bnema/vev/internal/usecase/palette" | 8 | "github.com/bnema/vev/internal/usecase/palette" | ||
| @@ -154,6 +156,9 @@ func (e paletteExec) RenameTab() error { | |||||
| 154 | } | 156 | } | ||
| 155 | e.sess.mu.Lock() | 157 | e.sess.mu.Lock() | ||
| 156 | currentName := tb.name | 158 | currentName := tb.name | ||
| 159 | + | if currentName == "" { | |||
| 160 | + | currentName = strconv.Itoa(e.sess.active + 1) | |||
| 161 | + | } | |||
| 157 | e.sess.mu.Unlock() | 162 | e.sess.mu.Unlock() | ||
| 158 | e.d.enterPrompt(e.sess, e.ac, " Rename tab ", currentName, func(name string) error { | 163 | e.d.enterPrompt(e.sess, e.ac, " Rename tab ", currentName, func(name string) error { | ||
| 159 | return e.d.renameTab(e.sess, tb, name) | 164 | return e.d.renameTab(e.sess, tb, name) | ||
M internal/usecase/daemon/picker.go +4 -1
| @@ -71,7 +71,10 @@ func (d *Daemon) pickerViews(cur *session) ([]picker.SessionView, int) { | |||
| 71 | 71 | view := picker.SessionView{ID: s.id, Name: s.name, Active: s.active, Tabs: make([]string, len(s.tabs))} | |
| 72 | 72 | sessionAttention := false | |
| 73 | 73 | for i, tb := range s.tabs { | |
| 74 | - | label := strconv.Itoa(i + 1) | |
| 74 | + | label := tb.name | |
| 75 | + | if label == "" { | |
| 76 | + | label = strconv.Itoa(i + 1) | |
| 77 | + | } | |
| 75 | 78 | if tb.attention { | |
| 76 | 79 | label = attentionSuffix(label) | |
| 77 | 80 | sessionAttention = true | |
| @@ -71,7 +71,10 @@ func (d *Daemon) pickerViews(cur *session) ([]picker.SessionView, int) { | |||||
| 71 | view := picker.SessionView{ID: s.id, Name: s.name, Active: s.active, Tabs: make([]string, len(s.tabs))} | 71 | view := picker.SessionView{ID: s.id, Name: s.name, Active: s.active, Tabs: make([]string, len(s.tabs))} | ||
| 72 | sessionAttention := false | 72 | sessionAttention := false | ||
| 73 | for i, tb := range s.tabs { | 73 | for i, tb := range s.tabs { | ||
| 74 | - | label := strconv.Itoa(i + 1) | 74 | + | label := tb.name |
| 75 | + | if label == "" { | |||
| 76 | + | label = strconv.Itoa(i + 1) | |||
| 77 | + | } | |||
| 75 | if tb.attention { | 78 | if tb.attention { | ||
| 76 | label = attentionSuffix(label) | 79 | label = attentionSuffix(label) | ||
| 77 | sessionAttention = true | 80 | sessionAttention = true | ||
M internal/usecase/daemon/picker_test.go +2 -2
| @@ -38,7 +38,7 @@ func TestPickerViewsAddsBellSuffixForAttention(t *testing.T) { | |||
| 38 | 38 | ctx, cancel := context.WithCancel(d.serveCtx) | |
| 39 | 39 | defer cancel() | |
| 40 | 40 | current := &session{id: "s1", name: "alpha", ctx: ctx, cancel: cancel, tabs: []*tab{{}, {}}} | |
| 41 | - | ringing := &session{id: "s2", name: "beta", ctx: ctx, cancel: cancel, tabs: []*tab{{}, {}}} | |
| 41 | + | ringing := &session{id: "s2", name: "beta", ctx: ctx, cancel: cancel, tabs: []*tab{{name: "shell"}, {name: "logs"}}} | |
| 42 | 42 | ringing.mu.Lock() | |
| 43 | 43 | ringing.tabs[1].attention = true | |
| 44 | 44 | ringing.tabs[1].attentionAt = time.Unix(10, 0) | |
| @@ -53,7 +53,7 @@ func TestPickerViewsAddsBellSuffixForAttention(t *testing.T) { | |||
| 53 | 53 | require.Equal(t, "alpha", views[0].Name) | |
| 54 | 54 | require.Equal(t, []string{"1", "2"}, views[0].Tabs) | |
| 55 | 55 | require.Equal(t, "beta ", views[1].Name) | |
| 56 | - | require.Equal(t, []string{"1", "2 "}, views[1].Tabs) | |
| 56 | + | require.Equal(t, []string{"shell", "logs "}, views[1].Tabs) | |
| 57 | 57 | } | |
| 58 | 58 | ||
| 59 | 59 | func TestPickerResumesStoppedSessionWithPersistedTabNames(t *testing.T) { | |
| @@ -38,7 +38,7 @@ func TestPickerViewsAddsBellSuffixForAttention(t *testing.T) { | |||||
| 38 | ctx, cancel := context.WithCancel(d.serveCtx) | 38 | ctx, cancel := context.WithCancel(d.serveCtx) | ||
| 39 | defer cancel() | 39 | defer cancel() | ||
| 40 | current := &session{id: "s1", name: "alpha", ctx: ctx, cancel: cancel, tabs: []*tab{{}, {}}} | 40 | current := &session{id: "s1", name: "alpha", ctx: ctx, cancel: cancel, tabs: []*tab{{}, {}}} | ||
| 41 | - | ringing := &session{id: "s2", name: "beta", ctx: ctx, cancel: cancel, tabs: []*tab{{}, {}}} | 41 | + | ringing := &session{id: "s2", name: "beta", ctx: ctx, cancel: cancel, tabs: []*tab{{name: "shell"}, {name: "logs"}}} |
| 42 | ringing.mu.Lock() | 42 | ringing.mu.Lock() | ||
| 43 | ringing.tabs[1].attention = true | 43 | ringing.tabs[1].attention = true | ||
| 44 | ringing.tabs[1].attentionAt = time.Unix(10, 0) | 44 | ringing.tabs[1].attentionAt = time.Unix(10, 0) | ||
| @@ -53,7 +53,7 @@ func TestPickerViewsAddsBellSuffixForAttention(t *testing.T) { | |||||
| 53 | require.Equal(t, "alpha", views[0].Name) | 53 | require.Equal(t, "alpha", views[0].Name) | ||
| 54 | require.Equal(t, []string{"1", "2"}, views[0].Tabs) | 54 | require.Equal(t, []string{"1", "2"}, views[0].Tabs) | ||
| 55 | require.Equal(t, "beta ", views[1].Name) | 55 | require.Equal(t, "beta ", views[1].Name) | ||
| 56 | - | require.Equal(t, []string{"1", "2 "}, views[1].Tabs) | 56 | + | require.Equal(t, []string{"shell", "logs "}, views[1].Tabs) |
| 57 | } | 57 | } | ||
| 58 | 58 | ||||
| 59 | func TestPickerResumesStoppedSessionWithPersistedTabNames(t *testing.T) { | 59 | func TestPickerResumesStoppedSessionWithPersistedTabNames(t *testing.T) { | ||