New v1.2.0: tsv support

pull/2/head
Anthony Axenov 2022-02-23 12:25:40 +08:00
parent c7fd26e7b4
commit 13dedbac3b
Signed by: anthony
GPG Key ID: EA9EC32FF7CCD4EC
5 changed files with 124 additions and 73 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
/bin
# /.vscode
*.csv
*.tsv
*.md
!example.csv

19
.vscode/launch.json vendored
View File

@ -9,10 +9,21 @@
"type": "go",
"request": "launch",
"mode": "auto",
"program": "main.go"
// "args": [
// "example.csv",
// ]
"program": "main.go",
"args": [
"-f=example.csv",
]
},
{
"name": "Debug csv2md (tsv)",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "main.go",
"args": [
"-t",
"-f=example.tsv",
]
}
]
}

View File

@ -1,37 +1,63 @@
# csv2md
Stupidly simple tool to convert csv-file to [markdown](https://spec-md.com/) table.
Stupidly simple tool to convert csv/tsv to [markdown](https://spec-md.com/) table.
Outputs result in stdout.
## Usage
```shell
csv2md (-h|-help|--help|help) # to get this help
csv2md example.csv # convert data from file and write result in stdout
csv2md < example.csv # convert data from stdin and write result in stdout
cat example.csv | csv2md # convert data from stdin and write result in stdout
csv2md example.csv > example.md # convert data from file and write result in new file
csv2md example.csv | less # convert data from file and write result in stdout using pager
csv2md # paste or type data to stdin by hands
# press Ctrl+D to view result in stdout
csv2md > example.md # paste or type data to stdin by hands
# press Ctrl+D to write result in new file
...anything is possible with redirection and piping
csv2md [-help|--help] [-t] [-f <FILE>]
```
> **IMPORTANT:**
> * input must be valid csv
> * whitespaces allowed only between double-quotes
Available arguments:
* `-help` or `--help` - get help
* `-f=<FILE>` or `-f <FILE>` - convert specified `FILE`
* `-t` - convert input as tsv
Examples can be found here: https://people.sc.fsu.edu/~jburkardt/data/csv/csv.html
Available `FILE` formats:
* csv (default);
* tsv (with `-t` argument).
Path to `FILE` may be presented as:
* absolute path;
* path relative to current working directory;
* path relative to user home directory (~).
Also if `PATH` contains whitespaces then you should double-quote it.
To save result as separate file you can use piping.
> **IMPORTANT:**
> 1. Input data must be valid csv/tsv
> 2. Whitespaces allowed only between double-quotes
> 3. Due to markdown spec first line of result table will always be presented as header.
> So if your raw data hasn't one you'll should add it before conversion or edit later in ready md.
### Examples
```
csv2md - paste or type csv to stdin and then
press Ctrl+D to view result in stdout
csv2md -t > example.md - paste or type tsv to stdin and then
press Ctrl+D to write result in new file
csv2md -f example.csv - convert csv from file and view result in stdout
csv2md -t < example.tsv - convert tsv from stdin and view result in stdout
csv2md -t < example.tsv > example.md - convert tsv from stdin and write result in new file
cat example.csv | csv2md - convert csv from stdin and view result in stdout
csv2md -t -f=example.tsv > example.md - convert tsv from file and write result in new file
csv2md -f example.csv | less - convert csv from file and view result in stdout using pager
...anything is possible with redirection and piping, e.g. grep, sed, awk, etc.
```
You can generate some examples here: [csv](https://onlinerandomtools.com/generate-random-csv), [tsv](https://onlinerandomtools.com/generate-random-tsv)
## Compilation
1) [Install go](https://go.dev/learn/).
2) Download this repo via zip or `git clone`.
3) Run `make help` to get help or `go run . <csv_path>` to build and run temporary binary.
3) Run `make help` to get help about compilation or `go run . [ARGS...]` to build and run temporary binary.
## License

6
example.tsv 100644
View File

@ -0,0 +1,6 @@
impossible political hand larger upward during
shade tip opinion star keep aside
wrong heat line pool song just
she slowly gain snow ourselves six
race thrown get yard nearest swam
though than teacher away dirt escape
1 impossible political hand larger upward during
2 shade tip opinion star keep aside
3 wrong heat line pool song just
4 she slowly gain snow ourselves six
5 race thrown get yard nearest swam
6 though than teacher away dirt escape

81
main.go
View File

