cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

cat/module-path
012 / internal / ui / assistsheets.go
assistsheets.go 2.2K
1package ui23import (4 "src.rest/cat/012/internal/sheet"5 "src.rest/cat/012/internal/ui/lineedit"6)78// Pointing after a sheet's name: once a suggestion (package suggest) or9// typing has put Summary! before the caret, an arrow points into that10// sheet, as clicking its tab would, so the reference comes out as11// Summary!B3.1213// sheetBeforeCaret returns the sheet named just before the caret, as in14// "=SUM(Summary!" or "='Q3 plan'!", and where its name starts.15func sheetBeforeCaret(l *lineedit.Line, book *sheet.Workbook) (*sheet.Sheet, int, bool) {16 head := l.Buf[:l.Pos]17 end := len(head) - 1 // the "!"18 if end < 2 || head[end] != '!' {19 return nil, 0, false20 }21 start := end22 if head[end-1] == '\'' {23 start = -124 for i := end - 2; i >= 1; i-- {25 if head[i] != '\'' {26 continue27 }28 if head[i-1] == '\'' {29 i-- // '' inside a quoted name30 continue31 }32 start = i33 break34 }35 } else {36 for start > 1 && isNameRune(head[start-1]) {37 start--38 }39 }40 if start < 1 || start >= end {41 return nil, 0, false42 }43 name, _ := sheet.SplitSheet(string(head[start:]))44 s := book.Lookup(name)45 return s, start, s != nil46}4748func isNameRune(r rune) bool {49 return r == '_' || r == '.' || r >= '0' && r <= '9' || r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' || r > 0x7f50}5152// pointAfterSheet starts pointing with key when the caret follows a53// sheet reference such as "Summary!": on that sheet, the name typed54// giving way to the reference pointed at (Summary!B3), as if its tab had55// been clicked. It reports whether it did.56func (m *Model) pointAfterSheet(key string) bool {57 if _, extend := extendKey(key); !extend && (!isMoveKey(key) || key == "tab" || key == "shift+tab") {58 return false59 }60 s, start, ok := sheetBeforeCaret(&m.line, m.book())61 if !ok || s.Hidden() {62 return false63 }64 if s == m.sheet && !m.away() {65 return m.startPoint(key) // its own sheet: the name stays as typed66 }67 m.line.Buf = append(m.line.Buf[:start:start], m.line.Buf[m.line.Pos:]...)68 m.line.Pos = start69 if s == m.sheet {70 return m.startPoint(key)71 }72 m.pointInto(s)73 if m.mode != modePoint {74 return true75 }76 if base, extend := extendKey(key); extend {77 m.point.anchor, m.point.anchored = m.point.at, true78 key = base79 }80 m.navigate(key, &m.point.at)81 return true82}