import (
"bufio"
- "bytes"
"io"
"unicode/utf8"
"github.com/zyedidia/micro/cmd/micro/highlight"
)
-func lineCounter(r io.Reader) (int, error) {
- buf := make([]byte, 32*1024)
- count := 0
- lineSep := []byte{'\n'}
-
- for {
- c, err := r.Read(buf)
- count += bytes.Count(buf[:c], lineSep)
-
- switch {
- case err == io.EOF:
- return count, nil
-
- case err != nil:
- return count, err
- }
- }
-}
-
func runeToByteIndex(n int, txt []byte) int {
if n == 0 {
return 0
return count
}
+// A Line contains the data in bytes as well as a highlight state, match
+// and a flag for whether the highlighting needs to be updated
type Line struct {
data []byte
lines []Line
}
+// Append efficiently appends lines together
+// It allocates an additional 10000 lines if the original estimate
+// is incorrect
func Append(slice []Line, data ...Line) []Line {
l := len(slice)
if l+len(data) > cap(slice) { // reallocate
- // Allocate double what's needed, for future growth.
newSlice := make([]Line, (l+len(data))+10000)
// The copy function is predeclared and works for any slice type.
copy(newSlice, slice)
n := 0
for {
data, err := br.ReadBytes('\n')
+ if len(data) > 1 && data[len(data)-2] == '\r' {
+ data = append(data[:len(data)-2], '\n')
+ if fileformat == 0 {
+ fileformat = 2
+ }
+ } else if len(data) > 0 {
+ if fileformat == 0 {
+ fileformat = 1
+ }
+ }
if n >= 1000 && loaded >= 0 {
totalLinesNum := int(float64(size) * (float64(n) / float64(loaded)))
newSlice := make([]Line, len(la.lines), totalLinesNum+10000)
- // The copy function is predeclared and works for any slice type.
copy(newSlice, la.lines)
la.lines = newSlice
loaded = -1
if err != nil {
if err == io.EOF {
- la.lines = Append(la.lines, Line{data[:len(data)], nil, nil, false})
+ la.lines = Append(la.lines, Line{data[:], nil, nil, false})
// la.lines = Append(la.lines, Line{data[:len(data)]})
}
// Last line was read
return str
}
+// SaveString returns the string that should be written to disk when
+// the line array is saved
+// It is the same as string but uses crlf or lf line endings depending
+func (la *LineArray) SaveString(useCrlf bool) string {
+ str := ""
+ for i, l := range la.lines {
+ str += string(l.data)
+ if i != len(la.lines)-1 {
+ if useCrlf {
+ str += "\r"
+ }
+ str += "\n"
+ }
+ }
+ return str
+}
+
// NewlineBelow adds a newline below the given line number
func (la *LineArray) NewlineBelow(y int) {
- la.lines = append(la.lines, Line{[]byte(" "), nil, nil, false})
+ la.lines = append(la.lines, Line{[]byte{' '}, nil, nil, false})
copy(la.lines[y+2:], la.lines[y+1:])
- la.lines[y+1] = Line{[]byte(""), la.lines[y].state, nil, false}
+ la.lines[y+1] = Line{[]byte{}, la.lines[y].state, nil, false}
}
// inserts a byte array at a given location
return str
}
+// State gets the highlight state for the given line number
func (la *LineArray) State(lineN int) highlight.State {
return la.lines[lineN].state
}
+// SetState sets the highlight state at the given line number
func (la *LineArray) SetState(lineN int, s highlight.State) {
la.lines[lineN].state = s
}
+// SetMatch sets the match at the given line number
func (la *LineArray) SetMatch(lineN int, m highlight.LineMatch) {
la.lines[lineN].match = m
}
+// Match retrieves the match for the given line number
func (la *LineArray) Match(lineN int) highlight.LineMatch {
return la.lines[lineN].match
}