1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
package dedent
import (
"bytes"
)
// String automatically detects the maximum indentation shared by all lines and
// trims them accordingly.
func String(s string) string {
indent := minIndent(s)
if indent == 0 {
return s
}
return dedent(s, indent)
}
func minIndent(s string) int {
var (
curIndent int
minIndent int
shouldAppend = true
)
for i := 0; i < len(s); i++ {
switch s[i] {
case ' ', '\t':
if shouldAppend {
curIndent++
}
case '\n':
curIndent = 0
shouldAppend = true
default:
if curIndent > 0 && (minIndent == 0 || curIndent < minIndent) {
minIndent = curIndent
curIndent = 0
}
shouldAppend = false
}
}
return minIndent
}
func dedent(s string, indent int) string {
var (
omitted int
shouldOmit = true
buf bytes.Buffer
)
for i := 0; i < len(s); i++ {
switch s[i] {
case ' ', '\t':
if shouldOmit {
if omitted < indent {
omitted++
continue
}
shouldOmit = false
}
_ = buf.WriteByte(s[i])
case '\n':
omitted = 0
shouldOmit = true
_ = buf.WriteByte(s[i])
default:
_ = buf.WriteByte(s[i])
}
}
return buf.String()
}
|