"os"
"path/filepath"
"runtime"
- "strings"
"tabwriter"
)
)
-const (
- esc2 = '\xfe' // an escape byte that cannot occur in regular UTF-8
- _ = 1 / (esc2 - tabwriter.Escape) // cause compiler error if esc2 == tabwriter.Escape
- esc2str = "\xfe"
-)
-
-
var (
esc = []byte{tabwriter.Escape}
htab = []byte{'\t'}
data = x.Name
tok = token.IDENT
case *ast.BasicLit:
- // If we have a raw string that spans multiple lines and
- // the opening quote (`) is on a line preceded only by
- // indentation, we don't want to write that indentation
- // because the following lines of the raw string are not
- // indented. It's easiest to correct the output at the end
- // via the trimmer (because of the complex handling of
- // white space).
- // Mark multi-line raw strings by replacing the opening
- // quote with esc2 and have the trimmer take care of fixing
- // it up.
- if x.Value[0] == '`' && strings.Index(x.Value, "\n") > 0 {
- data = p.escape(esc2str + x.Value[1:])
- } else {
- data = p.escape(x.Value)
- }
+ data = p.escape(x.Value)
tok = x.Kind
case token.Token:
s := x.String()
// through unchanged.
//
type trimmer struct {
- output io.Writer
- state int
- space bytes.Buffer
- hasText bool
+ output io.Writer
+ state int
+ space bytes.Buffer
}
// It can be in one of the following states:
const (
inSpace = iota // inside space
- atEscape // inside space and the last char was an opening tabwriter.Escape
inEscape // inside text bracketed by tabwriter.Escapes
inText // inside text
)
-var backquote = []byte{'`'}
-
-
// Design note: It is tempting to eliminate extra blanks occurring in
// whitespace in this function as it could simplify some
// of the blanks logic in the node printing functions.
func (p *trimmer) Write(data []byte) (n int, err os.Error) {
// invariants:
- // p.state == inSpace, atEscape:
+ // p.state == inSpace:
// p.space is unwritten
- // p.hasText indicates if there is any text on this line
// p.state == inEscape, inText:
// data[m:n] is unwritten
m := 0
case '\n', '\f':
p.space.Reset() // discard trailing space
_, err = p.output.Write(newlines[0:1]) // write newline
- p.hasText = false
case tabwriter.Escape:
- p.state = atEscape
+ _, err = p.output.Write(p.space.Bytes())
+ p.state = inEscape
+ m = n + 1 // +1: skip tabwriter.Escape
default:
_, err = p.output.Write(p.space.Bytes())
p.state = inText
m = n
}
- case atEscape:
- // discard indentation if we have a multi-line raw string
- // (see printer.print for details)
- if b != esc2 || p.hasText {
- _, err = p.output.Write(p.space.Bytes())
- }
- p.state = inEscape
- m = n
- if b == esc2 {
- _, err = p.output.Write(backquote) // convert back
- m++
- }
case inEscape:
if b == tabwriter.Escape {
_, err = p.output.Write(data[m:n])
p.state = inSpace
p.space.Reset()
- p.hasText = true
}
case inText:
switch b {
p.state = inSpace
p.space.Reset()
p.space.WriteByte(b) // WriteByte returns no errors
- p.hasText = true
case '\n', '\f':
_, err = p.output.Write(data[m:n])
p.state = inSpace
p.space.Reset()
_, err = p.output.Write(newlines[0:1]) // write newline
- p.hasText = false
case tabwriter.Escape:
_, err = p.output.Write(data[m:n])
- p.state = atEscape
- p.space.Reset()
- p.hasText = true
+ p.state = inEscape
+ m = n + 1 // +1: skip tabwriter.Escape
}
+ default:
+ panic("unreachable")
}
if err != nil {
return
_, err = p.output.Write(data[m:n])
p.state = inSpace
p.space.Reset()
- p.hasText = true
}
return
_ = `foo
bar`
_ = `three spaces before the end of the line starting here:
-they must not be removed`\f}
+they must not be removed`
+}
func _() {
var _ = ``
var _ = `foo`
var _ =
- // the next line should not be indented
-`foo
+ // the next line should remain indented
+ `foo
bar`
var _ = // comment
var _ = // comment
`foo`
var _ = // comment
- // the next line should not be indented
-`foo
+ // the next line should remain indented
+ `foo
bar`
var _ = /* comment */ ``
var _ = /* comment */
`foo`
var _ = /* comment */
- // the next line should not be indented
-`foo
+ // the next line should remain indented
+ `foo
bar`
var board = []int(
-`...........
+ `...........
...........
....●●●....
....●●●....
var state = S{
"foo",
- // the next line should not be indented
-`...........
+ // the next line should remain indented
+ `...........
...........
....●●●....
....●●●....