Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New version #1

Merged
merged 6 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/bin
# /.vscode
*.csv
*.md
!example.csv
28 changes: 13 additions & 15 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
// ]
}
]
}
33 changes: 24 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

Usage:
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

```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)
64 changes: 50 additions & 14 deletions example.csv
Original file line number Diff line number Diff line change
@@ -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
109 changes: 88 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,71 @@ package main

import (
"encoding/csv"
"errors"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"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)
}

// ...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)
}
}

result := convert(readCsv(src))
// 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 {
Expand All @@ -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 {
Expand All @@ -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)
}
}