Skip to content

Commit dc0429e

Browse files
Merge pull request #45 from yehonatanz/feature/autonumber
Support `autonumber` directive in sequence diagrams
2 parents 0ccc8d6 + 4f7cf0e commit dc0429e

5 files changed

Lines changed: 88 additions & 7 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sequenceDiagram
2+
autonumber
3+
Alice->>Bob: Hello
4+
Bob->>Bob: Think
5+
Bob-->>Alice: Hi
6+
Alice->>Bob: Bye
7+
---
8+
+-------+ +-----+
9+
| Alice | | Bob |
10+
+---+---+ +--+--+
11+
| |
12+
| 1. Hello |
13+
+----------->|
14+
| |
15+
| | 2. Think
16+
| +--+
17+
| | |
18+
| |<-+
19+
| |
20+
| 3. Hi |
21+
|<...........+
22+
| |
23+
| 4. Bye |
24+
+----------->|
25+
| |
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sequenceDiagram
2+
autonumber
3+
Alice->>Bob: Hello
4+
Bob->>Bob: Think
5+
Bob-->>Alice: Hi
6+
Alice->>Bob: Bye
7+
---
8+
┌───────┐ ┌─────┐
9+
│ Alice │ │ Bob │
10+
└───┬───┘ └──┬──┘
11+
│ │
12+
│ 1. Hello │
13+
├───────────►│
14+
│ │
15+
│ │ 2. Think
16+
│ ├──┐
17+
│ │ │
18+
│ │◄─┘
19+
│ │
20+
│ 3. Hi │
21+
│◄┈┈┈┈┈┈┈┈┈┈┈┤
22+
│ │
23+
│ 4. Bye │
24+
├───────────►│
25+
│ │

internal/sequence/parser.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ var (
2020

2121
// messageRegex matches messages: [From]->>[To]: [Label]
2222
messageRegex = regexp.MustCompile(`^\s*(?:"([^"]+)"|([^\s\->]+))\s*(-->>|->>)\s*(?:"([^"]+)"|([^\s\->]+))\s*:\s*(.*)$`)
23+
24+
// autonumberRegex matches the autonumber directive
25+
autonumberRegex = regexp.MustCompile(`^\s*autonumber\s*$`)
2326
)
2427

2528
// SequenceDiagram represents a parsed sequence diagram.
2629
type SequenceDiagram struct {
2730
Participants []*Participant
2831
Messages []*Message
32+
Autonumber bool
2933
}
3034

3135
type Participant struct {
@@ -39,6 +43,7 @@ type Message struct {
3943
To *Participant
4044
Label string
4145
ArrowType ArrowType
46+
Number int // Message number when autonumber is enabled (0 means no number)
4247
}
4348

4449
type ArrowType int
@@ -91,6 +96,7 @@ func Parse(input string) (*SequenceDiagram, error) {
9196
sd := &SequenceDiagram{
9297
Participants: []*Participant{},
9398
Messages: []*Message{},
99+
Autonumber: false,
94100
}
95101
participantMap := make(map[string]*Participant)
96102

@@ -100,6 +106,12 @@ func Parse(input string) (*SequenceDiagram, error) {
100106
continue
101107
}
102108

109+
// Check for autonumber directive
110+
if autonumberRegex.MatchString(trimmed) {
111+
sd.Autonumber = true
112+
continue
113+
}
114+
103115
if matched, err := sd.parseParticipant(trimmed, participantMap); err != nil {
104116
return nil, fmt.Errorf("line %d: %w", i+2, err)
105117
} else if matched {
@@ -180,11 +192,17 @@ func (sd *SequenceDiagram) parseMessage(line string, participants map[string]*Pa
180192
aType = SolidArrow
181193
}
182194

195+
msgNumber := 0
196+
if sd.Autonumber {
197+
msgNumber = len(sd.Messages) + 1
198+
}
199+
183200
msg := &Message{
184201
From: from,
185202
To: to,
186203
Label: label,
187204
ArrowType: aType,
205+
Number: msgNumber,
188206
}
189207
sd.Messages = append(sd.Messages, msg)
190208
return true, nil

internal/sequence/renderer.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,14 @@ func renderMessage(msg *Message, layout *diagramLayout, chars BoxChars) []string
160160
var lines []string
161161
from, to := layout.participantCenters[msg.From.Index], layout.participantCenters[msg.To.Index]
162162

163-
if msg.Label != "" {
163+
label := msg.Label
164+
if msg.Number > 0 {
165+
label = fmt.Sprintf("%d. %s", msg.Number, msg.Label)
166+
}
167+
168+
if label != "" {
164169
start := min(from, to) + labelLeftMargin
165-
labelWidth := runewidth.StringWidth(msg.Label)
170+
labelWidth := runewidth.StringWidth(label)
166171
w := max(layout.totalWidth, start+labelWidth) + labelBufferSpace
167172
line := []rune(buildLifeline(layout, chars))
168173
if len(line) < w {
@@ -174,7 +179,7 @@ func renderMessage(msg *Message, layout *diagramLayout, chars BoxChars) []string
174179
}
175180

176181
col := start
177-
for _, r := range msg.Label {
182+
for _, r := range label {
178183
if col < len(line) {
179184
line[col] = r
180185
col++
@@ -226,10 +231,15 @@ func renderSelfMessage(msg *Message, layout *diagramLayout, chars BoxChars) []st
226231
return r
227232
}
228233

229-
if msg.Label != "" {
234+
label := msg.Label
235+
if msg.Number > 0 {
236+
label = fmt.Sprintf("%d. %s", msg.Number, msg.Label)
237+
}
238+
239+
if label != "" {
230240
line := ensureWidth(buildLifeline(layout, chars))
231241
start := center + labelLeftMargin
232-
labelWidth := runewidth.StringWidth(msg.Label)
242+
labelWidth := runewidth.StringWidth(label)
233243
needed := start + labelWidth + labelBufferSpace
234244
if len(line) < needed {
235245
pad := make([]rune, needed-len(line))
@@ -239,7 +249,7 @@ func renderSelfMessage(msg *Message, layout *diagramLayout, chars BoxChars) []st
239249
line = append(line, pad...)
240250
}
241251
col := start
242-
for _, c := range msg.Label {
252+
for _, c := range label {
243253
if col < len(line) {
244254
line[col] = c
245255
col++

internal/sequence/renderer_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func TestSequenceDiagramRendering(t *testing.T) {
2525
// Test files - stored in sequence/ directory (Unicode expected output)
2626
testFiles := []string{
2727
"adjacent_participants_communication.txt",
28+
"autonumber.txt",
2829
"bidirectional_messages.txt",
2930
"dotted_arrows_only.txt",
3031
"four_participants.txt",
@@ -50,9 +51,10 @@ func TestSequenceDiagramRendering_ASCII(t *testing.T) {
5051
testDataPath := filepath.Join(getTestDataPath(), "sequence-ascii")
5152

5253
goldenFiles := []string{
53-
"simple_two_participants.txt",
54+
"autonumber.txt",
5455
"dotted_arrows_only.txt",
5556
"self_message.txt",
57+
"simple_two_participants.txt",
5658
"three_participants.txt",
5759
}
5860

@@ -70,6 +72,7 @@ func TestSequenceDiagramRendering_ASCIISmokeTest(t *testing.T) {
7072

7173
testFiles := []string{
7274
"adjacent_participants_communication.txt",
75+
"autonumber.txt",
7376
"bidirectional_messages.txt",
7477
"dotted_arrows_only.txt",
7578
"four_participants.txt",

0 commit comments

Comments
 (0)