Skip to content

Commit e56b170

Browse files
committed
Support trimming and padding modifiers
1 parent 6920514 commit e56b170

File tree

3 files changed

+67
-42
lines changed

3 files changed

+67
-42
lines changed

stringlib.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ func strGsubStr(L *LState, str string, repl string, matches []*pm.MatchData) str
222222
infoList := make([]replaceInfo, 0, len(matches))
223223
for _, match := range matches {
224224
start, end := match.Capture(0), match.Capture(1)
225-
sc := newFlagScanner('%', "", "", repl)
225+
sc := newFlagScanner('%', "", "", "", repl)
226226
for c, eos := sc.Next(); !eos; c, eos = sc.Next() {
227227
if !sc.ChangeFlag {
228228
if sc.HasFlag {

utils.go

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,22 @@ func defaultFormat(v interface{}, f fmt.State, c rune) {
4848
}
4949

5050
type flagScanner struct {
51-
flag byte
52-
start string
53-
end string
54-
buf []byte
55-
str string
56-
Length int
57-
Pos int
58-
HasFlag bool
59-
ChangeFlag bool
51+
flag byte
52+
modifiers []byte
53+
start string
54+
end string
55+
buf []byte
56+
str string
57+
Length int
58+
Pos int
59+
HasFlag bool
60+
ChangeFlag bool
61+
HasModifier bool
62+
Modifier byte
6063
}
6164

62-
func newFlagScanner(flag byte, start, end, str string) *flagScanner {
63-
return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false}
65+
func newFlagScanner(flag byte, modifiers, start, end, str string) *flagScanner {
66+
return &flagScanner{flag, []byte(modifiers), start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false, false, 0}
6467
}
6568

6669
func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) }
@@ -85,54 +88,65 @@ func (fs *flagScanner) Next() (byte, bool) {
8588
fs.AppendChar(fs.flag)
8689
fs.Pos += 2
8790
return fs.Next()
88-
} else if fs.Pos != fs.Length-1 {
91+
} else if fs.Pos < fs.Length-1 {
8992
if fs.HasFlag {
9093
fs.AppendString(fs.end)
9194
}
9295
fs.AppendString(fs.start)
9396
fs.ChangeFlag = true
9497
fs.HasFlag = true
98+
fs.HasModifier = false
99+
fs.Modifier = 0
100+
if fs.Pos < fs.Length-2 {
101+
for _, modifier := range fs.modifiers {
102+
if fs.str[fs.Pos+1] == modifier {
103+
fs.HasModifier = true
104+
fs.Modifier = modifier
105+
fs.Pos += 1
106+
}
107+
}
108+
}
95109
}
96110
}
97111
}
98112
fs.Pos++
99113
return c, false
100114
}
101115