@ -11,30 +11,28 @@ import (
"strings"
)
const VERSION = "1.1.0"
const VERSION = "1.2.0"
func main() {
log.SetFlags(0)
switch len(os.Args) {
case 1: // first we read data from stdin and then convert it
data, err := readRawCsv()
if err != nil {
log.Fatal(err)
}
print(data)
case 2: // but if 2nd arg is present
// probably user wants to get help
help1 := flag.Bool("h", false, "Get help")
help2 := flag.Bool("help", false, "Get help")
filepath := flag.String("f", "", "File path")
is_help := flag.Bool("help", false, "Get help")
as_tsv := flag.Bool("t", false, "Parse as tsv")
flag.Parse()
if os.Args[1] == "help" || *help1 || *help2 {
if *is_help {
usage(os.Stdout)
os.Exit(0)
}
// ...or to convert data from file
src, err := ExpandPath(os.Args[1])
if *filepath == "" {
data, err := readRawCsv(*as_tsv)
if err != nil {
log.Fatal(err)
}
print(data)
} else {
src, err := ExpandPath(*filepath)
if err != nil {
log.Fatal(err)
}
@ -42,16 +40,11 @@ func main() {
log.Fatal(err)
}
data, err := readCsvFile(src)
data, err := readCsvFile(src, *as_tsv)
if err != nil {
log.Fatal(err)
}
print(data)
// otherwise let's show usage help and exit (probably inaccessible code, but anyway)
default:
usage(os.Stdout)
os.Exit(0)
}
}
@ -77,7 +70,7 @@ func ExpandPath(path string) (string, error) {
}
// readRawCsv read data from file
func readCsvFile(filePath string) ([][]string, error) {
func readCsvFile(filePath string, as_tsv bool) ([][]string, error) {
f, err := os.Open(filePath)
if err != nil {
return nil, errors.New("Failed to open file '" + filePath + "': " + err.Error())
@ -85,21 +78,30 @@ func readCsvFile(filePath string) ([][]string, error) {
defer f.Close()
csvReader := csv.NewReader(f)
if as_tsv {
csvReader.Comma = '\t'
}
records, err := csvReader.ReadAll()
if err != nil {
return nil, errors.New("Failed to parse CSV from file '" + filePath + "': " + err.Error())
return nil, errors.New("Failed to parse file '" + filePath + "': " + err.Error())
}
return records, nil
}
// readRawCsv read data from stdin
func readRawCsv() ([][]string, error) {
func readRawCsv(as_tsv bool) ([][]string, error) {
csvReader := csv.NewReader(os.Stdin)
if as_tsv {
csvReader.Comma = '\t'
}
records, err := csvReader.ReadAll()
if err != nil {
return nil, errors.New("Failed to parse CSV from stdin: " + err.Error())
return nil, errors.New("Failed to parse input from stdin: " + err.Error())
}
return records, nil
}
@ -127,20 +129,25 @@ func convert(records [][]string) []string {
func usage(writer *os.File) {
usage := []string{
"csv2md v" + VERSION,
"Anthony Axenov (c) 2022, MIT license",
"Anthony Axenov (c) 2022, MIT License",
"https://github.com/anthonyaxenov/csv2md",
"",
"Usage:",
"\tcsv2md (-h|-help|--help|help) # to get this help",
"\tcsv2md example.csv # convert data from file and write result in stdout",
"\tcsv2md < example.csv # convert data from stdin and write result in stdout",
"\tcat example.csv | csv2md # convert data from stdin and write result in stdout",
"\tcsv2md example.csv > example.md # convert data from file and write result in new file",
"\tcsv2md example.csv | less # convert data from file and write result in stdout using pager",
"\tcsv2md # paste or type data to stdin by hands",
"\t # press Ctrl+D to view result in stdout",
"\tcsv2md > example.md # paste or type data to stdin by hands",
"\t # press Ctrl+D to write result in new file",
"\tcsv2md [-help|--help] [-t] [-f <FILE>]",
"",
"Available arguments:",
"\t-help|--help - get this help",
"\t-f=<FILE>|-f <FILE> - convert specified FILE",
"\t-t - convert input as TSV",
"",
"FILE formats supported:",
"\t- csv (default)",
"\t- tsv (with -t flag)",
"",
"Path to FILE may be presented as:",
"\t- absolute",
"\t- relative to current working directory",
"\t- relative to user home directory (~)",
}
for _, str := range usage {
fmt.Fprintln(writer, str)