Compare commits
5 Commits
e07bb9e496
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0f7d74adc | ||
|
|
3dd1cfef55 | ||
|
|
555ca1f6ab | ||
|
|
1af6539deb | ||
|
|
a8c7ad60c3 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
db.*
|
db.*
|
||||||
|
main
|
||||||
|
debug.log
|
||||||
|
|||||||
298
cmd/sqv-tea/main.go
Normal file
298
cmd/sqv-tea/main.go
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
engine "git.pablu.de/pablu/sqv-engine"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
"github.com/charmbracelet/bubbles/textarea"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/charmbracelet/lipgloss/table"
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Focused int
|
||||||
|
|
||||||
|
const (
|
||||||
|
EDITOR Focused = iota
|
||||||
|
TABLE
|
||||||
|
PICKER
|
||||||
|
)
|
||||||
|
|
||||||
|
type mainModel struct {
|
||||||
|
width, height int
|
||||||
|
|
||||||
|
manager *engine.Manager
|
||||||
|
|
||||||
|
lastFocused, focused Focused
|
||||||
|
|
||||||
|
table *table.Table
|
||||||
|
editor textarea.Model
|
||||||
|
picker list.Model
|
||||||
|
|
||||||
|
debugMsgs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultStyle = lipgloss.NewStyle().
|
||||||
|
Align(lipgloss.Center).
|
||||||
|
BorderStyle(lipgloss.NormalBorder())
|
||||||
|
|
||||||
|
focusedStyle = defaultStyle.BorderForeground(lipgloss.Color("202"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type item struct {
|
||||||
|
title string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i item) Title() string { return i.title }
|
||||||
|
func (i item) Description() string { return i.title }
|
||||||
|
func (i item) FilterValue() string { return i.title }
|
||||||
|
|
||||||
|
func newMainModerl(manager *engine.Manager) mainModel {
|
||||||
|
ed := textarea.New()
|
||||||
|
ed.Placeholder = "Try \"SELECT * FROM ?;\""
|
||||||
|
|
||||||
|
ed.ShowLineNumbers = false
|
||||||
|
|
||||||
|
ta := table.New().Border(lipgloss.NormalBorder())
|
||||||
|
|
||||||
|
li := list.New(nil, list.NewDefaultDelegate(), 0, 0)
|
||||||
|
li.Title = "Table Picker"
|
||||||
|
|
||||||
|
return mainModel{
|
||||||
|
editor: ed,
|
||||||
|
table: ta,
|
||||||
|
picker: li,
|
||||||
|
manager: manager,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) Init() tea.Cmd {
|
||||||
|
return m.GetTableDefinitions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) GetTableDefinitions() tea.Msg {
|
||||||
|
|
||||||
|
tables := m.manager.GetTables()
|
||||||
|
tableNames := make([]list.Item, len(tables))
|
||||||
|
|
||||||
|
for i, table := range tables {
|
||||||
|
tableNames[i] = item{table.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableDefinitionsMsg{
|
||||||
|
tableNames,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type tableDefinitionsMsg struct {
|
||||||
|
Tables []list.Item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) GetFirstTable() tea.Msg {
|
||||||
|
t := m.manager.GetTables()[0]
|
||||||
|
cmd := m.GetTable(t.Name)
|
||||||
|
return cmd()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) GetTable(name string) tea.Cmd {
|
||||||
|
return func() tea.Msg {
|
||||||
|
t, ok := m.manager.GetTable(name)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.manager.LoadTable(&t)
|
||||||
|
|
||||||
|
msg := tableMsg{
|
||||||
|
Columns: make([]string, len(t.Columns)),
|
||||||
|
Rows: make([][]string, len(t.Rows)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, r := range t.Rows {
|
||||||
|
msg.Rows[i] = r.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range t.Columns {
|
||||||
|
msg.Columns[i] = c.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type tableMsg struct {
|
||||||
|
Columns []string
|
||||||
|
Rows [][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var (
|
||||||
|
edCmd tea.Cmd
|
||||||
|
pickerCmd tea.Cmd
|
||||||
|
cmds tea.Cmd
|
||||||
|
)
|
||||||
|
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "ctrl+c":
|
||||||
|
return m, tea.Quit
|
||||||
|
case "tab":
|
||||||
|
if m.focused == EDITOR {
|
||||||
|
m.focused = TABLE
|
||||||
|
m.editor.Blur()
|
||||||
|
} else {
|
||||||
|
m.focused = EDITOR
|
||||||
|
}
|
||||||
|
case "j":
|
||||||
|
m.table.Offset(50)
|
||||||
|
case "ctrl+e":
|
||||||
|
if m.focused == PICKER {
|
||||||
|
m.focused = m.lastFocused
|
||||||
|
} else {
|
||||||
|
// Maybe blur is not even needed
|
||||||
|
m.editor.Blur()
|
||||||
|
m.lastFocused = m.focused
|
||||||
|
m.focused = PICKER
|
||||||
|
}
|
||||||
|
case "enter":
|
||||||
|
log.Debug("Enter was pressed")
|
||||||
|
if m.focused == PICKER {
|
||||||
|
i, ok := m.picker.SelectedItem().(item)
|
||||||
|
if ok {
|
||||||
|
log.Debug("Selected item okay and batched")
|
||||||
|
cmds = tea.Batch(cmds, m.GetTable(i.title))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.focused = m.lastFocused
|
||||||
|
if m.focused == EDITOR {
|
||||||
|
m.editor.Focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m = m.updateStyles(msg.Width, msg.Height)
|
||||||
|
cmds = tea.Batch(cmds, m.GetFirstTable)
|
||||||
|
|
||||||
|
case tableMsg:
|
||||||
|
m.table.Offset(0)
|
||||||
|
m.table.ClearRows()
|
||||||
|
m.table.Headers(msg.Columns...)
|
||||||
|
m.table.Rows(msg.Rows...)
|
||||||
|
|
||||||
|
case tableDefinitionsMsg:
|
||||||
|
pickerCmd = m.picker.SetItems(msg.Tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.focused {
|
||||||
|
case EDITOR:
|
||||||
|
m.editor.Focus()
|
||||||
|
m.editor, edCmd = m.editor.Update(msg)
|
||||||
|
case PICKER:
|
||||||
|
m.picker, pickerCmd = m.picker.Update(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, tea.Batch(edCmd, cmds, pickerCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) updateStyles(width, height int) mainModel {
|
||||||
|
m.width = width
|
||||||
|
m.height = height
|
||||||
|
|
||||||
|
h, v := defaultStyle.GetFrameSize()
|
||||||
|
|
||||||
|
topHeight := math.Ceil(float64(m.height)*3/4 - float64(h))
|
||||||
|
editorHeight := math.Ceil(float64(m.height)*1/4 - float64(h))
|
||||||
|
|
||||||
|
m.editor.SetWidth(m.width - v)
|
||||||
|
m.editor.SetHeight(int(editorHeight))
|
||||||
|
|
||||||
|
m.table.Width(m.width - v)
|
||||||
|
m.table.Height(int(topHeight) - h*2)
|
||||||
|
|
||||||
|
m.picker.SetSize(m.width*7/10, m.height*7/10)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mainModel) View() string {
|
||||||
|
var (
|
||||||
|
view, editor string
|
||||||
|
)
|
||||||
|
|
||||||
|
h, _ := defaultStyle.GetFrameSize()
|
||||||
|
topHeight := (m.height * 3 / 4) - h
|
||||||
|
editorHeight := (m.height * 1 / 4) - h
|
||||||
|
switch m.focused {
|
||||||
|
case EDITOR:
|
||||||
|
view = defaultStyle.
|
||||||
|
Height(topHeight).
|
||||||
|
Render(m.table.Render())
|
||||||
|
editor = focusedStyle.
|
||||||
|
Height(editorHeight).
|
||||||
|
Render(m.editor.View())
|
||||||
|
case TABLE:
|
||||||
|
view = focusedStyle.
|
||||||
|
Height(topHeight).
|
||||||
|
Render(m.table.Render())
|
||||||
|
editor = defaultStyle.
|
||||||
|
Height(editorHeight).
|
||||||
|
Render(m.editor.View())
|
||||||
|
case PICKER:
|
||||||
|
view = defaultStyle.
|
||||||
|
Height(topHeight).
|
||||||
|
Render(m.table.Render())
|
||||||
|
editor = defaultStyle.
|
||||||
|
Height(editorHeight).
|
||||||
|
Render(m.editor.View())
|
||||||
|
}
|
||||||
|
|
||||||
|
main := lipgloss.JoinVertical(lipgloss.Top, view, editor)
|
||||||
|
|
||||||
|
if m.focused == PICKER {
|
||||||
|
x := (m.width / 2) - m.picker.Width()/2
|
||||||
|
y := (m.height / 2) - m.picker.Height()/2
|
||||||
|
|
||||||
|
return PlaceOverlay(x, y, focusedStyle.Render(m.picker.View()), main, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return main
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f, err := tea.LogToFile("debug.log", "debug")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("fatal:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
log.SetOutput(f)
|
||||||
|
|
||||||
|
m, err := engine.NewManager("../vdcmp/db.sqlite")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("fatal:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("fatal:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
table.New()
|
||||||
|
|
||||||
|
p := tea.NewProgram(newMainModerl(m), tea.WithAltScreen())
|
||||||
|
if _, err := p.Run(); err != nil {
|
||||||
|
fmt.Println("fatal:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
208
cmd/sqv-tea/util.go
Normal file
208
cmd/sqv-tea/util.go
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/mattn/go-runewidth"
|
||||||
|
"github.com/muesli/ansi"
|
||||||
|
"github.com/muesli/reflow/truncate"
|
||||||
|
"github.com/muesli/termenv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Most of this code is borrowed from
|
||||||
|
// https://github.com/charmbracelet/lipgloss/pull/102
|
||||||
|
// as well as the lipgloss library, with some modification for what I needed.
|
||||||
|
|
||||||
|
// Split a string into lines, additionally returning the size of the widest
|
||||||
|
// line.
|
||||||
|
func getLines(s string) (lines []string, widest int) {
|
||||||
|
lines = strings.Split(s, "\n")
|
||||||
|
|
||||||
|
for _, l := range lines {
|
||||||
|
w := ansi.PrintableRuneWidth(l)
|
||||||
|
if widest < w {
|
||||||
|
widest = w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines, widest
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlaceOverlay places fg on top of bg.
|
||||||
|
func PlaceOverlay(
|
||||||
|
x, y int,
|
||||||
|
fg, bg string,
|
||||||
|
shadow bool, opts ...WhitespaceOption,
|
||||||
|
) string {
|
||||||
|
fgLines, fgWidth := getLines(fg)
|
||||||
|
bgLines, bgWidth := getLines(bg)
|
||||||
|
bgHeight := len(bgLines)
|
||||||
|
fgHeight := len(fgLines)
|
||||||
|
|
||||||
|
if shadow {
|
||||||
|
var shadowbg string = ""
|
||||||
|
shadowchar := lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("#333333")).
|
||||||
|
Render("░")
|
||||||
|
for i := 0; i <= fgHeight; i++ {
|
||||||
|
if i == 0 {
|
||||||
|
shadowbg += " " + strings.Repeat(" ", fgWidth) + "\n"
|
||||||
|
} else {
|
||||||
|
shadowbg += " " + strings.Repeat(shadowchar, fgWidth) + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fg = PlaceOverlay(0, 0, fg, shadowbg, false, opts...)
|
||||||
|
fgLines, fgWidth = getLines(fg)
|
||||||
|
fgHeight = len(fgLines)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fgWidth >= bgWidth && fgHeight >= bgHeight {
|
||||||
|
// FIXME: return fg or bg?
|
||||||
|
return fg
|
||||||
|
}
|
||||||
|
// TODO: allow placement outside of the bg box?
|
||||||
|
x = clamp(x, 0, bgWidth-fgWidth)
|
||||||
|
y = clamp(y, 0, bgHeight-fgHeight)
|
||||||
|
|
||||||
|
ws := &whitespace{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
var b strings.Builder
|
||||||
|
for i, bgLine := range bgLines {
|
||||||
|
if i > 0 {
|
||||||
|
b.WriteByte('\n')
|
||||||
|
}
|
||||||
|
if i < y || i >= y+fgHeight {
|
||||||
|
b.WriteString(bgLine)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := 0
|
||||||
|
if x > 0 {
|
||||||
|
left := truncate.String(bgLine, uint(x))
|
||||||
|
pos = ansi.PrintableRuneWidth(left)
|
||||||
|
b.WriteString(left)
|
||||||
|
if pos < x {
|
||||||
|
b.WriteString(ws.render(x - pos))
|
||||||
|
pos = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fgLine := fgLines[i-y]
|
||||||
|
b.WriteString(fgLine)
|
||||||
|
pos += ansi.PrintableRuneWidth(fgLine)
|
||||||
|
|
||||||
|
right := cutLeft(bgLine, pos)
|
||||||
|
bgWidth := ansi.PrintableRuneWidth(bgLine)
|
||||||
|
rightWidth := ansi.PrintableRuneWidth(right)
|
||||||
|
if rightWidth <= bgWidth-pos {
|
||||||
|
b.WriteString(ws.render(bgWidth - rightWidth - pos))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString(right)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// cutLeft cuts printable characters from the left.
|
||||||
|
// This function is heavily based on muesli's ansi and truncate packages.
|
||||||
|
func cutLeft(s string, cutWidth int) string {
|
||||||
|
var (
|
||||||
|
pos int
|
||||||
|
isAnsi bool
|
||||||
|
ab bytes.Buffer
|
||||||
|
b bytes.Buffer
|
||||||
|
)
|
||||||
|
for _, c := range s {
|
||||||
|
var w int
|
||||||
|
if c == ansi.Marker || isAnsi {
|
||||||
|
isAnsi = true
|
||||||
|
ab.WriteRune(c)
|
||||||
|
if ansi.IsTerminator(c) {
|
||||||
|
isAnsi = false
|
||||||
|
if bytes.HasSuffix(ab.Bytes(), []byte("[0m")) {
|
||||||
|
ab.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
w = runewidth.RuneWidth(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos >= cutWidth {
|
||||||
|
if b.Len() == 0 {
|
||||||
|
if ab.Len() > 0 {
|
||||||
|
b.Write(ab.Bytes())
|
||||||
|
}
|
||||||
|
if pos-cutWidth > 1 {
|
||||||
|
b.WriteByte(' ')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.WriteRune(c)
|
||||||
|
}
|
||||||
|
pos += w
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp(v, lower, upper int) int {
|
||||||
|
return min(max(v, lower), upper)
|
||||||
|
}
|
||||||
|
|
||||||
|
func max(a, b int) int {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func min(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
type whitespace struct {
|
||||||
|
style termenv.Style
|
||||||
|
chars string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render whitespaces.
|
||||||
|
func (w whitespace) render(width int) string {
|
||||||
|
if w.chars == "" {
|
||||||
|
w.chars = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
r := []rune(w.chars)
|
||||||
|
j := 0
|
||||||
|
b := strings.Builder{}
|
||||||
|
|
||||||
|
// Cycle through runes and print them into the whitespace.
|
||||||
|
for i := 0; i < width; {
|
||||||
|
b.WriteRune(r[j])
|
||||||
|
j++
|
||||||
|
if j >= len(r) {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
i += ansi.PrintableRuneWidth(string(r[j]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill any extra gaps white spaces. This might be necessary if any runes
|
||||||
|
// are more than one cell wide, which could leave a one-rune gap.
|
||||||
|
short := width - ansi.PrintableRuneWidth(b.String())
|
||||||
|
if short > 0 {
|
||||||
|
b.WriteString(strings.Repeat(" ", short))
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.style.Styled(b.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhitespaceOption sets a styling rule for rendering whitespace.
|
||||||
|
type WhitespaceOption func(*whitespace)
|
||||||
@@ -168,6 +168,10 @@ func main() {
|
|||||||
return event
|
return event
|
||||||
})
|
})
|
||||||
|
|
||||||
|
menuView.SetFocusFunc(func() {
|
||||||
|
menuView.SetBorderColor(tcell.ColorRed)
|
||||||
|
})
|
||||||
|
|
||||||
if err := app.SetRoot(horizontalFlex, true).EnableMouse(true).Run(); err != nil {
|
if err := app.SetRoot(horizontalFlex, true).EnableMouse(true).Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
25
go.mod
25
go.mod
@@ -9,12 +9,35 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
|
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
github.com/gdamore/encoding v1.0.1 // indirect
|
github.com/gdamore/encoding v1.0.1 // indirect
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||||
golang.org/x/term v0.28.0 // indirect
|
golang.org/x/term v0.28.0 // indirect
|
||||||
golang.org/x/text v0.25.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.36.0 // indirect
|
require (
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.10
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
|
github.com/charmbracelet/log v0.4.2
|
||||||
|
github.com/muesli/reflow v0.3.0
|
||||||
|
golang.org/x/sys v0.36.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
48
go.sum
48
go.sum
@@ -1,26 +1,72 @@
|
|||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
||||||
|
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||||
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||||
|
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||||
|
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
||||||
|
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||||
|
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
||||||
|
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||||
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
||||||
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
||||||
github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU=
|
github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU=
|
||||||
github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw=
|
github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw=
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||||
|
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
|
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||||
|
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||||
|
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||||
|
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||||
github.com/rivo/tview v0.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c=
|
github.com/rivo/tview v0.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c=
|
||||||
github.com/rivo/tview v0.42.0/go.mod h1:cSfIYfhpSGCjp3r/ECJb+GKS7cGJnqV8vfjQPwoXyfY=
|
github.com/rivo/tview v0.42.0/go.mod h1:cSfIYfhpSGCjp3r/ECJb+GKS7cGJnqV8vfjQPwoXyfY=
|
||||||
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
@@ -44,9 +90,11 @@ golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
|||||||
14
sql/lexer.go
14
sql/lexer.go
@@ -25,6 +25,10 @@ const (
|
|||||||
QUOTE
|
QUOTE
|
||||||
SINGLE_QUOTE
|
SINGLE_QUOTE
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
TYPE_NUMERIC
|
||||||
|
TYPE_TEXT
|
||||||
|
|
||||||
// Keywords
|
// Keywords
|
||||||
CREATE
|
CREATE
|
||||||
TABLE
|
TABLE
|
||||||
@@ -157,6 +161,12 @@ func (l *Lexer) Lex() (Position, Token, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return startPos, IDENT, lit
|
return startPos, IDENT, lit
|
||||||
|
} else if unicode.IsNumber(r) {
|
||||||
|
startPos := l.pos
|
||||||
|
l.backup()
|
||||||
|
lit := l.lexIdent()
|
||||||
|
|
||||||
|
return startPos, TYPE_NUMERIC, lit
|
||||||
} else {
|
} else {
|
||||||
return l.pos, ILLEGAL, string(r)
|
return l.pos, ILLEGAL, string(r)
|
||||||
}
|
}
|
||||||
@@ -176,7 +186,9 @@ func (l *Lexer) lexIdent() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.pos.column++
|
l.pos.column++
|
||||||
if unicode.IsLetter(r) || unicode.IsNumber(r) || r == '_' {
|
|
||||||
|
// Dont allow dot, just for testing with numeric
|
||||||
|
if unicode.IsLetter(r) || unicode.IsNumber(r) || r == '_' || r == '.' {
|
||||||
// Change this to stringstream or something similar
|
// Change this to stringstream or something similar
|
||||||
lit = lit + string(r)
|
lit = lit + string(r)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (p *Parser) parseInsert() (*InsertStatement, error) {
|
|||||||
for loop := true; loop; {
|
for loop := true; loop; {
|
||||||
_, tok, val := p.scan()
|
_, tok, val := p.scan()
|
||||||
switch tok {
|
switch tok {
|
||||||
case IDENT:
|
case IDENT, TYPE_NUMERIC:
|
||||||
// TODO, convert to actual datatype?
|
// TODO, convert to actual datatype?
|
||||||
values = append(values, val)
|
values = append(values, val)
|
||||||
case COMMA, QUOTE, SINGLE_QUOTE, BACKQUOTE:
|
case COMMA, QUOTE, SINGLE_QUOTE, BACKQUOTE:
|
||||||
@@ -47,7 +47,7 @@ func (p *Parser) parseInsert() (*InsertStatement, error) {
|
|||||||
case RPAREN:
|
case RPAREN:
|
||||||
loop = false
|
loop = false
|
||||||
default:
|
default:
|
||||||
return nil, p.unexpectedToken(IDENT, RPAREN, COMMA)
|
return nil, p.unexpectedToken(IDENT, RPAREN, COMMA, TYPE_NUMERIC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user