102-
var cDateFlagToGo = map[byte]string{
116+
var cDateFlagToGo = map[string]string{
103117
// Formatting
104-
'n': "\n",
105-
't': "\t",
118+
"n": "\n",
119+
"t": "\t",
106120

107121
// Year
108-
'Y': "2006", 'y': "06",
122+
"Y": "2006", "y": "06",
109123

110124
// Month
111-
'b': "Jan", 'B': "January", // TODO: %^B, %^b
112-
'm': "01", // TODO: %-m, %_m
125+
"b": "Jan", "B": "January",
126+
"m": "01", "-m": "1",
113127

114128
// Day of the year/month
115-
'j': "002",
116-
'd': "02", 'e': "_2", // TODO: %-d
129+
"j": "002",
130+
"d": "02", "-d": "2", "e": "_2",
117131

118132
// Day of the week
119-
'a': "Mon", 'A': "Monday", // TODO: %^A, %^a
133+
"a": "Mon", "A": "Monday",
120134

121135
// Hour, minute, second
122-
'H': "15",
123-
'I': "03", 'l': "3",
124-
'M': "04",
125-
'S': "05",
136+
"H": "15",
137+
"I": "03", "l": "3",
138+
"M": "04",
139+
"S": "05",
126140

127141
// Other
128-
'c': "02 Jan 06 15:04 MST",
129-
'x': "01/02/06", 'X': "15:04:05",
130-
'D': "01/02/06",
131-
'F': "2006-01-02",
132-
'r': "03:04:05 PM", 'R': "15:04",
133-
'T': "15:04:05",
134-
'p': "PM", 'P': "pm",
135-
'z': "-0700", 'Z': "MST",
142+
"c": "02 Jan 06 15:04 MST",
143+
"x": "01/02/06", "X": "15:04:05",
144+
"D": "01/02/06",
145+
"F": "2006-01-02",
146+
"r": "03:04:05 PM", "R": "15:04",
147+
"T": "15:04:05",
148+
"p": "PM", "P": "pm",
149+
"z": "-0700", "Z": "MST",
136150

137151
// Many other flags are handled in the body of strftime since they cannot
138152
// be represented in Go format strings.
@@ -142,11 +156,16 @@ var cDateFlagToGo = map[byte]string{
142156
// extensions. This allows for flags like %-d, which provides the day of the
143157
// month without padding (1..31 instead of 01..31).
144158
func strftime(t time.Time, cfmt string) string {
145-
sc := newFlagScanner('%', "", "", cfmt)
159+
sc := newFlagScanner('%', "_-", "", "", cfmt)
146160
for c, eos := sc.Next(); !eos; c, eos = sc.Next() {
147161
if !sc.ChangeFlag {
148162
if sc.HasFlag {
149-
if v, ok := cDateFlagToGo[c]; ok {
163+
flag := string(c)
164+
if sc.HasModifier {
165+
flag = string(sc.Modifier) + flag
166+
}
167+
168+
if v, ok := cDateFlagToGo[flag]; ok {
150169
sc.AppendString(t.Format(v))
151170
} else {
152171
switch c {
@@ -163,6 +182,9 @@ func strftime(t time.Time, cfmt string) string {
163182
sc.AppendString(fmt.Sprint(int(t.Weekday())))
164183
default:
165184
sc.AppendChar('%')
185+
if sc.HasModifier {
186+
sc.AppendChar(sc.Modifier)
187+
}
166188
sc.AppendChar(c)
167189
}
168190
}

utils_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ func TestStrftime(t *testing.T) {
2121

2222
{t1, "%Y %y", "2016 16"},
2323
{t1, "%G %g", "2016 16"},
24-
{t1, "%b %B %m", "Feb February 02"},
24+
{t1, "%b %B", "Feb February"},
25+
{t1, "%m %-m", "02 2"},
2526
{t1, "%V", "5"},
2627
{t1, "%w", "3"},
2728
{t1, "%j", "034"},
28-
{t1, "%d", "03"},
29-
{t1, "%e", " 3"},
29+
{t1, "%d %-d %e", "03 3 3"},
3030
{t1, "%a %A", "Wed Wednesday"},
3131
{t1, "%H %I %l", "13 01 1"},
3232
{t1, "%M", "23"},
@@ -41,12 +41,12 @@ func TestStrftime(t *testing.T) {
4141

4242
{t2, "%Y %y", "1945 45"},
4343
{t2, "%G %g", "1945 45"},
44-
{t2, "%b %B %m", "Sep September 09"},
44+
{t2, "%b %B", "Sep September"},
45+
{t2, "%m %-m", "09 9"},
4546
{t2, "%V", "36"},
4647
{t2, "%w", "4"},
4748
{t2, "%j", "249"},
48-
{t2, "%d", "06"},
49-
{t2, "%e", " 6"},
49+
{t2, "%d %-d %e", "06 6 6"},
5050
{t2, "%a %A", "Thu Thursday"},
5151
{t2, "%H %I %l", "07 07 7"},
5252
{t2, "%M", "35"},
@@ -58,6 +58,9 @@ func TestStrftime(t *testing.T) {
5858
{t2, "%R %T %X", "07:35 07:35:04 07:35:04"},
5959
{t2, "%p %P", "AM am"},
6060
{t2, "%z %Z", "-0500 Minus5"},
61+
62+
{t1, "not real flags: %-Q %_J %^^ %-", "not real flags: %-Q %_J %^^ %-"},
63+
{t1, "end in flag: %", "end in flag: %"},
6164
}
6265
for i, c := range cases {
6366
t.Run(fmt.Sprintf("Case %d (\"%s\")", i, c.Fmt), func(t *testing.T) {

0 commit comments

Comments
 (0)