mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
layout: rename formatState to formatter
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+143
-143
@@ -9,7 +9,7 @@ import (
|
|||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type formatState struct {
|
type formatter struct {
|
||||||
current int
|
current int
|
||||||
orig string
|
orig string
|
||||||
expr string
|
expr string
|
||||||
@@ -71,7 +71,7 @@ func Format(gtx *Context, format string, widgets ...Widget) {
|
|||||||
if format == "" {
|
if format == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state := formatState{
|
f := formatter{
|
||||||
orig: format,
|
orig: format,
|
||||||
expr: format,
|
expr: format,
|
||||||
}
|
}
|
||||||
@@ -80,185 +80,185 @@ func Format(gtx *Context, format string, widgets ...Widget) {
|
|||||||
if _, ok := err.(formatError); !ok {
|
if _, ok := err.(formatError); !ok {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
pos := len(state.orig) - len(state.expr)
|
pos := len(f.orig) - len(f.expr)
|
||||||
msg := state.orig[:pos] + "✗" + state.orig[pos:]
|
msg := f.orig[:pos] + "✗" + f.orig[pos:]
|
||||||
panic(fmt.Errorf("Format: %s:%d: %s", msg, pos, err))
|
panic(fmt.Errorf("Format: %s:%d: %s", msg, pos, err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
formatExpr(gtx, &state, widgets)
|
formatExpr(gtx, &f, widgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatExpr(gtx *Context, state *formatState, widgets []Widget) {
|
func formatExpr(gtx *Context, f *formatter, widgets []Widget) {
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case '_':
|
case '_':
|
||||||
formatWidget(gtx, state, widgets)
|
formatWidget(gtx, f, widgets)
|
||||||
default:
|
default:
|
||||||
formatLayout(gtx, state, widgets)
|
formatLayout(gtx, f, widgets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatLayout(gtx *Context, state *formatState, widgets []Widget) {
|
func formatLayout(gtx *Context, f *formatter, widgets []Widget) {
|
||||||
name := parseName(state)
|
name := parseName(f)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
errorf("missing layout name")
|
errorf("missing layout name")
|
||||||
}
|
}
|
||||||
expect(state, "(")
|
expect(f, "(")
|
||||||
f := func() {
|
fexpr := func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
}
|
}
|
||||||
align, ok := dirFor(name)
|
align, ok := dirFor(name)
|
||||||
if ok {
|
if ok {
|
||||||
Align(align).Layout(gtx, f)
|
Align(align).Layout(gtx, fexpr)
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch name {
|
switch name {
|
||||||
case "inset":
|
case "inset":
|
||||||
in := parseInset(gtx, state, widgets)
|
in := parseInset(gtx, f, widgets)
|
||||||
in.Layout(gtx, f)
|
in.Layout(gtx, fexpr)
|
||||||
case "hflex":
|
case "hflex":
|
||||||
formatFlex(gtx, Horizontal, state, widgets)
|
formatFlex(gtx, Horizontal, f, widgets)
|
||||||
case "vflex":
|
case "vflex":
|
||||||
formatFlex(gtx, Vertical, state, widgets)
|
formatFlex(gtx, Vertical, f, widgets)
|
||||||
case "stack":
|
case "stack":
|
||||||
formatStack(gtx, state, widgets)
|
formatStack(gtx, f, widgets)
|
||||||
case "hmax":
|
case "hmax":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Width.Min = cs.Width.Max
|
cs.Width.Min = cs.Width.Max
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "vmax":
|
case "vmax":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Height.Min = cs.Height.Max
|
cs.Height.Min = cs.Height.Max
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "max":
|
case "max":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Width.Min = cs.Width.Max
|
cs.Width.Min = cs.Width.Max
|
||||||
cs.Height.Min = cs.Height.Max
|
cs.Height.Min = cs.Height.Max
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "hmin":
|
case "hmin":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Width.Max = cs.Width.Min
|
cs.Width.Max = cs.Width.Min
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "vmin":
|
case "vmin":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Height.Max = cs.Height.Min
|
cs.Height.Max = cs.Height.Min
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "min":
|
case "min":
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Width.Max = cs.Width.Min
|
cs.Width.Max = cs.Width.Min
|
||||||
cs.Height.Max = cs.Height.Min
|
cs.Height.Max = cs.Height.Min
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "hcap":
|
case "hcap":
|
||||||
w := parseValue(state)
|
w := parseValue(f)
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Width.Max = cs.Width.Constrain(gtx.Px(w))
|
cs.Width.Max = cs.Width.Constrain(gtx.Px(w))
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
case "vcap":
|
case "vcap":
|
||||||
h := parseValue(state)
|
h := parseValue(f)
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
cs.Height.Max = cs.Height.Constrain(gtx.Px(h))
|
cs.Height.Max = cs.Height.Constrain(gtx.Px(h))
|
||||||
ctxLayout(gtx, cs, func() {
|
ctxLayout(gtx, cs, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
errorf("invalid layout %q", name)
|
errorf("invalid layout %q", name)
|
||||||
}
|
}
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatWidget(gtx *Context, state *formatState, widgets []Widget) {
|
func formatWidget(gtx *Context, f *formatter, widgets []Widget) {
|
||||||
expect(state, "_")
|
expect(f, "_")
|
||||||
if i, max := state.current, len(widgets)-1; i > max {
|
if i, max := f.current, len(widgets)-1; i > max {
|
||||||
errorf("widget index %d out of bounds [0;%d]", i, max)
|
errorf("widget index %d out of bounds [0;%d]", i, max)
|
||||||
}
|
}
|
||||||
if state.skip == 0 {
|
if f.skip == 0 {
|
||||||
widgets[state.current]()
|
widgets[f.current]()
|
||||||
}
|
}
|
||||||
state.current++
|
f.current++
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatStack(gtx *Context, state *formatState, widgets []Widget) {
|
func formatStack(gtx *Context, f *formatter, widgets []Widget) {
|
||||||
st := Stack{}
|
st := Stack{}
|
||||||
// Parse alignment, if present.
|
// Parse alignment, if present.
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case 'r', 'e', ')':
|
case 'r', 'e', ')':
|
||||||
default:
|
default:
|
||||||
name := parseName(state)
|
name := parseName(f)
|
||||||
align, ok := dirFor(name)
|
align, ok := dirFor(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
errorf("invalid stack alignment: %q", name)
|
errorf("invalid stack alignment: %q", name)
|
||||||
}
|
}
|
||||||
st.Alignment = align
|
st.Alignment = align
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
}
|
}
|
||||||
var children []StackChild
|
var children []StackChild
|
||||||
// First, lay out rigid children.
|
// First, lay out rigid children.
|
||||||
backup := *state
|
backup := *f
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case ')':
|
case ')':
|
||||||
break loop
|
break loop
|
||||||
case ',':
|
case ',':
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
case 'r':
|
case 'r':
|
||||||
expect(state, "r(")
|
expect(f, "r(")
|
||||||
children = append(children, st.Rigid(gtx, func() {
|
children = append(children, st.Rigid(gtx, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
}))
|
}))
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
case 'e':
|
case 'e':
|
||||||
expect(state, "e(")
|
expect(f, "e(")
|
||||||
state.skip++
|
f.skip++
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
children = append(children, StackChild{})
|
children = append(children, StackChild{})
|
||||||
state.skip--
|
f.skip--
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
default:
|
default:
|
||||||
errorf("invalid flex child")
|
errorf("invalid flex child")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Then, lay out expanded children.
|
// Then, lay out expanded children.
|
||||||
*state = backup
|
*f = backup
|
||||||
child := 0
|
child := 0
|
||||||
for {
|
for {
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case ')':
|
case ')':
|
||||||
if state.skip == 0 {
|
if f.skip == 0 {
|
||||||
st.Layout(gtx, children...)
|
st.Layout(gtx, children...)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case ',':
|
case ',':
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
case 'r':
|
case 'r':
|
||||||
expect(state, "r(")
|
expect(f, "r(")
|
||||||
state.skip++
|
f.skip++
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
state.skip--
|
f.skip--
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
child++
|
child++
|
||||||
case 'e':
|
case 'e':
|
||||||
expect(state, "e(")
|
expect(f, "e(")
|
||||||
children[child] = st.Expand(gtx, func() {
|
children[child] = st.Expand(gtx, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
child++
|
child++
|
||||||
default:
|
default:
|
||||||
errorf("invalid flex child")
|
errorf("invalid flex child")
|
||||||
@@ -266,13 +266,13 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatFlex(gtx *Context, axis Axis, state *formatState, widgets []Widget) {
|
func formatFlex(gtx *Context, axis Axis, f *formatter, widgets []Widget) {
|
||||||
fl := Flex{Axis: axis}
|
fl := Flex{Axis: axis}
|
||||||
// Parse alignment, if present.
|
// Parse alignment, if present.
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case 'r', 'f', ')':
|
case 'r', 'f', ')':
|
||||||
default:
|
default:
|
||||||
name := parseName(state)
|
name := parseName(f)
|
||||||
switch name {
|
switch name {
|
||||||
case "start":
|
case "start":
|
||||||
fl.Alignment = Start
|
fl.Alignment = Start
|
||||||
@@ -285,64 +285,64 @@ func formatFlex(gtx *Context, axis Axis, state *formatState, widgets []Widget) {
|
|||||||
default:
|
default:
|
||||||
errorf("invalid flex alignment: %q", name)
|
errorf("invalid flex alignment: %q", name)
|
||||||
}
|
}
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
}
|
}
|
||||||
var children []FlexChild
|
var children []FlexChild
|
||||||
// First, lay out rigid children.
|
// First, lay out rigid children.
|
||||||
backup := *state
|
backup := *f
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case ')':
|
case ')':
|
||||||
break loop
|
break loop
|
||||||
case ',':
|
case ',':
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
case 'r':
|
case 'r':
|
||||||
expect(state, "r(")
|
expect(f, "r(")
|
||||||
children = append(children, fl.Rigid(gtx, func() {
|
children = append(children, fl.Rigid(gtx, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
}))
|
}))
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
case 'f':
|
case 'f':
|
||||||
expect(state, "f(")
|
expect(f, "f(")
|
||||||
parseFloat(state)
|
parseFloat(f)
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
state.skip++
|
f.skip++
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
children = append(children, FlexChild{})
|
children = append(children, FlexChild{})
|
||||||
state.skip--
|
f.skip--
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
default:
|
default:
|
||||||
errorf("invalid flex child")
|
errorf("invalid flex child")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Then, lay out flexible children.
|
// Then, lay out flexible children.
|
||||||
*state = backup
|
*f = backup
|
||||||
child := 0
|
child := 0
|
||||||
for {
|
for {
|
||||||
switch peek(state) {
|
switch peek(f) {
|
||||||
case ')':
|
case ')':
|
||||||
if state.skip == 0 {
|
if f.skip == 0 {
|
||||||
fl.Layout(gtx, children...)
|
fl.Layout(gtx, children...)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case ',':
|
case ',':
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
case 'r':
|
case 'r':
|
||||||
expect(state, "r(")
|
expect(f, "r(")
|
||||||
state.skip++
|
f.skip++
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
state.skip--
|
f.skip--
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
child++
|
child++
|
||||||
case 'f':
|
case 'f':
|
||||||
expect(state, "f(")
|
expect(f, "f(")
|
||||||
weight := parseFloat(state)
|
weight := parseFloat(f)
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
children[child] = fl.Flex(gtx, weight, func() {
|
children[child] = fl.Flex(gtx, weight, func() {
|
||||||
formatExpr(gtx, state, widgets)
|
formatExpr(gtx, f, widgets)
|
||||||
})
|
})
|
||||||
expect(state, ")")
|
expect(f, ")")
|
||||||
child++
|
child++
|
||||||
default:
|
default:
|
||||||
errorf("invalid flex child")
|
errorf("invalid flex child")
|
||||||
@@ -350,15 +350,15 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseInset(gtx *Context, state *formatState, widgets []Widget) Inset {
|
func parseInset(gtx *Context, f *formatter, widgets []Widget) Inset {
|
||||||
v1 := parseValue(state)
|
v1 := parseValue(f)
|
||||||
if peek(state) == ',' {
|
if peek(f) == ',' {
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
return UniformInset(v1)
|
return UniformInset(v1)
|
||||||
}
|
}
|
||||||
v2 := parseValue(state)
|
v2 := parseValue(f)
|
||||||
if peek(state) == ',' {
|
if peek(f) == ',' {
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
return Inset{
|
return Inset{
|
||||||
Top: v1,
|
Top: v1,
|
||||||
Right: v2,
|
Right: v2,
|
||||||
@@ -366,9 +366,9 @@ func parseInset(gtx *Context, state *formatState, widgets []Widget) Inset {
|
|||||||
Left: v2,
|
Left: v2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v3 := parseValue(state)
|
v3 := parseValue(f)
|
||||||
if peek(state) == ',' {
|
if peek(f) == ',' {
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
return Inset{
|
return Inset{
|
||||||
Top: v1,
|
Top: v1,
|
||||||
Right: v2,
|
Right: v2,
|
||||||
@@ -376,8 +376,8 @@ func parseInset(gtx *Context, state *formatState, widgets []Widget) Inset {
|
|||||||
Left: v2,
|
Left: v2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v4 := parseValue(state)
|
v4 := parseValue(f)
|
||||||
expect(state, ",")
|
expect(f, ",")
|
||||||
return Inset{
|
return Inset{
|
||||||
Top: v1,
|
Top: v1,
|
||||||
Right: v2,
|
Right: v2,
|
||||||
@@ -386,12 +386,12 @@ func parseInset(gtx *Context, state *formatState, widgets []Widget) Inset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseValue(state *formatState) unit.Value {
|
func parseValue(f *formatter) unit.Value {
|
||||||
i := parseFloat(state)
|
i := parseFloat(f)
|
||||||
if len(state.expr) < 2 {
|
if len(f.expr) < 2 {
|
||||||
errorf("missing unit")
|
errorf("missing unit")
|
||||||
}
|
}
|
||||||
u := state.expr[:2]
|
u := f.expr[:2]
|
||||||
var v unit.Value
|
var v unit.Value
|
||||||
switch u {
|
switch u {
|
||||||
case "dp":
|
case "dp":
|
||||||
@@ -403,84 +403,84 @@ func parseValue(state *formatState) unit.Value {
|
|||||||
default:
|
default:
|
||||||
errorf("unknown unit")
|
errorf("unknown unit")
|
||||||
}
|
}
|
||||||
state.expr = state.expr[len(u):]
|
f.expr = f.expr[len(u):]
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseName(state *formatState) string {
|
func parseName(f *formatter) string {
|
||||||
i := 0
|
i := 0
|
||||||
for ; i < len(state.expr); i++ {
|
for ; i < len(f.expr); i++ {
|
||||||
c := state.expr[i]
|
c := f.expr[i]
|
||||||
switch {
|
switch {
|
||||||
case c == '(' || c == ',' || c == ')':
|
case c == '(' || c == ',' || c == ')':
|
||||||
fname := state.expr[:i]
|
fname := f.expr[:i]
|
||||||
state.expr = state.expr[i:]
|
f.expr = f.expr[i:]
|
||||||
return fname
|
return fname
|
||||||
case c < 'a' || 'z' < c:
|
case c < 'a' || 'z' < c:
|
||||||
errorf("invalid character '%c' in layout name", c)
|
errorf("invalid character '%c' in layout name", c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.expr = state.expr[i:]
|
f.expr = f.expr[i:]
|
||||||
errorf("missing ( after layout function")
|
errorf("missing ( after layout function")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFloat(state *formatState) float32 {
|
func parseFloat(f *formatter) float32 {
|
||||||
i := 0
|
i := 0
|
||||||
for ; i < len(state.expr); i++ {
|
for ; i < len(f.expr); i++ {
|
||||||
c := state.expr[i]
|
c := f.expr[i]
|
||||||
if (c < '0' || c > '9') && c != '.' {
|
if (c < '0' || c > '9') && c != '.' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr := state.expr[:i]
|
expr := f.expr[:i]
|
||||||
v, err := strconv.ParseFloat(expr, 32)
|
v, err := strconv.ParseFloat(expr, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorf("invalid number %q", expr)
|
errorf("invalid number %q", expr)
|
||||||
}
|
}
|
||||||
state.expr = state.expr[i:]
|
f.expr = f.expr[i:]
|
||||||
return float32(v)
|
return float32(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseInt(state *formatState) int {
|
func parseInt(f *formatter) int {
|
||||||
i := 0
|
i := 0
|
||||||
for ; i < len(state.expr); i++ {
|
for ; i < len(f.expr); i++ {
|
||||||
c := state.expr[i]
|
c := f.expr[i]
|
||||||
if c < '0' || c > '9' {
|
if c < '0' || c > '9' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr := state.expr[:i]
|
expr := f.expr[:i]
|
||||||
v, err := strconv.Atoi(expr)
|
v, err := strconv.Atoi(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorf("invalid number %q", expr)
|
errorf("invalid number %q", expr)
|
||||||
}
|
}
|
||||||
state.expr = state.expr[i:]
|
f.expr = f.expr[i:]
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func peek(state *formatState) rune {
|
func peek(f *formatter) rune {
|
||||||
skipWhitespace(state)
|
skipWhitespace(f)
|
||||||
if len(state.expr) == 0 {
|
if len(f.expr) == 0 {
|
||||||
errorf("unexpected end")
|
errorf("unexpected end")
|
||||||
}
|
}
|
||||||
return rune(state.expr[0])
|
return rune(f.expr[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func expect(state *formatState, str string) {
|
func expect(f *formatter, str string) {
|
||||||
skipWhitespace(state)
|
skipWhitespace(f)
|
||||||
n := len(str)
|
n := len(str)
|
||||||
if len(state.expr) < n || state.expr[:n] != str {
|
if len(f.expr) < n || f.expr[:n] != str {
|
||||||
errorf("expected %q", str)
|
errorf("expected %q", str)
|
||||||
}
|
}
|
||||||
state.expr = state.expr[n:]
|
f.expr = f.expr[n:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipWhitespace(state *formatState) {
|
func skipWhitespace(f *formatter) {
|
||||||
for len(state.expr) > 0 {
|
for len(f.expr) > 0 {
|
||||||
switch state.expr[0] {
|
switch f.expr[0] {
|
||||||
case '\t', '\n', '\v', '\f', '\r', ' ':
|
case '\t', '\n', '\v', '\f', '\r', ' ':
|
||||||
state.expr = state.expr[1:]
|
f.expr = f.expr[1:]
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user