package main import ( "fmt" "io/ioutil" "os" "os/user" "path/filepath" "strconv" "strings" ) const ( Sheet rune = 29 Row rune = 30 Field rune = 31 End rune = 3 ModSep rune = 26 ) func WriteFile(path string) { f, err := os.Create(path) if err != nil { panic(err.Error()) } defer f.Close() f.WriteString("tss") for _, s := range wb.sheets { writeSheet(f, s) } f.WriteString(string(End)) } func writeSheet(f *os.File, sh sheet) { var o strings.Builder o.WriteRune(Sheet) // Sheet header data fmt.Fprintf(&o, "%s%c%d%c%d%c%d", sh.name, Field, sh.cols, Field, sh.rows, Field, sh.zoom) for _, row := range sh.cells { o.WriteRune(Row) for c, cell := range row { o.WriteString(cell.rawVal) o.WriteRune(26) modstr := make([]string, len(cell.mods)) for _, modint := range cell.mods { ms := strconv.Itoa(modint) modstr = append(modstr, ms) } o.WriteString(strings.Join(modstr, ",")) if c < len(row) - 1 { o.WriteRune(Field) } } } f.WriteString(o.String()) } func LoadFile(path string) { fbytes, err := ioutil.ReadFile(path) if err != nil { fmt.Fprint(os.Stderr, "Unable to read file\n") os.Exit(1) } f := string(fbytes) if !strings.HasPrefix(f, "tss") || !strings.HasSuffix(f, string(End)) { fmt.Fprint(os.Stderr, "Invalid file type\n") os.Exit(1) } wb = makeWorkbook(path) wb.sheets = make([]sheet, 0, 2) sheets := strings.Split(f[4:len(f)-1], fmt.Sprintf("%c", Sheet)) for _, sh := range sheets { if len(sh) == 0 { continue } rows := strings.Split(sh, fmt.Sprintf("%c", Row)) if len(rows) < 1 { return } s := makeSheet("") sfields := strings.Split(rows[0], fmt.Sprintf("%c", Field)) s.name = sfields[0] s.cols, _ = strconv.Atoi(sfields[1]) s.rows, _ = strconv.Atoi(sfields[2]) s.zoom, _ = strconv.Atoi(sfields[3]) s.cells = make([][]cell, s.rows) for i, row := range rows[1:] { fields := strings.Split(row, fmt.Sprintf("%c", Field)) s.cells[i] = make([]cell, s.cols) for x, field := range fields { rawValModSep := strings.Split(field, fmt.Sprintf("%c", ModSep)) c := cell{} c.Update(rawValModSep[0]) if len(rawValModSep) > 1 { for _, mod := range strings.Split(rawValModSep[1], ",") { modint, err := strconv.Atoi(mod) if err != nil { continue } c.ToggleMod(modint) } } s.cells[i][x] = c } } wb.sheets = append(wb.sheets, s) } } func ExpandedAbsFilepath(p string) string { if strings.HasPrefix(p, "~/") { usr, _ := user.Current() homedir := usr.HomeDir p = filepath.Join(homedir, p[2:]) } path, _ := filepath.Abs(p) return path }