Add help
This commit is contained in:
parent
eb49052a48
commit
224cbe5093
8 changed files with 90 additions and 45 deletions
|
@ -967,6 +967,7 @@ func (h *BufHandler) ClearStatus() bool {
|
|||
|
||||
// ToggleHelp toggles the help screen
|
||||
func (h *BufHandler) ToggleHelp() bool {
|
||||
h.openHelp("help")
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue