Skip to content

Commit 889c739

Browse files
authored
submit: Allow configuring navigation comment marker (#903)
Allow users to customize the marker used in navigation comments via spice.submit.navigationCommentStyle.marker configuration option. Resolves #877
1 parent bc3b8ed commit 889c739

File tree

8 files changed

+82
-12
lines changed

8 files changed

+82
-12
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: Added
2+
body: >-
3+
submit: Add `spice.submit.navigationCommentStyle.marker` configuration option
4+
to customize the marker in navigation comments
5+
time: 2025-10-18T16:59:37.900306-07:00

doc/includes/cli-reference.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ or --nav-comment=multiple to post those comments only if there are multiple CRs
251251
* `-l`, `--label=LABEL,...`: Add labels to the change request. Pass multiple times or separate with commas.
252252
* `--no-web`: Alias for --web=false.
253253

254-
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
254+
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentStyle.marker](/cli/config.md#spicesubmitnavigationcommentstylemarker), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
255255

256256
### gs stack restack
257257

@@ -363,7 +363,7 @@ or --nav-comment=multiple to post those comments only if there are multiple CRs
363363
* `--no-web`: Alias for --web=false.
364364
* `--branch=NAME`: Branch to start at
365365

366-
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
366+
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentStyle.marker](/cli/config.md#spicesubmitnavigationcommentstylemarker), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
367367

368368
### gs upstack restack
369369

@@ -512,7 +512,7 @@ or --nav-comment=multiple to post those comments only if there are multiple CRs
512512
* `--no-web`: Alias for --web=false.
513513
* `--branch=NAME`: Branch to start at
514514

515-
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
515+
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentStyle.marker](/cli/config.md#spicesubmitnavigationcommentstylemarker), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.updateOnly](/cli/config.md#spicesubmitupdateonly), [spice.submit.web](/cli/config.md#spicesubmitweb)
516516

517517
### gs downstack edit
518518

@@ -941,7 +941,7 @@ or --nav-comment=multiple to post those comments only if there are multiple CRs
941941
* `--body=BODY`: Body of the change request
942942
* `--branch=NAME`: Branch to submit
943943

944-
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.web](/cli/config.md#spicesubmitweb)
944+
**Configuration**: [spice.submit.draft](/cli/config.md#spicesubmitdraft), [spice.submit.label](/cli/config.md#spicesubmitlabel), [spice.submit.listTemplatesTimeout](/cli/config.md#spicesubmitlisttemplatestimeout), [spice.submit.navigationComment](/cli/config.md#spicesubmitnavigationcomment), [spice.submit.navigationCommentStyle.marker](/cli/config.md#spicesubmitnavigationcommentstylemarker), [spice.submit.navigationCommentSync](/cli/config.md#spicesubmitnavigationcommentsync), [spice.submit.publish](/cli/config.md#spicesubmitpublish), [spice.submit.template](/cli/config.md#spicesubmittemplate), [spice.submit.web](/cli/config.md#spicesubmitweb)
945945

946946
## Commit
947947

doc/src/cli/config.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,29 @@ When set to `downstack`, any time a branch is submitted,
393393
git-spice will update the navigation comment for that branch
394394
and all branches below it in the stack.
395395

396+
### spice.submit.navigationCommentStyle.marker
397+
398+
<!-- gs:version unreleased -->
399+
400+
Specifies the marker to use for the current change in navigation comments.
401+
402+
By default, git-spice uses `` to indicate the current change.
403+
This can be customized to any string.
404+
405+
**Example:**
406+
407+
```bash
408+
git config spice.submit.navigationCommentStyle.marker "<-- you are here"
409+
```
410+
411+
This will render navigation comments like:
412+
413+
```
414+
- #123
415+
- #124 <-- you are here
416+
- #125
417+
```
418+
396419
### spice.submit.publish
397420

398421
<!-- gs:version v0.5.0 -->

internal/forge/stacknav/nav.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ const (
1515
_indent = " "
1616
)
1717

18+
// PrintOptions customizes the behavior of Print.
19+
type PrintOptions struct {
20+
// Marker is the marker to use for the current change.
21+
// If empty, defaults to "◀".
22+
Marker string
23+
}
24+
1825
// Node is a single item in the stack navigation list.
1926
// It usually represents a change in the Forge.
2027
type Node interface {
@@ -44,8 +51,15 @@ type Node interface {
4451
// currentIdx is the index of the current node in the nodes list.
4552
// It will be marked with [Printer.Marker].
4653
//
54+
// opts can be used to customize the behavior of Print.
55+
// If opts is nil, default options are used.
56+
//
4757
// All Write errors are ignored. Use a Writer that doesn't fail.
48-
func Print[N Node](w io.Writer, nodes []N, currentIdx int) {
58+
func Print[N Node](w io.Writer, nodes []N, currentIdx int, opts *PrintOptions) {
59+
marker := _marker
60+
if opts != nil && opts.Marker != "" {
61+
marker = opts.Marker
62+
}
4963
// aboves[i] holds indexes of nodes that are above nodes[i].
5064
aboves := make([][]int, len(nodes))
5165
for idx, node := range nodes {
@@ -63,7 +77,7 @@ func Print[N Node](w io.Writer, nodes []N, currentIdx int) {
6377

6478
_, _ = fmt.Fprintf(w, "- %v", node.Value())
6579
if nodeIdx == currentIdx {
66-
_, _ = fmt.Fprintf(w, " %v", _marker)
80+
_, _ = fmt.Fprintf(w, " %v", marker)
6781
}
6882

6983
_, _ = io.WriteString(w, "\n")

internal/forge/stacknav/nav_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestPrinter(t *testing.T) {
9393
for _, tt := range tests {
9494
t.Run(tt.name, func(t *testing.T) {
9595
var got strings.Builder
96-
Print(&got, tt.graph, tt.current)
96+
Print(&got, tt.graph, tt.current, nil)
9797
assert.Equal(t, tt.want, got.String())
9898
})
9999
}

internal/handler/submit/handler.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ type Options struct {
133133
Publish bool `name:"publish" negatable:"" default:"true" config:"submit.publish" help:"Whether to create CRs for pushed branches. Defaults to true."`
134134
Web OpenWeb `short:"w" config:"submit.web" help:"Open submitted changes in a web browser. Accepts an optional argument: 'true', 'false', 'created'."`
135135

136-
NavComment NavCommentWhen `name:"nav-comment" config:"submit.navigationComment" enum:"true,false,multiple" default:"true" help:"Whether to add a navigation comment to the change request. Must be one of: true, false, multiple."`
137-
NavCommentSync NavCommentSync `name:"nav-comment-sync" config:"submit.navigationCommentSync" enum:"branch,downstack" default:"branch" hidden:"" help:"Which navigation comment to sync. Must be one of: branch, downstack."`
136+
NavComment NavCommentWhen `name:"nav-comment" config:"submit.navigationComment" enum:"true,false,multiple" default:"true" help:"Whether to add a navigation comment to the change request. Must be one of: true, false, multiple."`
137+
NavCommentSync NavCommentSync `name:"nav-comment-sync" config:"submit.navigationCommentSync" enum:"branch,downstack" default:"branch" hidden:"" help:"Which navigation comment to sync. Must be one of: branch, downstack."`
138+
NavCommentMarker string `name:"nav-comment-marker" config:"submit.navigationCommentStyle.marker" hidden:"" help:"Marker to use for the current change in navigation comments. Defaults to '◀'."`
138139

139140
Force bool `help:"Force push, bypassing safety checks"`
140141
NoVerify bool `help:"Bypass pre-push hooks when pushing to the remote." released:"v0.15.0"`
@@ -268,6 +269,7 @@ func (h *Handler) SubmitBatch(ctx context.Context, req *BatchRequest) error {
268269
h.Store, h.Service, h.Log,
269270
opts.NavComment,
270271
opts.NavCommentSync,
272+
opts.NavCommentMarker,
271273
branchesToComment,
272274
h.RemoteRepository,
273275
)
@@ -312,6 +314,7 @@ func (h *Handler) Submit(ctx context.Context, req *Request) error {
312314
h.Store, h.Service, h.Log,
313315
opts.NavComment,
314316
opts.NavCommentSync,
317+
opts.NavCommentMarker,
315318
[]string{req.Branch},
316319
h.RemoteRepository,
317320
)

internal/handler/submit/nav_comment.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func updateNavigationComments(
8888
log *silog.Logger,
8989
navComment NavCommentWhen,
9090
navCommentSync NavCommentSync,
91+
navCommentMarker string,
9192
submittedBranches []string,
9293
getRemoteRepo func(context.Context) (forge.Repository, error),
9394
) error {
@@ -339,7 +340,7 @@ func updateNavigationComments(
339340
}
340341

341342
info := infos[idx]
342-
commentBody := generateStackNavigationComment(nodes, idx)
343+
commentBody := generateStackNavigationComment(nodes, idx, navCommentMarker)
343344
if info.Meta.NavigationCommentID() == nil {
344345
postc <- &postComment{
345346
Branch: info.Branch,
@@ -404,12 +405,17 @@ var _navCommentRegexes = []*regexp.Regexp{
404405
func generateStackNavigationComment(
405406
nodes []*stackedChange,
406407
current int,
408+
marker string,
407409
) string {
408410
var sb strings.Builder
409411
sb.WriteString(_commentHeader)
410412
sb.WriteString("\n\n")
411413

412-
stacknav.Print(&sb, nodes, current)
414+
var opts *stacknav.PrintOptions
415+
if marker != "" {
416+
opts = &stacknav.PrintOptions{Marker: marker}
417+
}
418+
stacknav.Print(&sb, nodes, current, opts)
413419

414420
sb.WriteString("\n")
415421
sb.WriteString(_commentFooter)

internal/handler/submit/nav_comment_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ func TestUpdateNavigationComments(t *testing.T) {
417417
log,
418418
tt.when,
419419
tt.sync,
420+
"",
420421
tt.submit,
421422
func(context.Context) (forge.Repository, error) {
422423
return mockRemoteRepo, nil
@@ -547,7 +548,7 @@ func TestGenerateStackNavigationComment(t *testing.T) {
547548
tt.want + "\n" +
548549
_commentFooter + "\n" +
549550
_commentMarker + "\n"
550-
got := generateStackNavigationComment(tt.graph, tt.current)
551+
got := generateStackNavigationComment(tt.graph, tt.current, "")
551552
assert.Equal(t, want, got)
552553

553554
// Sanity check: All generated comments must match
@@ -559,6 +560,24 @@ func TestGenerateStackNavigationComment(t *testing.T) {
559560
})
560561
})
561562
}
563+
564+
t.Run("CustomMarker", func(t *testing.T) {
565+
graph := []*stackedChange{
566+
{Change: _changeID("123"), Base: -1},
567+
{Change: _changeID("124"), Base: 0},
568+
}
569+
graph[0].Aboves = []int{1}
570+
571+
got := generateStackNavigationComment(graph, 1, "<-- you are here")
572+
want := _commentHeader + "\n\n" +
573+
joinLines(
574+
"- #123",
575+
" - #124 <-- you are here",
576+
) + "\n" +
577+
_commentFooter + "\n" +
578+
_commentMarker + "\n"
579+
assert.Equal(t, want, got)
580+
})
562581
}
563582

564583
func TestNavigationCommentWhen_StringMarshal(t *testing.T) {

0 commit comments

Comments
 (0)