Do not process ANSI codes in --preview output at once

Close #598
pull/601/head
Junegunn Choi 8 years ago
parent c39c039e15
commit 24e1fabf2e
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -36,7 +36,7 @@ func init() {
ansiRegex = regexp.MustCompile("\x1b\\[[0-9;]*[mK]") ansiRegex = regexp.MustCompile("\x1b\\[[0-9;]*[mK]")
} }
func extractColor(str string, state *ansiState) (string, []ansiOffset, *ansiState) { func extractColor(str string, state *ansiState, proc func(string, *ansiState) bool) (string, []ansiOffset, *ansiState) {
var offsets []ansiOffset var offsets []ansiOffset
var output bytes.Buffer var output bytes.Buffer
@ -46,7 +46,11 @@ func extractColor(str string, state *ansiState) (string, []ansiOffset, *ansiStat
idx := 0 idx := 0
for _, offset := range ansiRegex.FindAllStringIndex(str, -1) { for _, offset := range ansiRegex.FindAllStringIndex(str, -1) {
output.WriteString(str[idx:offset[0]]) prev := str[idx:offset[0]]
output.WriteString(prev)
if proc != nil && !proc(prev, state) {
break
}
newState := interpretCode(str[offset[0]:offset[1]], state) newState := interpretCode(str[offset[0]:offset[1]], state)
if !newState.equals(state) { if !newState.equals(state) {
@ -77,6 +81,9 @@ func extractColor(str string, state *ansiState) (string, []ansiOffset, *ansiStat
(&offsets[len(offsets)-1]).offset[1] = int32(utf8.RuneCount(output.Bytes())) (&offsets[len(offsets)-1]).offset[1] = int32(utf8.RuneCount(output.Bytes()))
} }
} }
if proc != nil {
proc(rest, state)
}
return output.String(), offsets, state return output.String(), offsets, state
} }

@ -17,7 +17,7 @@ func TestExtractColor(t *testing.T) {
var state *ansiState var state *ansiState
clean := "\x1b[0m" clean := "\x1b[0m"
check := func(assertion func(ansiOffsets []ansiOffset, state *ansiState)) { check := func(assertion func(ansiOffsets []ansiOffset, state *ansiState)) {
output, ansiOffsets, newState := extractColor(src, state) output, ansiOffsets, newState := extractColor(src, state, nil)
state = newState state = newState
if output != "hello world" { if output != "hello world" {
t.Errorf("Invalid output: {}", output) t.Errorf("Invalid output: {}", output)

@ -73,7 +73,7 @@ func Run(opts *Options) {
if opts.Theme != nil { if opts.Theme != nil {
var state *ansiState var state *ansiState
ansiProcessor = func(data []byte) ([]rune, []ansiOffset) { ansiProcessor = func(data []byte) ([]rune, []ansiOffset) {
trimmed, offsets, newState := extractColor(string(data), state) trimmed, offsets, newState := extractColor(string(data), state, nil)
state = newState state = newState
return []rune(trimmed), offsets return []rune(trimmed), offsets
} }
@ -81,7 +81,7 @@ func Run(opts *Options) {
// When color is disabled but ansi option is given, // When color is disabled but ansi option is given,
// we simply strip out ANSI codes from the input // we simply strip out ANSI codes from the input
ansiProcessor = func(data []byte) ([]rune, []ansiOffset) { ansiProcessor = func(data []byte) ([]rune, []ansiOffset) {
trimmed, _, _ := extractColor(string(data), nil) trimmed, _, _ := extractColor(string(data), nil, nil)
return []rune(trimmed), nil return []rune(trimmed), nil
} }
} }

@ -128,7 +128,7 @@ func (item *Item) AsString(stripAnsi bool) string {
func (item *Item) StringPtr(stripAnsi bool) *string { func (item *Item) StringPtr(stripAnsi bool) *string {
if item.origText != nil { if item.origText != nil {
if stripAnsi { if stripAnsi {
trimmed, _, _ := extractColor(string(*item.origText), nil) trimmed, _, _ := extractColor(string(*item.origText), nil, nil)
return &trimmed return &trimmed
} }
orig := string(*item.origText) orig := string(*item.origText)

@ -556,7 +556,7 @@ func (t *Terminal) printHeader() {
if line >= max { if line >= max {
continue continue
} }
trimmed, colors, newState := extractColor(lineStr, state) trimmed, colors, newState := extractColor(lineStr, state, nil)
state = newState state = newState
item := &Item{ item := &Item{
text: []rune(trimmed), text: []rune(trimmed),
@ -730,25 +730,13 @@ func (t *Terminal) printHighlighted(item *Item, bold bool, col1 int, col2 int, c
} }
func (t *Terminal) printPreview() { func (t *Terminal) printPreview() {
trimmed, ansiOffsets, _ := extractColor(t.previewTxt, nil)
var index int32
t.pwindow.Erase() t.pwindow.Erase()
for _, o := range ansiOffsets { extractColor(t.previewTxt, nil, func(str string, ansi *ansiState) bool {
b := o.offset[0] if ansi != nil && ansi.colored() {
e := o.offset[1] return t.pwindow.CFill(str, ansi.fg, ansi.bg, ansi.bold)
if b > index {
if !t.pwindow.Fill(trimmed[index:b]) {
return
}
}
if !t.pwindow.CFill(trimmed[b:e], o.color.fg, o.color.bg, o.color.bold) {
return
} }
index = e return t.pwindow.Fill(str)
} })
if int(index) < len(trimmed) {
t.pwindow.Fill(trimmed[index:])
}
} }
func processTabs(runes []rune, prefixWidth int) (string, int) { func processTabs(runes []rune, prefixWidth int) (string, int) {

Loading…
Cancel
Save