Merge pull request #1 from anthonyaxenov/develop

New version
pull/2/head v1.1.0
Anthony Axenov 2022-02-17 13:13:48 +08:00 committed by GitHub
commit c7fd26e7b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 177 additions and 60 deletions

1
.gitignore vendored
View File

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

28
.vscode/launch.json vendored
View File

@ -2,19 +2,17 @@
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileBasename}",
"args": [
"example.csv",
]
}
]
}
"version": "0.2.0",
"configurations": [
{
"name": "Debug csv2md",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "main.go"
// "args": [
// "example.csv",
// ]
}
]
}

View File

@ -4,20 +4,35 @@ Stupidly simple tool to convert csv-file to [markdown](https://spec-md.com/) tab
Outputs result in stdout.
Building:
## Usage
```shell
make help
```
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
Usage:
```shell
csv2md example.csv > example.md # makes new file
csv2md example.csv | less # view result using *pager*
...anything is possible with redirection and piping
```
> **IMPORTANT:** input must be valid csv and whitespaces are allowed only between double-quotes.
> **IMPORTANT:**
> * input must be valid csv
> * whitespaces allowed only between double-quotes
Examples can be found here: https://people.sc.fsu.edu/~jburkardt/data/csv/csv.html
## 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.
## License
[MIT](LICENSE)

View File

@ -1,14 +1,50 @@
"Month","1958","1959","1960"
"JAN",340,360,417
"FEB",318,342,391
"MAR",362,406,419
"APR",348,396,461
"MAY",363,420,472
"JUN",435,472,535
"JUL",491,548,622
"AUG",505,559,606
"SEP",404,463,508
"OCT",359,407,461
"NOV",310,362,390
"DEC",337,405,432
"Name","Team","Position","Height(inches)","Weight(lbs)","Age"
"Adam Donachie","BAL","Catcher",74,180,22.99
"Paul Bako","BAL","Catcher",74,215,34.69
"Ramon Hernandez","BAL","Catcher",72,210,30.78
"Kevin Millar","BAL","First Baseman",72,210,35.43
"Chris Gomez","BAL","First Baseman",73,188,35.71
"Brian Roberts","BAL","Second Baseman",69,176,29.39
"Miguel Tejada","BAL","Shortstop",69,209,30.77
"Melvin Mora","BAL","Third Baseman",71,200,35.07
"Aubrey Huff","BAL","Third Baseman",76,231,30.19
"Adam Stern","BAL","Outfielder",71,180,27.05
"Jeff Fiorentino","BAL","Outfielder",73,188,23.88
"Freddie Bynum","BAL","Outfielder",73,180,26.96
"Nick Markakis","BAL","Outfielder",74,185,23.29
"Brandon Fahey","BAL","Outfielder",74,160,26.11
"Corey Patterson","BAL","Outfielder",69,180,27.55
"Jay Payton","BAL","Outfielder",70,185,34.27
"Jay Gibbons","BAL","Designated Hitter",72,197,30
"Erik Bedard","BAL","Starting Pitcher",73,189,27.99
"Hayden Penn","BAL","Starting Pitcher",75,185,22.38
"Adam Loewen","BAL","Starting Pitcher",78,219,22.89
"Daniel Cabrera","BAL","Starting Pitcher",79,230,25.76
"Steve Trachsel","BAL","Starting Pitcher",76,205,36.33
"Jaret Wright","BAL","Starting Pitcher",74,230,31.17
"Kris Benson","BAL","Starting Pitcher",76,195,32.31
"Scott Williamson","BAL","Relief Pitcher",72,180,31.03
"John Parrish","BAL","Relief Pitcher",71,192,29.26
"Danys Baez","BAL","Relief Pitcher",75,225,29.47
"Chad Bradford","BAL","Relief Pitcher",77,203,32.46
"Jamie Walker","BAL","Relief Pitcher",74,195,35.67
"Brian Burres","BAL","Relief Pitcher",73,182,25.89
"Kurt Birkins","BAL","Relief Pitcher",74,188,26.55
"James Hoey","BAL","Relief Pitcher",78,200,24.17
"Sendy Rleal","BAL","Relief Pitcher",73,180,26.69
"Chris Ray","BAL","Relief Pitcher",75,200,25.13
"Jeremy Guthrie","BAL","Relief Pitcher",73,200,27.9
"A.J. Pierzynski","CWS","Catcher",75,245,30.17
"Toby Hall","CWS","Catcher",75,240,31.36
"Paul Konerko","CWS","First Baseman",74,215,30.99
"Tadahito Iguchi","CWS","Second Baseman",69,185,32.24
"Juan Uribe","CWS","Shortstop",71,175,27.61
"Alex Cintron","CWS","Shortstop",74,199,28.2
"Joe Crede","CWS","Third Baseman",73,200,28.85
"Josh Fields","CWS","Third Baseman",73,215,24.21
"Ryan Sweeney","CWS","Outfielder",76,200,22.02
"Brian N. Anderson","CWS","Outfielder",74,205,24.97
"Luis Terrero","CWS","Outfielder",74,206,26.78
"Pablo Ozuna","CWS","Outfielder",70,186,32.51
"Scott Podsednik","CWS","Outfielder",72,188,30.95
"Jermaine Dye","CWS","Outfielder",77,220,33.09

1 Month Name 1958 Team 1959 Position 1960 Height(inches) Weight(lbs) Age
2 JAN Adam Donachie 340 BAL 360 Catcher 417 74 180 22.99
3 FEB Paul Bako 318 BAL 342 Catcher 391 74 215 34.69
4 MAR Ramon Hernandez 362 BAL 406 Catcher 419 72 210 30.78
5 APR Kevin Millar 348 BAL 396 First Baseman 461 72 210 35.43
6 MAY Chris Gomez 363 BAL 420 First Baseman 472 73 188 35.71
7 JUN Brian Roberts 435 BAL 472 Second Baseman 535 69 176 29.39
8 JUL Miguel Tejada 491 BAL 548 Shortstop 622 69 209 30.77
9 AUG Melvin Mora 505 BAL 559 Third Baseman 606 71 200 35.07
10 SEP Aubrey Huff 404 BAL 463 Third Baseman 508 76 231 30.19
11 OCT Adam Stern 359 BAL 407 Outfielder 461 71 180 27.05
12 NOV Jeff Fiorentino 310 BAL 362 Outfielder 390 73 188 23.88
13 DEC Freddie Bynum 337 BAL 405 Outfielder 432 73 180 26.96
14 Nick Markakis BAL Outfielder 74 185 23.29
15 Brandon Fahey BAL Outfielder 74 160 26.11
16 Corey Patterson BAL Outfielder 69 180 27.55
17 Jay Payton BAL Outfielder 70 185 34.27
18 Jay Gibbons BAL Designated Hitter 72 197 30
19 Erik Bedard BAL Starting Pitcher 73 189 27.99
20 Hayden Penn BAL Starting Pitcher 75 185 22.38
21 Adam Loewen BAL Starting Pitcher 78 219 22.89
22 Daniel Cabrera BAL Starting Pitcher 79 230 25.76
23 Steve Trachsel BAL Starting Pitcher 76 205 36.33
24 Jaret Wright BAL Starting Pitcher 74 230 31.17
25 Kris Benson BAL Starting Pitcher 76 195 32.31
26 Scott Williamson BAL Relief Pitcher 72 180 31.03
27 John Parrish BAL Relief Pitcher 71 192 29.26
28 Danys Baez BAL Relief Pitcher 75 225 29.47
29 Chad Bradford BAL Relief Pitcher 77 203 32.46
30 Jamie Walker BAL Relief Pitcher 74 195 35.67
31 Brian Burres BAL Relief Pitcher 73 182 25.89
32 Kurt Birkins BAL Relief Pitcher 74 188 26.55
33 James Hoey BAL Relief Pitcher 78 200 24.17
34 Sendy Rleal BAL Relief Pitcher 73 180 26.69
35 Chris Ray BAL Relief Pitcher 75 200 25.13
36 Jeremy Guthrie BAL Relief Pitcher 73 200 27.9
37 A.J. Pierzynski CWS Catcher 75 245 30.17
38 Toby Hall CWS Catcher 75 240 31.36
39 Paul Konerko CWS First Baseman 74 215 30.99
40 Tadahito Iguchi CWS Second Baseman 69 185 32.24
41 Juan Uribe CWS Shortstop 71 175 27.61
42 Alex Cintron CWS Shortstop 74 199 28.2
43 Joe Crede CWS Third Baseman 73 200 28.85
44 Josh Fields CWS Third Baseman 73 215 24.21
45 Ryan Sweeney CWS Outfielder 76 200 22.02
46 Brian N. Anderson CWS Outfielder 74 205 24.97
47 Luis Terrero CWS Outfielder 74 206 26.78
48 Pablo Ozuna CWS Outfielder 70 186 32.51
49 Scott Podsednik CWS Outfielder 72 188 30.95
50 Jermaine Dye CWS Outfielder 77 220 33.09

111
main.go
View File

@ -2,6 +2,8 @@ package main
import (
"encoding/csv"
"errors"
"flag"
"fmt"
"log"
"os"
@ -9,33 +11,62 @@ import (
"strings"
)
const VERSION = "1.0.0"
const VERSION = "1.1.0"
func main() {
if len(os.Args) < 2 {
usage()
os.Exit(1)
}
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)
src, err := ExpandPath(os.Args[1])
if err != nil {
panic(err)
}
if _, err := os.Stat(src); err != nil {
panic(err)
}
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")
flag.Parse()
if os.Args[1] == "help" || *help1 || *help2 {
usage(os.Stdout)
os.Exit(0)
}
result := convert(readCsv(src))
// ...or to convert data from file
src, err := ExpandPath(os.Args[1])
if err != nil {
log.Fatal(err)
}
if _, err := os.Stat(src); err != nil {
log.Fatal(err)
}
data, err := readCsvFile(src)
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)
}
}
// print write converted data to stdout
func print(data [][]string) {
if len(data) == 0 {
usage(os.Stderr)
}
result := convert(data)
for _, row := range result {
fmt.Println(row)
}
}
func usage() {
fmt.Fprintln(os.Stderr, "csv2md v" + VERSION)
fmt.Fprintln(os.Stderr, "Usage: csv2md data.csv > data.md")
}
// ExpandPath return absolute path to file replacing ~ to user's home folder
func ExpandPath(path string) (string, error) {
homepath, err := os.UserHomeDir()
if err != nil {
@ -45,22 +76,34 @@ func ExpandPath(path string) (string, error) {
return newpath, err
}
func readCsv(filePath string) [][]string {
// readRawCsv read data from file
func readCsvFile(filePath string) ([][]string, error) {
f, err := os.Open(filePath)
if err != nil {
log.Fatal("Unable to read input file " + filePath, err)
return nil, errors.New("Failed to open file '" + filePath + "': " + err.Error())
}
defer f.Close()
csvReader := csv.NewReader(f)
records, err := csvReader.ReadAll()
if err != nil {
log.Fatal("Unable to parse file as CSV for " + filePath, err)
return nil, errors.New("Failed to parse CSV from file '" + filePath + "': " + err.Error())
}
return records
return records, nil
}
// readRawCsv read data from stdin
func readRawCsv() ([][]string, error) {
csvReader := csv.NewReader(os.Stdin)
records, err := csvReader.ReadAll()
if err != nil {
return nil, errors.New("Failed to parse CSV from stdin: " + err.Error())
}
return records, nil
}
// convert format data from file or stdin as markdown
func convert(records [][]string) []string {
var result []string
for idx, row := range records {
@ -79,3 +122,27 @@ func convert(records [][]string) []string {
}
return result
}
// usage print help into writer
func usage(writer *os.File) {
usage := []string{
"csv2md v" + VERSION,
"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",
}
for _, str := range usage {
fmt.Fprintln(writer, str)
}
}