-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create processing/text package (#44)
- Loading branch information
1 parent
85ef473
commit f672d23
Showing
4 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package text | ||
|
||
import ( | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
type Processor interface { | ||
Once() bool | ||
Process(string) (string, error) | ||
} | ||
|
||
var ( | ||
_ Processor = processor{} | ||
_ Processor = RemoveByRegexp{} | ||
_ Processor = Cut{} | ||
_ Processor = Trim{} | ||
) | ||
|
||
type processor struct { | ||
once bool | ||
fn func(string) (string, error) | ||
} | ||
|
||
func NewProcessor(once bool, fn func(string) (string, error)) Processor { | ||
return processor{once, fn} | ||
} | ||
|
||
func WrapFunc(fn func(string) string) func(string) (string, error) { | ||
return func(s string) (string, error) { return fn(s), nil } | ||
} | ||
|
||
func (p processor) Once() bool { return p.once } | ||
func (p processor) Process(s string) (string, error) { | ||
return p.fn(s) | ||
} | ||
|
||
type RemoveByRegexp struct { | ||
*regexp.Regexp | ||
} | ||
|
||
func (RemoveByRegexp) Once() bool { return false } | ||
func (p RemoveByRegexp) Process(s string) (string, error) { | ||
return p.ReplaceAllString(s, ""), nil | ||
} | ||
|
||
type Cut struct { | ||
Sep string | ||
} | ||
|
||
func (Cut) Once() bool { return true } | ||
func (p Cut) Process(s string) (string, error) { | ||
before, _, _ := strings.Cut(s, p.Sep) | ||
return before, nil | ||
} | ||
|
||
type Trim struct { | ||
Cutset string | ||
} | ||
|
||
func (Trim) Once() bool { return false } | ||
func (p Trim) Process(s string) (string, error) { | ||
return strings.Trim(s, p.Cutset), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package text | ||
|
||
import ( | ||
"regexp" | ||
"testing" | ||
) | ||
|
||
func TestRemoveByRegexp(t *testing.T) { | ||
for i, testcase := range []struct { | ||
re *regexp.Regexp | ||
s string | ||
expected string | ||
}{ | ||
{regexp.MustCompile(""), "", ""}, | ||
{regexp.MustCompile(`\d+`), "abc123", "abc"}, | ||
{regexp.MustCompile(`\d+$`), "123abc456", "123abc"}, | ||
} { | ||
if res, err := NewTasks().Append(RemoveByRegexp{testcase.re}).Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestCut(t *testing.T) { | ||
for i, testcase := range []struct { | ||
seq string | ||
s string | ||
expected string | ||
}{ | ||
{"", "", ""}, | ||
{" ", "abc 123", "abc"}, | ||
{" ", " abc 123", ""}, | ||
{"abc", "123abc456", "123"}, | ||
} { | ||
if res, err := NewTasks().Append(Cut{testcase.seq}).Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestTrim(t *testing.T) { | ||
for i, testcase := range []struct { | ||
cutset string | ||
s string | ||
expected string | ||
}{ | ||
{"", "", ""}, | ||
{" ", " abc 123 ", "abc 123"}, | ||
{" ", " abc 123\n", "abc 123\n"}, | ||
{" \n", " abc 123\n", "abc 123"}, | ||
} { | ||
if res, err := NewTasks().Append(Trim{testcase.cutset}).Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package text | ||
|
||
import ( | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
type Tasks struct { | ||
tasks []Processor | ||
} | ||
|
||
func NewTasks(tasks ...Processor) *Tasks { | ||
return &Tasks{tasks} | ||
} | ||
|
||
func (t *Tasks) Process(s string) (string, error) { | ||
var err error | ||
for first, output := true, s; ; { | ||
for _, task := range t.tasks { | ||
if first || !task.Once() { | ||
s, err = task.Process(s) | ||
if err != nil { | ||
return "", err | ||
} | ||
} | ||
} | ||
if s == output { | ||
return output, nil | ||
} else { | ||
output = s | ||
} | ||
if first { | ||
first = false | ||
} | ||
} | ||
} | ||
|
||
func (t *Tasks) ProcessAll(s []string) ([]string, error) { | ||
var output []string | ||
for _, i := range s { | ||
s, err := t.Process(i) | ||
if err != nil { | ||
return nil, err | ||
} | ||
output = append(output, s) | ||
} | ||
return output, nil | ||
} | ||
|
||
func (t *Tasks) Append(tasks ...Processor) *Tasks { | ||
t.tasks = append(t.tasks, tasks...) | ||
return t | ||
} | ||
|
||
func (t *Tasks) TrimSpace() *Tasks { | ||
return t.Append(NewProcessor(false, WrapFunc(strings.TrimSpace))) | ||
} | ||
|
||
func (t *Tasks) CutSpace() *Tasks { | ||
return t.Append(NewProcessor(true, func(s string) (string, error) { | ||
if fs := strings.Fields(s); len(fs) > 0 { | ||
return fs[0], nil | ||
} | ||
return "", nil | ||
})) | ||
} | ||
|
||
func (t *Tasks) RemoveParentheses() *Tasks { | ||
return t.Append( | ||
RemoveByRegexp{regexp.MustCompile(`\([^)]*\)`)}, | ||
RemoveByRegexp{regexp.MustCompile(`([^)]*)`)}, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package text | ||
|
||
import "testing" | ||
|
||
func TestTrimSpace(t *testing.T) { | ||
task := NewTasks().TrimSpace() | ||
for i, testcase := range []struct { | ||
s string | ||
expected string | ||
}{ | ||
{"", ""}, | ||
{" abc", "abc"}, | ||
{"abc\n", "abc"}, | ||
{"a b c", "a b c"}, | ||
} { | ||
if res, err := task.Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestCutSpace(t *testing.T) { | ||
task := NewTasks().CutSpace() | ||
for i, testcase := range []struct { | ||
s string | ||
expected string | ||
}{ | ||
{"", ""}, | ||
{" abc", "abc"}, | ||
{"abc def", "abc"}, | ||
{"abc\ndef", "abc"}, | ||
} { | ||
if res, err := task.Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestRemoveParentheses(t *testing.T) { | ||
task := NewTasks().RemoveParentheses() | ||
for i, testcase := range []struct { | ||
s string | ||
expected string | ||
}{ | ||
{"", ""}, | ||
{"abc", "abc"}, | ||
{"abc(123)", "abc"}, | ||
{"abc(123)", "abc"}, | ||
{"abc(123)", "abc(123)"}, | ||
{"abc(123)def", "abcdef"}, | ||
} { | ||
if res, err := task.Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestTasks(t *testing.T) { | ||
task := NewTasks().TrimSpace().RemoveParentheses().CutSpace() | ||
for i, testcase := range []struct { | ||
s string | ||
expected string | ||
}{ | ||
{"", ""}, | ||
{" abc(123)\n", "abc"}, | ||
{"abc (123)", "abc"}, | ||
{"(123)abc", "abc"}, | ||
} { | ||
if res, err := task.Process(testcase.s); err != nil { | ||
t.Error(err) | ||
} else if res != testcase.expected { | ||
t.Errorf("#%d: got %q; want %q", i, res, testcase.expected) | ||
} | ||
} | ||
} |