{"id":18840222,"url":"https://github.com/maxim2266/strit","last_synced_at":"2025-07-09T14:36:29.202Z","repository":{"id":144202318,"uuid":"85506828","full_name":"maxim2266/strit","owner":"maxim2266","description":"Package strit introduces a new type of string iterator, along with a number of iterator constructors, wrappers and combinators.","archived":false,"fork":false,"pushed_at":"2021-07-22T21:41:09.000Z","size":35,"stargazers_count":84,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-14T07:06:44.314Z","etag":null,"topics":["fluent-interface","function-composition","golang","iteration","pipeline-framework","string-processing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxim2266.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-19T20:35:26.000Z","updated_at":"2024-07-07T08:16:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"f826e8c2-b8f9-43ed-a664-0fd3ea8c21f7","html_url":"https://github.com/maxim2266/strit","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fstrit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fstrit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fstrit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxim2266%2Fstrit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxim2266","download_url":"https://codeload.github.com/maxim2266/strit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248837278,"owners_count":21169374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fluent-interface","function-composition","golang","iteration","pipeline-framework","string-processing"],"created_at":"2024-11-08T02:46:54.339Z","updated_at":"2025-04-14T07:07:04.545Z","avatar_url":"https://github.com/maxim2266.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# strit\n\n[![GoDoc](https://godoc.org/github.com/maxim2266/strit?status.svg)](https://pkg.go.dev/github.com/maxim2266/strit)\n[![Go Report Card](https://goreportcard.com/badge/github.com/maxim2266/strit)](https://goreportcard.com/report/github.com/maxim2266/strit)\n[![License: BSD 3 Clause](https://img.shields.io/badge/License-BSD_3--Clause-yellow.svg)](https://opensource.org/licenses/BSD-3-Clause)\n\nPackage `strit` (STRing ITerator) assists in development of string processing pipelines by providing a simple\niteration model that allows for easy composition of processing stages.\n\n### Motivation\nSuppose we want to develop a function that reads a file line by line, removes leading and trailing\nwhitespace from each line, selects only non-empty lines that also do not start with the `#` symbol, and\nstores those lines in a slice of strings. Using the Go standard library one possible implementation\nof the function may look like this:\n```Go\nfunc ReadConfig(fileName string) ([]string, error) {\n\tfile, err := os.Open(fileName)\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer file.Close()\n\n\tvar res []string\n\tsrc := bufio.NewScanner(file)\n\n\tfor src.Scan() {\n\t\tline := bytes.TrimSpace(src.Bytes())\n\n\t\tif len(line) \u003e 0 \u0026\u0026 line[0] != '#' {\n\t\t\tres = append(res, string(line))\n\t\t}\n\t}\n\n\tif err = src.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn res, nil\n}\n```\nUsing `strit` package the implementation can be simplified down to:\n```Go\nfunc ReadConfig(fileName string) ([]string, error) {\n\treturn strit.FromFile(fileName).\n           Map(bytes.TrimSpace).\n           Filter(strit.Not(strit.Empty).AndNot(strit.StartsWith(\"#\"))).\n           Strings()\n```\n### Features\n* A number of iterator constructors for reading text from a variety of sources:\n  * `io.Reader`:\n  \t[`FromReader`](https://godoc.org/github.com/maxim2266/strit#FromReader)\n  \t[`FromReaderSF`](https://godoc.org/github.com/maxim2266/strit#FromReaderSF)\n  * `io.ReadCloser`:\n  \t[`FromReadCloser`](https://godoc.org/github.com/maxim2266/strit#FromReadCloser)\n  \t[`FromReadCloserSF`](https://godoc.org/github.com/maxim2266/strit#FromReadCloserSF)\n  * `[]byte`:\n  \t[`FromBytes`](https://godoc.org/github.com/maxim2266/strit#FromBytes)\n  \t[`FromBytesSF`](https://godoc.org/github.com/maxim2266/strit#FromBytesSF)\n  * `string`:\n  \t[`FromString`](https://godoc.org/github.com/maxim2266/strit#FromString)\n  \t[`FromStringSF`](https://godoc.org/github.com/maxim2266/strit#FromStringSF)\n  * `[]string`:\n  \t[`FromStrings`](https://godoc.org/github.com/maxim2266/strit#FromStrings)\n  * Disk file:\n  \t[`FromFile`](https://godoc.org/github.com/maxim2266/strit#FromFile)\n  \t[`FromFileSF`](https://godoc.org/github.com/maxim2266/strit#FromFileSF)\n  * Directory listing:\n  \t[`FromDir`](https://godoc.org/github.com/maxim2266/strit#FromDir)\n  * Recursive directory listing:\n  \t[`FromDirWalk`](https://godoc.org/github.com/maxim2266/strit#FromDirWalk)\n  * External command output:\n  \t[`FromCommand`](https://godoc.org/github.com/maxim2266/strit#FromCommand)\n  \t[`FromCommandSF`](https://godoc.org/github.com/maxim2266/strit#FromCommandSF)\n* Mapping and filtering primitives:\n\t[`Filter`](https://godoc.org/github.com/maxim2266/strit#Iter.Filter)\n\t[`GenMap`](https://godoc.org/github.com/maxim2266/strit#Iter.GenMap)\n\t[`Map`](https://godoc.org/github.com/maxim2266/strit#Iter.Map)\n* Sequence limiting functions:\n\t[`Skip`](https://godoc.org/github.com/maxim2266/strit#Iter.Skip)\n\t[`SkipWhile`](https://godoc.org/github.com/maxim2266/strit#Iter.SkipWhile)\n\t[`Take`](https://godoc.org/github.com/maxim2266/strit#Iter.Take)\n\t[`TakeWhile`](https://godoc.org/github.com/maxim2266/strit#Iter.TakeWhile)\n* Search function:\n\t[`FirstNonEmpty`](https://godoc.org/github.com/maxim2266/strit#Iter.FirstNonEmpty)\n* Piping iterator output through an external command:\n\t[`Pipe`](https://godoc.org/github.com/maxim2266/strit#Iter.Pipe)\n\t[`PipeSF`](https://godoc.org/github.com/maxim2266/strit#Iter.PipeSF)\n* Iterator chaining (sequential combination):\n\t[`Chain`](https://godoc.org/github.com/maxim2266/strit#Chain)\n* Iterator merging (parallel combination):\n\t[`Merge`](https://godoc.org/github.com/maxim2266/strit#Merge)\n* Output collectors that invoke the given iterator and write the result to various destinations:\n  * `string`:\n  \t[`String`](https://godoc.org/github.com/maxim2266/strit#Iter.String)\n  \t[`Join`](https://godoc.org/github.com/maxim2266/strit#Iter.Join)\n  * `[]string`:\n  \t[`Strings`](https://godoc.org/github.com/maxim2266/strit#Iter.Strings)\n  * `[]byte`:\n  \t[`Bytes`](https://godoc.org/github.com/maxim2266/strit#Iter.Bytes)\n  \t[`JoinBytes`](https://godoc.org/github.com/maxim2266/strit#Iter.JoinBytes)\n  * `io.Writer`:\n  \t[`WriteTo`](https://godoc.org/github.com/maxim2266/strit#Iter.WriteTo)\n  \t[`WriteSepTo`](https://godoc.org/github.com/maxim2266/strit#Iter.WriteSepTo)\n  * Disk file:\n  \t[`WriteToFile`](https://godoc.org/github.com/maxim2266/strit#Iter.WriteToFile)\n  \t[`WriteSepToFile`](https://godoc.org/github.com/maxim2266/strit#Iter.WriteSepToFile)\n* Predicates and predicate combinators for use with `Filter`:\n\t[`Empty`](https://godoc.org/github.com/maxim2266/strit#Empty)\n\t[`StartsWith`](https://godoc.org/github.com/maxim2266/strit#StartsWith)\n\t[`EndsWith`](https://godoc.org/github.com/maxim2266/strit#EndsWith)\n\t[`Not`](https://godoc.org/github.com/maxim2266/strit#Not)\n\t[`And`](https://godoc.org/github.com/maxim2266/strit#Pred.And)\n\t[`AndNot`](https://godoc.org/github.com/maxim2266/strit#Pred.AndNot)\n\t[`Or`](https://godoc.org/github.com/maxim2266/strit#Pred.Or)\n\t[`OrNot`](https://godoc.org/github.com/maxim2266/strit#Pred.OrNot)\n* Basic parsing supported via [`Parse`](https://godoc.org/github.com/maxim2266/strit#Iter.Parse) function.\n\n### More examples:\n* Naïve `grep`:\n```Go\nfunc main() {\n\t_, err := strit.FromReader(os.Stdin).\n\t\t\tFilter(regexp.MustCompile(os.Args[1]).Match).\n\t\t\tWriteSepTo(os.Stdout, \"\\n\")\n\n\tif err != nil {\n\t\tos.Stderr.WriteString(err.Error() + \"\\n\")\n\t\tos.Exit(1)\n\t}\n}\n```\n* Recursively find all the filesystem entries matching the given regular expression:\n```Go\nfunc selectEntries(root string, re *regexp.Regexp) ([]string, error) {\n\treturn FromDirWalk(root, nil).Filter(re.Match).Strings()\n}\n```\n* Build a list of `.flac` files in the given directory, annotating each name with its corresponding\ntrack number from FLAC metadata:\n```Go\nfunc namesWithTrackNumbers(dir string) ([]string, error) {\n\treturn strit.FromDir(dir, func(info os.FileInfo) bool { return info.Mode().IsRegular() }).\n\t\tFilter(strit.EndsWith(\".flac\")).\n\t\tGenMap(prependTrackNo).\n\t\tStrings()\n}\n\nfunc prependTrackNo(file []byte) ([]byte, error) {\n\tname := string(file)\n\n\tno, err := strit.FromCommand(exec.Command(\"metaflac\", \"--list\", \"--block-type=VORBIS_COMMENT\", name)).\n\t\tFirstNonEmpty(func(s []byte) []byte {\n\t\t\tif m := match(s); len(m) == 2 {\n\t\t\t\treturn m[1]\n\t\t\t}\n\n\t\t\treturn nil\n\t\t}).\n\t\tString()\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(no) == 0 {\n\t\treturn []byte(\"???: \" + filepath.Base(name)), nil\n\t}\n\n\treturn []byte(no + \": \" + filepath.Base(name)), nil\n}\n\nvar match = regexp.MustCompile(`tracknumber=([[:digit:]]+)$`).FindSubmatch\n```\n\n### Project status\nThe project is in a beta state. Tested on Linux Mint 19.1, with Go version 1.12.\nShould also work on other platforms supported by Go runtime, but currently this is not very well tested.\n\n##### License: BSD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxim2266%2Fstrit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxim2266%2Fstrit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxim2266%2Fstrit/lists"}