Skip to content

Commit 459c5a8

Browse files
authored
Add number-lines processor (#65)
* Add numberlines processor numberlines prepends non-empty lines with consecutive numbers * Update README.md with number-lines * Remove full name from a list of aliases * Simplify creation of string from slice * Remove unnecessary error variable, use ++ instead of +=1 * Re-generate processor * Fix alias test for number-lines * Pad line numbers with spaces, right-aligned
1 parent c5a4c0b commit 459c5a8

File tree

5 files changed

+232
-0
lines changed

5 files changed

+232
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ echo "Hello World" | sttr base64-encode | sttr md5
237237
- [x] **shuffle-lines** - Shuffle lines randomly
238238
- [x] **sort-lines** - Sort lines alphabetically
239239
- [x] **unique-lines** - Get unique lines from list
240+
- [x] **number-lines** - Prepend consecutive number to each line
240241
241242
#### Spaces
242243

cmd/processor_number-lines.go

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

processors/numberlines.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package processors
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
)
8+
9+
// / Prepends consecutive number to each line of input
10+
type LineNumberer struct{}
11+
12+
func (p LineNumberer) Name() string {
13+
return "number-lines"
14+
}
15+
16+
func (p LineNumberer) Alias() []string {
17+
return []string{"nl"}
18+
}
19+
20+
func nonEmptyCount(strs []string) int {
21+
var count = 0
22+
for _, s := range strs {
23+
if s != "" {
24+
count++
25+
}
26+
}
27+
return count
28+
}
29+
func (p LineNumberer) Transform(data []byte, _ ...Flag) (string, error) {
30+
var s = string(data)
31+
var counter = 1
32+
var result = ""
33+
var lines = strings.Split(s, "\n")
34+
var nec = nonEmptyCount(lines)
35+
var maxDigits = len(strconv.Itoa(nec))
36+
for _, line := range lines {
37+
if line != "" {
38+
line = fmt.Sprintf("%*d. %s", maxDigits, counter, line)
39+
counter++
40+
}
41+
result += line + "\n"
42+
43+
}
44+
result = strings.TrimSuffix(result, "\n")
45+
return result, nil
46+
}
47+
48+
func (p LineNumberer) Flags() []Flag {
49+
return nil
50+
}
51+
52+
func (p LineNumberer) Title() string {
53+
return "Line numberer"
54+
}
55+
56+
func (p LineNumberer) Description() string {
57+
return "Prepends consecutive number to each input line"
58+
}
59+
60+
func (p LineNumberer) FilterValue() string {
61+
return p.Title()
62+
}

processors/numberlines_test.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package processors
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func TestLineNumberer_Command(t *testing.T) {
9+
test := struct {
10+
alias []string
11+
description string
12+
filterValue string
13+
flags []Flag
14+
name string
15+
title string
16+
}{
17+
alias: []string{"nl"},
18+
description: "Prepends consecutive number to each input line",
19+
filterValue: "Line numberer",
20+
flags: nil,
21+
name: "number-lines",
22+
title: "Line numberer",
23+
}
24+
p := LineNumberer{}
25+
if got := p.Alias(); !reflect.DeepEqual(got, test.alias) {
26+
t.Errorf("Alias() = %v, want %v", got, test.alias)
27+
}
28+
if got := p.Description(); got != test.description {
29+
t.Errorf("Description() = %v, want %v", got, test.description)
30+
}
31+
if got := p.FilterValue(); got != test.filterValue {
32+
t.Errorf("FilterValue() = %v, want %v", got, test.filterValue)
33+
}
34+
if got := p.Flags(); !reflect.DeepEqual(got, test.flags) {
35+
t.Errorf("Flags() = %v, want %v", got, test.flags)
36+
}
37+
if got := p.Name(); got != test.name {
38+
t.Errorf("Name() = %v, want %v", got, test.name)
39+
}
40+
if got := p.Title(); got != test.title {
41+
t.Errorf("Title() = %v, want %v", got, test.title)
42+
}
43+
}
44+
45+
func TestLineNumberer_Transform(t *testing.T) {
46+
type args struct {
47+
data []byte
48+
in1 []Flag
49+
}
50+
tests := []struct {
51+
name string
52+
args args
53+
want string
54+
wantErr bool
55+
}{
56+
{
57+
name: "Test empty string",
58+
args: args{data: []byte("")},
59+
want: "",
60+
},
61+
{
62+
name: "String",
63+
args: args{data: []byte("this is string")},
64+
want: "1. this is string",
65+
}, {
66+
name: "Emoji",
67+
args: args{data: []byte("😃😇🙃🙂😉😌😙😗🇮🇳")},
68+
want: "1. 😃😇🙃🙂😉😌😙😗🇮🇳",
69+
}, {
70+
name: "Multi line string",
71+
args: args{data: []byte("Hello\nfoo\nbar\nfoo\nf00\n%*&^*&^&\n***")},
72+
want: "1. Hello\n2. foo\n3. bar\n4. foo\n5. f00\n6. %*&^*&^&\n7. ***",
73+
}, {
74+
name: "Multi line string ending with \\n",
75+
args: args{data: []byte("Hello\nfoo\nbar\n")},
76+
want: "1. Hello\n2. foo\n3. bar\n",
77+
}, {
78+
name: "Multi line string with padding",
79+
args: args{data: []byte("Hello\nfoo\nbar\nfoo\nf00\n%*&^*&^&\n***\neight\nnine\nten")},
80+
want: " 1. Hello\n 2. foo\n 3. bar\n 4. foo\n 5. f00\n 6. %*&^*&^&\n 7. ***\n 8. eight\n 9. nine\n10. ten",
81+
}, {
82+
name: "Test multi lingual character",
83+
args: args{data: []byte("नमस्ते")},
84+
want: "1. नमस्ते",
85+
},
86+
{
87+
name: "Lines with empty lines between",
88+
args: args{data: []byte("this is string\n\nfollowed by empty line and another")},
89+
want: "1. this is string\n\n2. followed by empty line and another",
90+
},
91+
{
92+
name: "Lines with first empty line",
93+
args: args{data: []byte("\nthis is string after newline\n\nfollowed by empty line and another")},
94+
want: "\n1. this is string after newline\n\n2. followed by empty line and another",
95+
},
96+
{
97+
name: "Lines with space-only lines between",
98+
args: args{data: []byte("this is string\n \nfollowed by three-space line and another")},
99+
want: "1. this is string\n2. \n3. followed by three-space line and another",
100+
},
101+
}
102+
for _, tt := range tests {
103+
t.Run(tt.name, func(t *testing.T) {
104+
p := LineNumberer{}
105+
got, err := p.Transform(tt.args.data, tt.args.in1...)
106+
if (err != nil) != tt.wantErr {
107+
t.Errorf("Transform() error = %v, wantErr %v", err, tt.wantErr)
108+
return
109+
}
110+
if got != tt.want {
111+
t.Errorf("Transform() got = %v, want %v", got, tt.want)
112+
}
113+
})
114+
}
115+
}

processors/processor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var List = []list.Item{
4343
MorseCodeDecode{},
4444
MD5{},
4545
MSGPACKToJSON{},
46+
LineNumberer{},
4647
Pascal{},
4748
RemoveNewLines{},
4849
RemoveSpaces{},

0 commit comments

Comments
 (0)