162 lines
4.3 KiB
Go
162 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"tildegit.org/sloum/tally/qline"
|
|
"tildegit.org/sloum/tally/termios"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
Left rune = 'h'
|
|
Right rune = 'l'
|
|
Up rune = 'k'
|
|
Down rune = 'j'
|
|
Quit rune = 'Q'
|
|
Edit rune = '\n'
|
|
EditAlt rune = ' '
|
|
EditText rune = '"'
|
|
Del rune = 'd'
|
|
Com rune = ':'
|
|
ZoomIn rune = '+'
|
|
ZoomOut rune = '-'
|
|
Yank rune = 'y'
|
|
Paste rune = 'p'
|
|
PasteRelative rune = 'P'
|
|
ToTop rune = 'g'
|
|
ToBottom rune = 'G'
|
|
RowStart rune = '^'
|
|
RowEnd rune = '$'
|
|
ModBold rune = 'b'
|
|
ModFaint rune = 'f'
|
|
ModItalic rune = 'i'
|
|
ModUnderline rune = 'u'
|
|
OpenLink rune = 'O'
|
|
)
|
|
|
|
type workbook struct {
|
|
name string
|
|
path string
|
|
sheets []sheet
|
|
sheet int
|
|
termRows int
|
|
termCols int
|
|
}
|
|
|
|
func (w *workbook) PollForTermSize() {
|
|
for {
|
|
var cols, rows = termios.GetWindowSize()
|
|
if rows != w.termRows || cols != w.termCols {
|
|
w.termRows = rows
|
|
w.termCols = cols
|
|
fmt.Print("\033[2J")
|
|
w.Draw()
|
|
}
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func (w workbook) Draw() {
|
|
fmt.Print("\033[0;0H")
|
|
fmt.Printf("FILE: \033[1m%-*.*s\033[0m\n", w.termCols-6, w.termCols-6, w.path)
|
|
fmt.Printf("EXPR: %-*.*s\n",
|
|
w.termCols-6, w.termCols-6,
|
|
w.sheets[w.sheet].CurrentValue(true))
|
|
w.sheets[w.sheet].Draw(w.termCols,w.termRows)
|
|
}
|
|
|
|
func (w *workbook) Run() {
|
|
defer termios.Restore()
|
|
termios.SetCharMode()
|
|
fmt.Print("\033[?25l\033[2J")
|
|
|
|
go w.PollForTermSize()
|
|
|
|
var input rune
|
|
var chErr error
|
|
for {
|
|
w.Draw()
|
|
input, chErr = Getch()
|
|
if chErr != nil {
|
|
continue
|
|
}
|
|
switch input {
|
|
case Left, Right, Up, Down, ToTop, RowStart, ToBottom, RowEnd, qline.LeftArrow, qline.RightArrow, qline.DownArrow, qline.UpArrow, qline.Home, qline.End, qline.PageUp, qline.PageDown:
|
|
w.sheets[w.sheet].moveSelection(input, w.termRows)
|
|
case Quit:
|
|
if modified {
|
|
fmt.Print("There are unsaved changes. Quit anyway? [y/n]")
|
|
answer, err := Getch()
|
|
if err != nil || answer == 'n' || answer == 'N' {
|
|
continue
|
|
}
|
|
fmt.Print("\n")
|
|
}
|
|
termios.Restore()
|
|
fmt.Print("\033[?25h")
|
|
os.Exit(0)
|
|
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, w.termCols, quote)
|
|
w.sheets[w.sheet].Recalculate()
|
|
case Del, qline.Delete, qline.BackSpace:
|
|
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1] = cell{}
|
|
w.sheets[w.sheet].Recalculate()
|
|
case Com:
|
|
line := GetEditLine(":", "", w.termCols)
|
|
runCommand(strings.Fields(line))
|
|
case ZoomIn:
|
|
w.sheets[w.sheet].ZoomIn()
|
|
fmt.Print("\033[2J")
|
|
case ZoomOut:
|
|
w.sheets[w.sheet].ZoomOut()
|
|
fmt.Print("\033[2J")
|
|
case Yank:
|
|
w.sheets[w.sheet].Yank()
|
|
case Paste:
|
|
w.sheets[w.sheet].Paste()
|
|
w.sheets[w.sheet].Recalculate()
|
|
case PasteRelative:
|
|
w.sheets[w.sheet].PasteRelative()
|
|
w.sheets[w.sheet].Recalculate()
|
|
case ModBold:
|
|
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].ToggleMod(Bold)
|
|
case ModFaint:
|
|
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].ToggleMod(Faint)
|
|
case ModItalic:
|
|
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].ToggleMod(Italic)
|
|
case ModUnderline:
|
|
w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].ToggleMod(Underline)
|
|
case OpenLink:
|
|
url := w.sheets[w.sheet].cells[w.sheets[w.sheet].selection.row-1][w.sheets[w.sheet].selection.col-1].mask
|
|
if IsURL(url) {
|
|
OpenInBrowser(url)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func makeWorkbook(path string) workbook {
|
|
// TODO parse path and get file name
|
|
// set name of strict to the filename
|
|
// or untitled.qsh if no filename; set
|
|
// path to the full path
|
|
cols, rows := termios.GetWindowSize()
|
|
sh := makeSheet("Sheet1")
|
|
wb = workbook{filepath.Base(path), path, make([]sheet,1), 0, rows, cols}
|
|
wb.sheets[0] = sh
|
|
return wb
|
|
}
|
|
|
|
func (w workbook) header() string {
|
|
return fmt.Sprintf("\033[1;7m %s \033[0m %s\n",w.name, w.sheets[w.sheet].name)
|
|
}
|
|
|