Skip to content

Commit

Permalink
go: Add printf and houdini padding syntax support (refs #14)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinfx committed Dec 1, 2020
1 parent c00a704 commit cc672ff
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 22 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ Support for:
* Staggered: 1-100:3 (1-100x3, 1-100x2, 1-100)
* Negative frame numbers: -10-100
* Padding: #=4 padded, @=single pad

* Printf Syntax Padding: %04d=4 padded, %01d=1 padded
* Houdini Syntax Padding: $F4=4 padding, $F=1 padded

Sequence Formats
----------------

Expand All @@ -35,6 +37,8 @@ Sequences of files are expected to follow a pattern similar to:
* /path/to/some/file_foo.0100.exr
* /path/to/some/file_foo.1-100#.jpg
* /path/to/some/file_foo.1-100@@@.tif
* /path/to/some/file_foo.1-100%03d.tif
* /path/to/some/file_foo.1-100$F3.tif

Install
-------
Expand Down
28 changes: 23 additions & 5 deletions fileseq.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Support for:
Staggered: 1-100:3 (1-100x3, 1-100x2, 1-100)
Negative frame numbers: -10-100
Padding: #=4 padded, @=single pad
Printf Syntax Padding: %04d=4 padded, %01d=1 padded
Houdini Syntax Padding: $F4=4 padding, $F=1 padded
*/
package fileseq
Expand All @@ -29,9 +31,11 @@ import (
const Version = "2.7.1"

var (
rangePatterns []*regexp.Regexp
splitPattern *regexp.Regexp
singleFrame *regexp.Regexp
rangePatterns []*regexp.Regexp
splitPattern *regexp.Regexp
singleFrame *regexp.Regexp
printfPattern *regexp.Regexp
houdiniPattern *regexp.Regexp
)

func init() {
Expand All @@ -53,10 +57,16 @@ func init() {
// Example:
// /film/shot/renders/hero_bty.1-100#.exr
// /film/shot/renders/hero_bty.@@.exr
// /film/shot/renders/hero_bty.1-100%04d.exr
// /film/shot/renders/hero_bty.1-100$F04.exr
splitPattern = regexp.MustCompile(
`^(?P<name>.*?)` +
`(?P<range>[\d-][:xy\d,-]*)?` +
`(?P<pad>[#@]+)` +
`(?P<pad>` +
`[#@]+` + // standard pad chars
`|%\d*d` + // or printf padding
`|\$F\d*` + // or houdini padding
`)` + // end <pad>
// multiple extension parts:
`(?P<ext>\.(?:\w*[a-zA-Z]\w*)*(?:\.[a-zA-Z0-9]+)?)$`)

Expand All @@ -66,6 +76,14 @@ func init() {
`(?P<frame>-?\d+)` +
// multiple extension parts:
`(?P<ext>(?:\.\w*[a-zA-Z]\w*)*(?:\.[a-zA-Z0-9]+)?)$`)

// Regular expression pattern for matching padding against a
// printf syntax padding string E.g. %04d
printfPattern = regexp.MustCompile(`^%(\d*)d$`)

// Regular expression pattern for matching padding against
// houdini syntax. E.g. $F04
houdiniPattern = regexp.MustCompile(`^\$F(\d*)$`)
}

// IsFrameRange returns true if the given string is a valid frame
Expand Down Expand Up @@ -244,7 +262,7 @@ func parseInt(s string) (int, error) {
if err != nil {
return 0, parseIntErr
}
return int(val), nil
return val, nil
}

// Return whether a string component from a frame
Expand Down
67 changes: 63 additions & 4 deletions fileseq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ func TestFrameSetSplitPattern(t *testing.T) {
{"/path/to/file%s_1-100x10@@.tar.gz", "file%s_", 1, 91, "@@"},
{"/path/to/file%s.-10--1x2##.tar.gz", "file%s.", -10, -2, "##"},
{"/path/to/file%s1,2,3,5-10,20-30#.tar.gz", "file%s", 1, 30, "#"},

{"/path/to/file%s_1-100x10%%02d.exr", "file%s_", 1, 91, "%02d"},
{"/path/to/file%s_1-100x10$F2.exr", "file%s_", 1, 91, "$F2"},
{"/path/to/file%s_1-100x10$F02.exr", "file%s_", 1, 91, "$F02"},
}

// ref: splitPattern range directive chars
Expand Down Expand Up @@ -318,6 +322,12 @@ func TestNewFileSequence(t *testing.T) {
{".10000000000.123",
".10000000000@@@@@@@@@@@.123", 10000000000, 10000000000, 11,
1, ".123"},
{"/dir/f.1-100%04d.jpeg",
"/dir/f.1-100%04d.jpeg", 1, 100, 4,
100, ".jpeg"},
{"/dir/f.1-100$F04.jpeg",
"/dir/f.1-100$F04.jpeg", 1, 100, 4,
100, ".jpeg"},
}
for _, tt := range table {
seq, err := NewFileSequence(tt.path)
Expand Down Expand Up @@ -354,6 +364,8 @@ func TestFileSequenceSplit(t *testing.T) {
{"/file_path.100.exr", []string{"100"}},
{"/file_path.-005.exr", []string{"-005"}},
{"/dir/f.-1-100#.jpeg", []string{"-1-100"}},
{"/dir/f.-1-100%04d.jpeg", []string{"-1-100"}},
{"/dir/f.-1-100$F04.jpeg", []string{"-1-100"}},
{"/dir/f.1-10,50,60-90x2##.exr", []string{"1-10", "50", "60-90x2"}},
{"/dir/f.1-10,50,60-90x2##.tar.gz", []string{"1-10", "50", "60-90x2"}},
{"/dir/f.exr", []string{""}},
Expand Down Expand Up @@ -438,6 +450,24 @@ func TestFileSequenceSetDir(t *testing.T) {
newPad: "@@@",
expected: "/other/subdir/fileB-10-5,20-30x2@@@.f",
},
{
src: "/path/to/file.1-100#.exr",
newDir: "/other/subdir",
newBase: "fileB",
newExt: "f",
newFrange: "-10-5,20-30x2",
newPad: "%03d",
expected: "/other/subdir/fileB-10-5,20-30x2%03d.f",
},
{
src: "/path/to/file.1-100#.exr",
newDir: "/other/subdir",
newBase: "fileB",
newExt: "f",
newFrange: "-10-5,20-30x2",
newPad: "$F03",
expected: "/other/subdir/fileB-10-5,20-30x2$F03.f",
},
}

for _, tt := range table {
Expand Down Expand Up @@ -569,14 +599,37 @@ func TestPaddingCharsSize(t *testing.T) {
}{
{
padders[PadStyleHash1], []TestVals{
{"", 0}, {"#", 1}, {"##", 2}, {"###", 3}, {"####", 4},
{"@", 1}, {"@@", 2}, {"@@@", 3}, {"@@@@", 4},
{"", 0},
{"#", 1},
{"##", 2},
{"###", 3},
{"####", 4},
{"@", 1},
{"@@", 2},
{"@@@", 3},
{"@@@@", 4},
{"%02d", 2},
{"%04d", 4},
{"$F", 1},
{"$F2", 2},
{"$F04", 4},
},
},
{
padders[PadStyleHash4], []TestVals{
{"", 0}, {"#", 4}, {"##", 8}, {"###", 12}, {"####", 16},
{"@", 1}, {"@@", 2}, {"@@@", 3}, {"@@@@", 4},
{"", 0},
{"#", 4},
{"##", 8},
{"###", 12},
{"####", 16},
{"@", 1},
{"@@", 2},
{"@@@", 3},
{"@@@@", 4},
{"%02d", 2},
{"%04d", 4},
{"$F2", 2},
{"$F04", 4},
},
},
}
Expand Down Expand Up @@ -714,6 +767,9 @@ func TestFindSequenceOnDisk(t *testing.T) {
"testdata/seqA.@@@@.exr": "testdata/seqA.1,3-6,8-10####.exr",
"testdata/seqA.@.jpg": "",

"testdata/seqC.%02d.tif": "testdata/seqC.-5-2,4-10,20-21,27-30##.tif",
"testdata/seqC.$F02.tif": "testdata/seqC.-5-2,4-10,20-21,27-30##.tif",

"testdata/mixed/seq.####.ext": "testdata/mixed/seq.-1-5####.ext",
"testdata/mixed/seq.#.ext": "",
"testdata/mixed/seq.@@.ext": "testdata/mixed/seq.-1-5##.ext",
Expand All @@ -735,6 +791,9 @@ func TestFindSequenceOnDisk(t *testing.T) {
"testdata/seqA.@.exr": "",
"testdata/seqA.@.jpg": "",

"testdata/seqC.%02d.tif": "testdata/seqC.-5-2,4-10,20-21,27-30@@.tif",
"testdata/seqC.$F02.tif": "testdata/seqC.-5-2,4-10,20-21,27-30@@.tif",

"testdata/mixed/seq.#.ext": "testdata/mixed/seq.-1-5#.ext",
"testdata/mixed/seq.@@.ext": "testdata/mixed/seq.-1-5@@.ext",
"testdata/mixed/seq.@@@@@.ext": "testdata/mixed/seq.-1-5,1001@@@@@.ext",
Expand Down
5 changes: 1 addition & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
module github.com/justinfx/gofileseq/v2

require (
github.com/jessevdk/go-flags v1.4.0
golang.org/x/tools v0.0.0-20191011211836-4c025a95b26e
)
require github.com/jessevdk/go-flags v1.4.0

go 1.13
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,2 @@
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191011211836-4c025a95b26e h1:1o2bDs9pCd2xFhdwqJTrCIswAeEsn4h/PCNelWpfcsI=
golang.org/x/tools v0.0.0-20191011211836-4c025a95b26e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
19 changes: 19 additions & 0 deletions pad.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fileseq

import (
"fmt"
"regexp"
"strconv"
"strings"
)
Expand Down Expand Up @@ -109,6 +110,24 @@ func (m *paddingMap) AllChars() []string {
}

func (m *paddingMap) PaddingCharsSize(chars string) int {
if len(chars) == 0 {
return 0
}

// check for alternate padding syntax
var match []string
for _, rx := range []*regexp.Regexp{printfPattern, houdiniPattern} {
if match = rx.FindStringSubmatch(chars); len(match) == 0 {
continue
}
intVal, err := strconv.Atoi(match[1])
if err != nil || intVal < 1 {
return 1
}
return intVal
}

// standard pad chars
var size int
for _, char := range chars {
size += m.charToSize[string(char)]
Expand Down

0 comments on commit cc672ff

Please sign in to comment.