This commit is contained in:
Zachary Yedidia 2019-01-14 16:52:25 -05:00
parent eb49052a48
commit 224cbe5093
8 changed files with 90 additions and 45 deletions

View file

@ -967,6 +967,7 @@ func (h *BufHandler) ClearStatus() bool {
// ToggleHelp toggles the help screen
func (h *BufHandler) ToggleHelp() bool {
h.openHelp("help")
return true
}

View file

@ -1,6 +1,8 @@
package action
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
@ -274,8 +276,37 @@ func (h *BufHandler) ToggleLogCmd(args []string) {
func (h *BufHandler) ReloadCmd(args []string) {
}
func (h *BufHandler) openHelp(page string) error {
if data, err := config.FindRuntimeFile(config.RTHelp, page).Data(); err != nil {
return errors.New(fmt.Sprint("Unable to load help text", page, "\n", err))
} else {
helpBuffer := buffer.NewBufferFromString(string(data), page+".md", buffer.BTHelp)
helpBuffer.SetName("Help " + page)
if h.Buf.Type == buffer.BTHelp {
h.OpenBuffer(helpBuffer)
} else {
h.HSplitBuf(helpBuffer)
}
}
return nil
}
// HelpCmd tries to open the given help page in a horizontal split
func (h *BufHandler) HelpCmd(args []string) {
if len(args) < 1 {
// Open the default help if the user just typed "> help"
h.openHelp("help")
} else {
if config.FindRuntimeFile(config.RTHelp, args[0]) != nil {
err := h.openHelp(args[0])
if err != nil {
InfoBar.Error(err)
}
} else {
InfoBar.Error("Sorry, no help for ", args[0])
}
}
}
// VSplitCmd opens a vertical split with file given in the first argument

View file

@ -5,6 +5,7 @@ import (
"errors"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
@ -38,6 +39,25 @@ var (
ErrFileTooLarge = errors.New("File is too large to hash")
)
type SharedBuffer struct {
*LineArray
// Stores the last modification time of the file the buffer is pointing to
ModTime time.Time
// Type of the buffer (e.g. help, raw, scratch etc..)
Type BufType
isModified bool
}
func (b *SharedBuffer) insert(pos Loc, value []byte) {
b.isModified = true
b.LineArray.insert(pos, value)
}
func (b *SharedBuffer) remove(start, end Loc) []byte {
b.isModified = true
return b.LineArray.remove(start, end)
}
// Buffer stores the main information about a currently open file including
// the actual text (in a LineArray), the undo/redo stack (in an EventHandler)
// all the cursors, the syntax highlighting info, the settings for the buffer
@ -46,8 +66,8 @@ var (
// highlighter attaches information to each line of the buffer for optimization
// purposes so it doesn't have to rehighlight everything on every update.
type Buffer struct {
*LineArray
*EventHandler
*SharedBuffer
cursors []*Cursor
curCursor int
@ -60,9 +80,6 @@ type Buffer struct {
// Name of the buffer on the status line
name string
// Stores the last modification time of the file the buffer is pointing to
ModTime *time.Time
SyntaxDef *highlight.Def
Highlighter *highlight.Highlighter
@ -72,9 +89,6 @@ type Buffer struct {
// Settings customized by the user
Settings map[string]interface{}
// Type of the buffer (e.g. help, raw, scratch etc..)
Type BufType
Messages []*Message
}
@ -122,7 +136,6 @@ func NewBuffer(reader io.Reader, size int64, path string, cursorPosition []strin
absPath, _ := filepath.Abs(path)
b := new(Buffer)
b.Type = btype
b.Settings = config.DefaultLocalSettings()
for k, v := range config.GlobalSettings {
@ -137,28 +150,24 @@ func NewBuffer(reader io.Reader, size int64, path string, cursorPosition []strin
for _, buf := range OpenBuffers {
if buf.AbsPath == absPath {
found = true
b.LineArray = buf.LineArray
b.SharedBuffer = buf.SharedBuffer
b.EventHandler = buf.EventHandler
b.ModTime = buf.ModTime
b.isModified = buf.isModified
}
}
}
if !found {
b.SharedBuffer = new(SharedBuffer)
b.Type = btype
b.LineArray = NewLineArray(uint64(size), FFAuto, reader)
b.EventHandler = NewEventHandler(b.LineArray, b.cursors)
b.ModTime = new(time.Time)
b.isModified = new(bool)
*b.isModified = false
*b.ModTime = time.Time{}
b.EventHandler = NewEventHandler(b.SharedBuffer, b.cursors)
}
b.Path = path
b.AbsPath = absPath
// The last time this file was modified
*b.ModTime, _ = GetModTime(b.Path)
b.ModTime, _ = GetModTime(b.Path)
b.UpdateRules()
@ -219,6 +228,11 @@ func (b *Buffer) GetName() string {
return b.name
}
//SetName changes the name for this buffer
func (b *Buffer) SetName(s string) {
b.name = s
}
// FileType returns the buffer's filetype
func (b *Buffer) FileType() string {
return b.Settings["filetype"].(string)
@ -234,8 +248,8 @@ func (b *Buffer) ReOpen() error {
}
b.EventHandler.ApplyDiff(txt)
*b.ModTime, err = GetModTime(b.Path)
*b.isModified = false
b.ModTime, err = GetModTime(b.Path)
b.isModified = false
for _, c := range b.cursors {
c.Relocate()
}
@ -264,7 +278,7 @@ func (b *Buffer) RuneAt(loc Loc) rune {
// being opened
func (b *Buffer) Modified() bool {
if b.Settings["fastdirty"].(bool) {
return *b.isModified
return b.isModified
}
var buff [md5.Size]byte
@ -402,6 +416,7 @@ func (b *Buffer) SetCursors(c []*Cursor) {
func (b *Buffer) AddCursor(c *Cursor) {
b.cursors = append(b.cursors, c)
b.EventHandler.cursors = b.cursors
log.Println(b.cursors)
b.UpdateCursors()
}

View file

@ -1,6 +1,7 @@
package buffer
import (
"log"
"time"
"unicode/utf8"
@ -37,7 +38,7 @@ type Delta struct {
}
// ExecuteTextEvent runs a text event
func ExecuteTextEvent(t *TextEvent, buf *LineArray) {
func ExecuteTextEvent(t *TextEvent, buf *SharedBuffer) {
if t.EventType == TextEventInsert {
for _, d := range t.Deltas {
buf.insert(d.Start, d.Text)
@ -60,25 +61,25 @@ func ExecuteTextEvent(t *TextEvent, buf *LineArray) {
}
// UndoTextEvent undoes a text event
func UndoTextEvent(t *TextEvent, buf *LineArray) {
func UndoTextEvent(t *TextEvent, buf *SharedBuffer) {
t.EventType = -t.EventType
ExecuteTextEvent(t, buf)
}
// EventHandler executes text manipulations and allows undoing and redoing
type EventHandler struct {
buf *LineArray
buf *SharedBuffer
cursors []*Cursor
UndoStack *TEStack
RedoStack *TEStack
}
// NewEventHandler returns a new EventHandler
func NewEventHandler(la *LineArray, cursors []*Cursor) *EventHandler {
func NewEventHandler(buf *SharedBuffer, cursors []*Cursor) *EventHandler {
eh := new(EventHandler)
eh.UndoStack = new(TEStack)
eh.RedoStack = new(TEStack)
eh.buf = la
eh.buf = buf
eh.cursors = cursors
return eh
}
@ -93,12 +94,12 @@ func (eh *EventHandler) ApplyDiff(new string) {
loc := eh.buf.Start()
for _, d := range diff {
if d.Type == dmp.DiffDelete {
eh.Remove(loc, loc.MoveLA(utf8.RuneCountInString(d.Text), eh.buf))
eh.Remove(loc, loc.MoveLA(utf8.RuneCountInString(d.Text), eh.buf.LineArray))
} else {
if d.Type == dmp.DiffInsert {
eh.Insert(loc, d.Text)
}
loc = loc.MoveLA(utf8.RuneCountInString(d.Text), eh.buf)
loc = loc.MoveLA(utf8.RuneCountInString(d.Text), eh.buf.LineArray)
}
}
}
@ -113,15 +114,16 @@ func (eh *EventHandler) Insert(start Loc, textStr string) {
Time: time.Now(),
}
eh.Execute(e)
e.Deltas[0].End = start.MoveLA(utf8.RuneCount(text), eh.buf)
e.Deltas[0].End = start.MoveLA(utf8.RuneCount(text), eh.buf.LineArray)
end := e.Deltas[0].End
log.Println(eh.cursors)
for _, c := range eh.cursors {
move := func(loc Loc) Loc {
if start.Y != end.Y && loc.GreaterThan(start) {
loc.Y += end.Y - start.Y
} else if loc.Y == start.Y && loc.GreaterEqual(start) {
loc = loc.MoveLA(utf8.RuneCount(text), eh.buf)
loc = loc.MoveLA(utf8.RuneCount(text), eh.buf.LineArray)
}
return loc
}
@ -149,7 +151,7 @@ func (eh *EventHandler) Remove(start, end Loc) {
if start.Y != end.Y && loc.GreaterThan(end) {
loc.Y -= end.Y - start.Y
} else if loc.Y == end.Y && loc.GreaterEqual(end) {
loc = loc.MoveLA(-DiffLA(start, end, eh.buf), eh.buf)
loc = loc.MoveLA(-DiffLA(start, end, eh.buf.LineArray), eh.buf.LineArray)
}
return loc
}

View file

@ -52,10 +52,9 @@ type FileFormat byte
// A LineArray simply stores and array of lines and makes it easy to insert
// and delete in it
type LineArray struct {
lines []Line
endings FileFormat
initsize uint64
isModified *bool
lines []Line
endings FileFormat
initsize uint64
}
// Append efficiently appends lines together
@ -162,7 +161,6 @@ func (la *LineArray) newlineBelow(y int) {
// Inserts a byte array at a given location
func (la *LineArray) insert(pos Loc, value []byte) {
*la.isModified = true
x, y := runeToByteIndex(pos.X, la.lines[pos.Y].data), pos.Y
for i := 0; i < len(value); i++ {
if value[i] == '\n' {
@ -203,7 +201,6 @@ func (la *LineArray) split(pos Loc) {
// removes from start to end
func (la *LineArray) remove(start, end Loc) []byte {
*la.isModified = true
sub := la.Substr(start, end)
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
@ -222,7 +219,6 @@ func (la *LineArray) remove(start, end Loc) []byte {
// deleteToEnd deletes from the end of a line to the position
func (la *LineArray) deleteToEnd(pos Loc) {
*la.isModified = true
la.lines[pos.Y].data = la.lines[pos.Y].data[:pos.X]
}

View file

@ -73,7 +73,7 @@ func (b *Buffer) SaveAs(filename string) error {
// Update the last time this file was updated after saving
defer func() {
*b.ModTime, _ = GetModTime(filename)
b.ModTime, _ = GetModTime(filename)
}()
// Removes any tilde and replaces with the absolute path to home
@ -146,7 +146,7 @@ func (b *Buffer) SaveAs(filename string) error {
b.Path = filename
absPath, _ := filepath.Abs(filename)
b.AbsPath = absPath
*b.isModified = false
b.isModified = false
return b.Serialize()
}
@ -182,8 +182,8 @@ func (b *Buffer) SaveAsWithSudo(filename string) error {
err := cmd.Wait()
if err == nil {
*b.isModified = false
*b.ModTime, _ = GetModTime(filename)
b.isModified = false
b.ModTime, _ = GetModTime(filename)
return b.Serialize()
}
return err

View file

@ -36,7 +36,7 @@ func (b *Buffer) Serialize() error {
err := gob.NewEncoder(file).Encode(SerializedBuffer{
b.EventHandler,
b.GetActiveCursor().Loc,
*b.ModTime,
b.ModTime,
})
return err
})
@ -61,10 +61,10 @@ func (b *Buffer) Unserialize() error {
if b.Settings["saveundo"].(bool) {
// We should only use last time's eventhandler if the file wasn't modified by someone else in the meantime
if *b.ModTime == buffer.ModTime {
if b.ModTime == buffer.ModTime {
b.EventHandler = buffer.EventHandler
b.EventHandler.cursors = b.cursors
b.EventHandler.buf = b.LineArray
b.EventHandler.buf = b.SharedBuffer
}
}
}

View file

@ -30,7 +30,7 @@ func (b *Buffer) SetOption(option, value string) error {
} else if option == "filetype" {
b.UpdateRules()
} else if option == "fileformat" {
*b.isModified = true
b.isModified = true
} else if option == "syntax" {
if !nativeValue.(bool) {
b.ClearMatches()