Adds csv and tsv io as well as quoted string entry

This commit is contained in:
sloum 2021-03-16 22:17:52 -07:00
parent 9e090de845
commit 9520f75399
5 changed files with 163 additions and 10 deletions

13
cell.go
View File

@ -62,14 +62,23 @@ func (c *cell) ToggleMod(mod int) {
}
}
func (c *cell) Edit(row, col int) {
func (c *cell) Edit(row, col int, text bool) {
line, err := GetLine(fmt.Sprintf("\033[2KUpdate %c%d: \033[?25h", col+64, row))
if err != nil {
panic(err)
}
if len(line) == 0 {
return
}
fmt.Print("\033[?25l")
line = strings.TrimSpace(line)
c.Update(line)
if text {
line = fmt.Sprintf("\"%s\"", line)
}
updated := c.Update(line)
if updated {
modified = true
}
}
func (c *cell) Update(val string) bool {

80
csvLoader.go Normal file
View File

@ -0,0 +1,80 @@
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"strconv"
)
func LoadCsv(path string, tab bool) {
f, err := os.Open(path)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to open file %q", path)
os.Exit(1)
}
wb = makeWorkbook(path)
wb.sheets = make([]sheet, 0, 1)
s := makeSheet("")
s.cols = 0
reader := csv.NewReader(f)
if tab {
reader.Comma = '\t'
}
for {
record, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
fmt.Fprintf(os.Stderr, "Err: %s", err.Error())
continue
}
if s.cols == 0 {
s.cols = len(record)
s.cells = make([][]cell, 0, 10)
}
r := make([]cell, len(record))
for i := range record {
_, err := strconv.Atoi(record[i])
if err != nil {
record[i] = fmt.Sprintf("\"%s\"", record[i])
}
r[i].Update(record[i])
}
s.cells = append(s.cells, r)
}
s.rows = len(s.cells)
wb.sheets = append(wb.sheets, s)
}
func WriteCsv(path string, tab bool) {
f, err := os.Create(path)
if err != nil {
// TODO report error
panic(err.Error())
}
defer f.Close()
writer := csv.NewWriter(f)
if tab {
writer.Comma = '\t'
}
for _, row := range wb.sheets[wb.sheet].cells {
r := make([]string, len(row))
for i, cell := range row {
r[i] = cell.mask
}
if err := writer.Write(r); err != nil {
// TODO report error
}
}
writer.Flush()
if err := writer.Error(); err != nil {
// TODO report error
panic(err.Error())
}
}

View File

@ -57,7 +57,6 @@ func writeSheet(f *os.File, sh sheet) {
}
func LoadFile(path string) {
path = ExpandedAbsFilepath(path)
fbytes, err := ioutil.ReadFile(path)
if err != nil {
fmt.Fprint(os.Stderr, "Unable to read file\n")

62
main.go
View File

@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
@ -20,6 +21,7 @@ const (
var wb workbook
var reAddr *regexp.Regexp = regexp.MustCompile(`^[A-Z][0-9]+$`)
var reAddrRange *regexp.Regexp = regexp.MustCompile(`^[A-Z][0-9]+:[A-Z][0-9]+$`)
var modified bool = false
type point struct {
row int
@ -31,15 +33,51 @@ func runCommand(elems []string) {
return
}
switch elems[0] {
case "save":
case "write", "w":
if len(elems) >= 2 {
WriteFile(strings.Join(elems[1:], " "))
path := ExpandedAbsFilepath(strings.Join(elems[1:], " "))
WriteFile(path)
} else {
WriteFile(wb.path)
path := wb.path
ext := filepath.Ext(path)
if ext != ".tss" {
path = path[:len(path)-len(ext)] + ".tss"
}
WriteFile(path)
}
case "trim":
modified = false
case "write-csv", "wc":
if len(elems) >= 2 {
path := ExpandedAbsFilepath(strings.Join(elems[1:], " "))
WriteCsv(path, false)
} else {
path := wb.path
ext := filepath.Ext(path)
if ext != ".csv" {
path = path[:len(path)-len(ext)] + ".csv"
}
WriteCsv(path, false)
}
case "write-tsv", "wt":
if len(elems) >= 2 {
path := ExpandedAbsFilepath(strings.Join(elems[1:], " "))
WriteCsv(path, true)
} else {
path := wb.path
ext := filepath.Ext(path)
if ext != ".tsv" {
path = path[:len(path)-len(ext)] + ".tsv"
}
WriteCsv(path, true)
}
case "trim", "t":
wb.sheets[wb.sheet].TrimSheet()
fmt.Print("\033[2J") // Clear the screen
case "recalculate", "r":
wb.sheets[wb.sheet].Recalculate()
default:
// TODO report error
panic("Invalid command")
}
}
@ -58,10 +96,12 @@ func GetLine(prefix string) (string, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Print(prefix)
fmt.Print("\033[?25h")
text, err := reader.ReadString('\n')
if err != nil {
return "", err
}
fmt.Print("\033[?25l")
return text[:len(text)-1], nil
}
@ -121,7 +161,19 @@ func IsFunc(val string) bool {
func main() {
args := os.Args
if len(args) > 1 {
LoadFile(args[1])
path := ExpandedAbsFilepath(args[1])
ext := strings.ToLower(filepath.Ext(path))
switch ext {
case ".tss":
LoadFile(path)
case ".csv":
LoadCsv(path, false)
case ".tsv":
LoadCsv(path, true)
default:
fmt.Fprintf(os.Stderr, "Unknown file type %q", ext)
os.Exit(1)
}
wb.sheets[wb.sheet].Recalculate()
} else {
wb = makeWorkbook("blank.tss")

View File

@ -16,6 +16,7 @@ const (
Quit rune = 'Q'
Edit rune = '\n'
EditAlt rune = ' '
EditText rune = '"'
Del rune = 'd'
Com rune = ':'
ZoomIn rune = '+'
@ -63,11 +64,23 @@ func (w *workbook) Run() {
case Left, Right, Up, Down, ToTop, RowStart, ToBottom, RowEnd:
w.sheets[w.sheet].moveSelection(input, w.termRows)
case Quit:
if modified {
fmt.Print("There are unsaved changes. Quit? [y/n]")
answer := Getch()
if answer == 'n' || answer == 'N' {
continue
}
fmt.Print("\n")
}
termios.Restore()
fmt.Print("\033[?25h")
os.Exit(0)
case Edit, EditAlt:
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].Edit(w.sheets[w.sheet].selection.row, w.sheets[w.sheet].selection.col)
case Edit, EditAlt, EditText:
quote := false
if input == EditText {
quote = true
}
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].Edit(w.sheets[w.sheet].selection.row, w.sheets[w.sheet].selection.col, quote)
w.sheets[w.sheet].Recalculate()
case Del:
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1] = cell{}