Use io.Readers to read files more efficiently

This commit is contained in:
Zachary Yedidia 2016-11-29 13:44:30 -05:00
parent d13f9602ff
commit eeaac76f5f
9 changed files with 57 additions and 35 deletions

View file

@ -1469,7 +1469,7 @@ func (v *View) AddTab(usePlugin bool) bool {
return false
}
tab := NewTabFromView(NewView(NewBuffer([]byte{}, "")))
tab := NewTabFromView(NewView(NewBuffer(strings.NewReader(""), "")))
tab.SetNum(len(tabs))
tabs = append(tabs, tab)
curTab++
@ -1529,7 +1529,7 @@ func (v *View) VSplitBinding(usePlugin bool) bool {
return false
}
v.VSplit(NewBuffer([]byte{}, ""))
v.VSplit(NewBuffer(strings.NewReader(""), ""))
if usePlugin {
return PostActionCall("VSplit", v)
@ -1543,7 +1543,7 @@ func (v *View) HSplitBinding(usePlugin bool) bool {
return false
}
v.HSplit(NewBuffer([]byte{}, ""))
v.HSplit(NewBuffer(strings.NewReader(""), ""))
if usePlugin {
return PostActionCall("HSplit", v)

View file

@ -3,6 +3,7 @@ package main
import (
"bytes"
"encoding/gob"
"io"
"io/ioutil"
"os"
"os/exec"
@ -55,8 +56,12 @@ type SerializedBuffer struct {
ModTime time.Time
}
// NewBuffer creates a new buffer from `txt` with path and name `path`
func NewBuffer(txt []byte, path string) *Buffer {
func NewBufferFromString(text, path string) *Buffer {
return NewBuffer(strings.NewReader(text), path)
}
// NewBuffer creates a new buffer from a given reader with a given path
func NewBuffer(reader io.Reader, path string) *Buffer {
if path != "" {
for _, tab := range tabs {
for _, view := range tab.views {
@ -68,7 +73,7 @@ func NewBuffer(txt []byte, path string) *Buffer {
}
b := new(Buffer)
b.LineArray = NewLineArray(txt)
b.LineArray = NewLineArray(reader)
b.Settings = DefaultLocalSettings()
for k, v := range globalSettings {
@ -166,6 +171,9 @@ func NewBuffer(txt []byte, path string) *Buffer {
func (b *Buffer) GetName() string {
if b.name == "" {
if b.Path == "" {
return "No name"
}
return b.Path
}
return b.name

View file

@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"os/signal"
@ -266,17 +265,18 @@ func Help(args []string) {
// If no file is given, it opens an empty buffer in a new split
func VSplit(args []string) {
if len(args) == 0 {
CurView().VSplit(NewBuffer([]byte{}, ""))
CurView().VSplit(NewBuffer(strings.NewReader(""), ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := ioutil.ReadFile(filename)
file, err := os.Open(filename)
defer file.Close()
var buf *Buffer
if err != nil {
// File does not exist -- create an empty buffer with that name
buf = NewBuffer([]byte{}, filename)
buf = NewBuffer(strings.NewReader(""), filename)
} else {
buf = NewBuffer(file, filename)
}
@ -288,17 +288,18 @@ func VSplit(args []string) {
// If no file is given, it opens an empty buffer in a new split
func HSplit(args []string) {
if len(args) == 0 {
CurView().HSplit(NewBuffer([]byte{}, ""))
CurView().HSplit(NewBuffer(strings.NewReader(""), ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := ioutil.ReadFile(filename)
file, err := os.Open(filename)
defer file.Close()
var buf *Buffer
if err != nil {
// File does not exist -- create an empty buffer with that name
buf = NewBuffer([]byte{}, filename)
buf = NewBuffer(strings.NewReader(""), filename)
} else {
buf = NewBuffer(file, filename)
}
@ -326,7 +327,8 @@ func NewTab(args []string) {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, _ := ioutil.ReadFile(filename)
file, _ := os.Open(filename)
defer file.Close()
tab := NewTabFromView(NewView(NewBuffer(file, filename)))
tab.SetNum(len(tabs))

View file

@ -1,7 +1,9 @@
package main
import (
"bufio"
"bytes"
"io"
"unicode/utf8"
)
@ -33,14 +35,23 @@ type LineArray struct {
}
// NewLineArray returns a new line array from an array of bytes
func NewLineArray(text []byte) *LineArray {
func NewLineArray(reader io.Reader) *LineArray {
la := new(LineArray)
// Split the bytes into lines
split := bytes.Split(text, []byte("\n"))
la.lines = make([][]byte, len(split))
for i := range split {
la.lines[i] = make([]byte, len(split[i]))
copy(la.lines[i], split[i])
br := bufio.NewReader(reader)
i := 0
for {
data, err := br.ReadBytes('\n')
if err != nil {
if err == io.EOF {
la.lines = append(la.lines, data[:len(data)])
}
// Last line was read
break
} else {
la.lines = append(la.lines, data[:len(data)-1])
}
i++
}
return la

View file

@ -6,6 +6,7 @@ import (
"fmt"
"os"
"strconv"
"strings"
"github.com/zyedidia/clipboard"
"github.com/zyedidia/tcell"
@ -78,7 +79,7 @@ func (m *Messenger) AddLog(msg string) {
func (m *Messenger) getBuffer() *Buffer {
if m.log == nil {
m.log = NewBuffer([]byte{}, "")
m.log = NewBuffer(strings.NewReader(""), "")
m.log.name = "Log"
}
return m.log

View file

@ -93,9 +93,11 @@ func LoadInput() []*Buffer {
filename = flag.Args()[i]
// Check that the file exists
var input *os.File
if _, e := os.Stat(filename); e == nil {
// If it exists we load it into a buffer
input, err = ioutil.ReadFile(filename)
input, err = os.Open(filename)
defer input.Close()
if err != nil {
TermMessage(err)
continue
@ -103,6 +105,7 @@ func LoadInput() []*Buffer {
}
// If the file didn't exist, input will be empty, and we'll open an empty buffer
buffers = append(buffers, NewBuffer(input, filename))
fmt.Print("\a")
}
} else if !isatty.IsTerminal(os.Stdin.Fd()) {
// Option 2
@ -113,10 +116,10 @@ func LoadInput() []*Buffer {
TermMessage("Error reading from stdin: ", err)
input = []byte{}
}
buffers = append(buffers, NewBuffer(input, filename))
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
} else {
// Option 3, just open an empty buffer
buffers = append(buffers, NewBuffer(input, filename))
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
}
return buffers
@ -335,7 +338,7 @@ func main() {
L.SetGlobal("HandleShellCommand", luar.New(L, HandleShellCommand))
L.SetGlobal("GetLeadingWhitespace", luar.New(L, GetLeadingWhitespace))
L.SetGlobal("MakeCompletion", luar.New(L, MakeCompletion))
L.SetGlobal("NewBuffer", luar.New(L, NewBuffer))
L.SetGlobal("NewBuffer", luar.New(L, NewBufferFromString))
L.SetGlobal("RuneStr", luar.New(L, func(r rune) string {
return string(r)
}))
@ -404,6 +407,7 @@ func main() {
}()
for {
fmt.Print("\a")
// Display everything
RedrawAll()

View file

@ -18,9 +18,6 @@ func (sline *Statusline) Display() {
y := sline.view.Height + sline.view.y
file := sline.view.Buf.GetName()
if file == "" {
file = "No name"
}
// If the buffer is dirty (has been modified) write a little '+'
if sline.view.Buf.IsModified {

View file

@ -13,8 +13,6 @@ type Tab struct {
views []*View
// This is the current view for this tab
CurView int
// Generally this is the name of the current view's buffer
name string
tree *SplitTree
}

View file

@ -1,7 +1,7 @@
package main
import (
"io/ioutil"
"os"
"strconv"
"strings"
"time"
@ -242,13 +242,14 @@ func (v *View) OpenBuffer(buf *Buffer) {
func (v *View) Open(filename string) {
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
file, err := ioutil.ReadFile(filename)
file, err := os.Open(filename)
defer file.Close()
var buf *Buffer
if err != nil {
messenger.Message(err.Error())
// File does not exist -- create an empty buffer with that name
buf = NewBuffer([]byte{}, filename)
buf = NewBuffer(strings.NewReader(""), filename)
} else {
buf = NewBuffer(file, filename)
}
@ -630,7 +631,7 @@ func (v *View) openHelp(helpPage string) {
if data, err := FindRuntimeFile(RTHelp, helpPage).Data(); err != nil {
TermMessage("Unable to load help text", helpPage, "\n", err)
} else {
helpBuffer := NewBuffer(data, helpPage+".md")
helpBuffer := NewBuffer(strings.NewReader(string(data)), helpPage+".md")
helpBuffer.name = "Help"
if v.Type == vtHelp {