mirror of
https://github.com/anthonyaxenov/csv2md.git
synced 2024-10-31 17:15:34 +00:00
New version
- stdin support - refactored error handling - help and some comments in src
This commit is contained in:
parent
bcb0a39d82
commit
f1aa5d3eff
99
main.go
99
main.go
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -9,33 +11,62 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "1.0.0"
|
const VERSION = "1.1.0"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
log.SetFlags(0)
|
||||||
usage()
|
switch len(os.Args) {
|
||||||
os.Exit(1)
|
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")
|
||||||
|
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])
|
src, err := ExpandPath(os.Args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(src); err != nil {
|
if _, err := os.Stat(src); err != nil {
|
||||||
panic(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := convert(readCsv(src))
|
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 {
|
for _, row := range result {
|
||||||
fmt.Println(row)
|
fmt.Println(row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func usage() {
|
// ExpandPath return absolute path to file replacing ~ to user's home folder
|
||||||
fmt.Fprintln(os.Stderr, "csv2md v" + VERSION)
|
|
||||||
fmt.Fprintln(os.Stderr, "Usage: csv2md data.csv > data.md")
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExpandPath(path string) (string, error) {
|
func ExpandPath(path string) (string, error) {
|
||||||
homepath, err := os.UserHomeDir()
|
homepath, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -45,22 +76,34 @@ func ExpandPath(path string) (string, error) {
|
|||||||
return newpath, err
|
return newpath, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func readCsv(filePath string) [][]string {
|
// readRawCsv read data from file
|
||||||
|
func readCsvFile(filePath string) ([][]string, error) {
|
||||||
f, err := os.Open(filePath)
|
f, err := os.Open(filePath)
|
||||||
if err != nil {
|
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()
|
defer f.Close()
|
||||||
|
|
||||||
csvReader := csv.NewReader(f)
|
csvReader := csv.NewReader(f)
|
||||||
records, err := csvReader.ReadAll()
|
records, err := csvReader.ReadAll()
|
||||||
if err != nil {
|
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 {
|
func convert(records [][]string) []string {
|
||||||
var result []string
|
var result []string
|
||||||
for idx, row := range records {
|
for idx, row := range records {
|
||||||
@ -79,3 +122,27 @@ func convert(records [][]string) []string {
|
|||||||
}
|
}
|
||||||
return result
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user