mirror of
https://github.com/zyedidia/micro.git
synced 2026-02-08 16:10:29 +09:00
Store cursor and eventhandler in buffer instead of view
This is better design because the cursor and eventhandler are things the buffer should know about directly but the view shouldn't. This should make it easier to add persistent undo or location saving between sessions (see #107).
This commit is contained in:
@@ -506,7 +506,7 @@ func (v *View) InsertSpace() bool {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
v.eh.Insert(v.Cursor.Loc(), " ")
|
||||
v.Buf.Insert(v.Cursor.Loc(), " ")
|
||||
v.Cursor.Right()
|
||||
return true
|
||||
}
|
||||
@@ -519,12 +519,12 @@ func (v *View) InsertEnter() bool {
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
|
||||
v.eh.Insert(v.Cursor.Loc(), "\n")
|
||||
v.Buf.Insert(v.Cursor.Loc(), "\n")
|
||||
ws := GetLeadingWhitespace(v.Buf.Lines[v.Cursor.y])
|
||||
v.Cursor.Right()
|
||||
|
||||
if settings["autoindent"].(bool) {
|
||||
v.eh.Insert(v.Cursor.Loc(), ws)
|
||||
v.Buf.Insert(v.Cursor.Loc(), ws)
|
||||
for i := 0; i < len(ws); i++ {
|
||||
v.Cursor.Right()
|
||||
}
|
||||
@@ -556,14 +556,14 @@ func (v *View) Backspace() bool {
|
||||
v.Cursor.SetLoc(loc - tabSize)
|
||||
cx, cy := v.Cursor.x, v.Cursor.y
|
||||
v.Cursor.SetLoc(loc)
|
||||
v.eh.Remove(loc-tabSize, loc)
|
||||
v.Buf.Remove(loc-tabSize, loc)
|
||||
v.Cursor.x, v.Cursor.y = cx, cy
|
||||
} else {
|
||||
v.Cursor.Left()
|
||||
cx, cy := v.Cursor.x, v.Cursor.y
|
||||
v.Cursor.Right()
|
||||
loc := v.Cursor.Loc()
|
||||
v.eh.Remove(loc-1, loc)
|
||||
v.Buf.Remove(loc-1, loc)
|
||||
v.Cursor.x, v.Cursor.y = cx, cy
|
||||
}
|
||||
}
|
||||
@@ -579,7 +579,7 @@ func (v *View) Delete() bool {
|
||||
} else {
|
||||
loc := v.Cursor.Loc()
|
||||
if loc < v.Buf.Len() {
|
||||
v.eh.Remove(loc, loc+1)
|
||||
v.Buf.Remove(loc, loc+1)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -594,12 +594,12 @@ func (v *View) InsertTab() bool {
|
||||
}
|
||||
if settings["tabsToSpaces"].(bool) {
|
||||
tabSize := int(settings["tabsize"].(float64))
|
||||
v.eh.Insert(v.Cursor.Loc(), Spaces(tabSize))
|
||||
v.Buf.Insert(v.Cursor.Loc(), Spaces(tabSize))
|
||||
for i := 0; i < tabSize; i++ {
|
||||
v.Cursor.Right()
|
||||
}
|
||||
} else {
|
||||
v.eh.Insert(v.Cursor.Loc(), "\t")
|
||||
v.Buf.Insert(v.Cursor.Loc(), "\t")
|
||||
v.Cursor.Right()
|
||||
}
|
||||
return true
|
||||
@@ -663,14 +663,14 @@ func (v *View) FindPrevious() bool {
|
||||
|
||||
// Undo undoes the last action
|
||||
func (v *View) Undo() bool {
|
||||
v.eh.Undo()
|
||||
v.Buf.Undo()
|
||||
messenger.Message("Undid action")
|
||||
return true
|
||||
}
|
||||
|
||||
// Redo redoes the last action
|
||||
func (v *View) Redo() bool {
|
||||
v.eh.Redo()
|
||||
v.Buf.Redo()
|
||||
messenger.Message("Redid action")
|
||||
return true
|
||||
}
|
||||
@@ -722,7 +722,7 @@ func (v *View) Cut() bool {
|
||||
// DuplicateLine duplicates the current line
|
||||
func (v *View) DuplicateLine() bool {
|
||||
v.Cursor.End()
|
||||
v.eh.Insert(v.Cursor.Loc(), "\n"+v.Buf.Lines[v.Cursor.y])
|
||||
v.Buf.Insert(v.Cursor.Loc(), "\n"+v.Buf.Lines[v.Cursor.y])
|
||||
v.Cursor.Right()
|
||||
messenger.Message("Duplicated line")
|
||||
return true
|
||||
@@ -736,7 +736,7 @@ func (v *View) Paste() bool {
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
clip, _ := clipboard.ReadAll()
|
||||
v.eh.Insert(v.Cursor.Loc(), clip)
|
||||
v.Buf.Insert(v.Cursor.Loc(), clip)
|
||||
v.Cursor.SetLoc(v.Cursor.Loc() + Count(clip))
|
||||
v.freshClip = false
|
||||
messenger.Message("Pasted clipboard")
|
||||
|
||||
@@ -10,9 +10,14 @@ import (
|
||||
// It uses a rope to efficiently store the string and contains some
|
||||
// simple functions for saving and wrapper functions for modifying the rope
|
||||
type Buffer struct {
|
||||
// The eventhandler for undo/redo
|
||||
*EventHandler
|
||||
|
||||
// Stores the text of the buffer
|
||||
r *rope.Rope
|
||||
|
||||
Cursor Cursor
|
||||
|
||||
// Path to the file on disk
|
||||
Path string
|
||||
// Name of the buffer on the status line
|
||||
@@ -43,6 +48,15 @@ func NewBuffer(txt, path string) *Buffer {
|
||||
b.Path = path
|
||||
b.Name = path
|
||||
|
||||
// Put the cursor at the first spot
|
||||
b.Cursor = Cursor{
|
||||
x: 0,
|
||||
y: 0,
|
||||
Buf: b,
|
||||
}
|
||||
|
||||
b.EventHandler = NewEventHandler(b)
|
||||
|
||||
b.Update()
|
||||
b.UpdateRules()
|
||||
|
||||
@@ -84,8 +98,8 @@ func (b *Buffer) SaveAs(filename string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Insert a string into the rope
|
||||
func (b *Buffer) Insert(idx int, value string) {
|
||||
// This directly inserts value at idx, bypassing all undo/redo
|
||||
func (b *Buffer) insert(idx int, value string) {
|
||||
b.IsModified = true
|
||||
b.r = b.r.Insert(idx, value)
|
||||
b.Update()
|
||||
@@ -93,7 +107,8 @@ func (b *Buffer) Insert(idx int, value string) {
|
||||
|
||||
// Remove a slice of the rope from start to end (exclusive)
|
||||
// Returns the string that was removed
|
||||
func (b *Buffer) Remove(start, end int) string {
|
||||
// This directly removes from start to end from the buffer, bypassing all undo/redo
|
||||
func (b *Buffer) remove(start, end int) string {
|
||||
b.IsModified = true
|
||||
if start < 0 {
|
||||
start = 0
|
||||
|
||||
@@ -162,7 +162,7 @@ func HandleCommand(input string, view *View) {
|
||||
}
|
||||
if choice {
|
||||
view.Cursor.DeleteSelection()
|
||||
view.eh.Insert(match[0], replace)
|
||||
view.Buf.Insert(match[0], replace)
|
||||
view.Cursor.ResetSelection()
|
||||
messenger.Reset()
|
||||
} else {
|
||||
@@ -174,7 +174,7 @@ func HandleCommand(input string, view *View) {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
view.eh.Replace(match[0], match[1], replace)
|
||||
view.Buf.Replace(match[0], match[1], replace)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
|
||||
@@ -43,7 +43,7 @@ func ToCharPos(x, y int, buf *Buffer) int {
|
||||
// is also simpler to use character indicies for other tasks such as
|
||||
// selection.
|
||||
type Cursor struct {
|
||||
v *View
|
||||
Buf *Buffer
|
||||
|
||||
// The cursor display location
|
||||
x int
|
||||
@@ -64,7 +64,7 @@ type Cursor struct {
|
||||
// and not x, y location
|
||||
// It's just a simple wrapper of FromCharPos
|
||||
func (c *Cursor) SetLoc(loc int) {
|
||||
c.x, c.y = FromCharPos(loc, c.v.Buf)
|
||||
c.x, c.y = FromCharPos(loc, c.Buf)
|
||||
c.lastVisualX = c.GetVisualX()
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func (c *Cursor) SetLoc(loc int) {
|
||||
// of x, y location
|
||||
// It's just a simple wrapper of ToCharPos
|
||||
func (c *Cursor) Loc() int {
|
||||
return ToCharPos(c.x, c.y, c.v.Buf)
|
||||
return ToCharPos(c.x, c.y, c.Buf)
|
||||
}
|
||||
|
||||
// ResetSelection resets the user's selection
|
||||
@@ -89,12 +89,12 @@ func (c *Cursor) HasSelection() bool {
|
||||
// DeleteSelection deletes the currently selected text
|
||||
func (c *Cursor) DeleteSelection() {
|
||||
if c.curSelection[0] > c.curSelection[1] {
|
||||
c.v.eh.Remove(c.curSelection[1], c.curSelection[0])
|
||||
c.Buf.Remove(c.curSelection[1], c.curSelection[0])
|
||||
c.SetLoc(c.curSelection[1])
|
||||
} else if c.GetSelection() == "" {
|
||||
return
|
||||
} else {
|
||||
c.v.eh.Remove(c.curSelection[0], c.curSelection[1])
|
||||
c.Buf.Remove(c.curSelection[0], c.curSelection[1])
|
||||
c.SetLoc(c.curSelection[0])
|
||||
}
|
||||
}
|
||||
@@ -102,9 +102,9 @@ func (c *Cursor) DeleteSelection() {
|
||||
// GetSelection returns the cursor's selection
|
||||
func (c *Cursor) GetSelection() string {
|
||||
if c.curSelection[0] > c.curSelection[1] {
|
||||
return c.v.Buf.Substr(c.curSelection[1], c.curSelection[0])
|
||||
return c.Buf.Substr(c.curSelection[1], c.curSelection[0])
|
||||
}
|
||||
return c.v.Buf.Substr(c.curSelection[0], c.curSelection[1])
|
||||
return c.Buf.Substr(c.curSelection[0], c.curSelection[1])
|
||||
}
|
||||
|
||||
// SelectLine selects the current line
|
||||
@@ -112,7 +112,7 @@ func (c *Cursor) SelectLine() {
|
||||
c.Start()
|
||||
c.curSelection[0] = c.Loc()
|
||||
c.End()
|
||||
if c.v.Buf.NumLines-1 > c.y {
|
||||
if c.Buf.NumLines-1 > c.y {
|
||||
c.curSelection[1] = c.Loc() + 1
|
||||
} else {
|
||||
c.curSelection[1] = c.Loc()
|
||||
@@ -143,7 +143,7 @@ func (c *Cursor) AddLineToSelection() {
|
||||
|
||||
// SelectWord selects the word the cursor is currently on
|
||||
func (c *Cursor) SelectWord() {
|
||||
if len(c.v.Buf.Lines[c.y]) == 0 {
|
||||
if len(c.Buf.Lines[c.y]) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -161,14 +161,14 @@ func (c *Cursor) SelectWord() {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.v.Buf)
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.Buf)
|
||||
c.origSelection[0] = c.curSelection[0]
|
||||
|
||||
for forward < Count(c.v.Buf.Lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
for forward < Count(c.Buf.Lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.v.Buf) + 1
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.Buf) + 1
|
||||
c.origSelection[1] = c.curSelection[1]
|
||||
c.SetLoc(c.curSelection[1])
|
||||
}
|
||||
@@ -189,18 +189,18 @@ func (c *Cursor) AddWordToSelection() {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.v.Buf)
|
||||
c.curSelection[0] = ToCharPos(backward, c.y, c.Buf)
|
||||
c.curSelection[1] = c.origSelection[1]
|
||||
}
|
||||
|
||||
if loc > c.origSelection[1] {
|
||||
forward := c.x
|
||||
|
||||
for forward < Count(c.v.Buf.Lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
for forward < Count(c.Buf.Lines[c.y])-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.v.Buf) + 1
|
||||
c.curSelection[1] = ToCharPos(forward, c.y, c.Buf) + 1
|
||||
c.curSelection[0] = c.origSelection[0]
|
||||
}
|
||||
|
||||
@@ -222,13 +222,13 @@ func (c *Cursor) SelectTo(loc int) {
|
||||
func (c *Cursor) WordRight() {
|
||||
c.Right()
|
||||
for IsWhitespace(c.RuneUnder(c.x)) {
|
||||
if c.x == Count(c.v.Buf.Lines[c.y]) {
|
||||
if c.x == Count(c.Buf.Lines[c.y]) {
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
}
|
||||
for !IsWhitespace(c.RuneUnder(c.x)) {
|
||||
if c.x == Count(c.v.Buf.Lines[c.y]) {
|
||||
if c.x == Count(c.Buf.Lines[c.y]) {
|
||||
return
|
||||
}
|
||||
c.Right()
|
||||
@@ -255,7 +255,7 @@ func (c *Cursor) WordLeft() {
|
||||
|
||||
// RuneUnder returns the rune under the given x position
|
||||
func (c *Cursor) RuneUnder(x int) rune {
|
||||
line := []rune(c.v.Buf.Lines[c.y])
|
||||
line := []rune(c.Buf.Lines[c.y])
|
||||
if len(line) == 0 {
|
||||
return '\n'
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (c *Cursor) Up() {
|
||||
if c.y > 0 {
|
||||
c.y--
|
||||
|
||||
runes := []rune(c.v.Buf.Lines[c.y])
|
||||
runes := []rune(c.Buf.Lines[c.y])
|
||||
c.x = c.GetCharPosInLine(c.y, c.lastVisualX)
|
||||
if c.x > len(runes) {
|
||||
c.x = len(runes)
|
||||
@@ -282,10 +282,10 @@ func (c *Cursor) Up() {
|
||||
|
||||
// Down moves the cursor down one line (if possible)
|
||||
func (c *Cursor) Down() {
|
||||
if c.y < c.v.Buf.NumLines-1 {
|
||||
if c.y < c.Buf.NumLines-1 {
|
||||
c.y++
|
||||
|
||||
runes := []rune(c.v.Buf.Lines[c.y])
|
||||
runes := []rune(c.Buf.Lines[c.y])
|
||||
c.x = c.GetCharPosInLine(c.y, c.lastVisualX)
|
||||
if c.x > len(runes) {
|
||||
c.x = len(runes)
|
||||
@@ -309,10 +309,10 @@ func (c *Cursor) Left() {
|
||||
|
||||
// Right moves the cursor right one cell (if possible) or to the next line if it is at the end
|
||||
func (c *Cursor) Right() {
|
||||
if c.Loc() == c.v.Buf.Len() {
|
||||
if c.Loc() == c.Buf.Len() {
|
||||
return
|
||||
}
|
||||
if c.x < Count(c.v.Buf.Lines[c.y]) {
|
||||
if c.x < Count(c.Buf.Lines[c.y]) {
|
||||
c.x++
|
||||
} else {
|
||||
c.Down()
|
||||
@@ -323,7 +323,7 @@ func (c *Cursor) Right() {
|
||||
|
||||
// End moves the cursor to the end of the line it is on
|
||||
func (c *Cursor) End() {
|
||||
c.x = Count(c.v.Buf.Lines[c.y])
|
||||
c.x = Count(c.Buf.Lines[c.y])
|
||||
c.lastVisualX = c.GetVisualX()
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int {
|
||||
// Get the tab size
|
||||
tabSize := int(settings["tabsize"].(float64))
|
||||
// This is the visual line -- every \t replaced with the correct number of spaces
|
||||
visualLine := strings.Replace(c.v.Buf.Lines[lineNum], "\t", "\t"+Spaces(tabSize-1), -1)
|
||||
visualLine := strings.Replace(c.Buf.Lines[lineNum], "\t", "\t"+Spaces(tabSize-1), -1)
|
||||
if visualPos > Count(visualLine) {
|
||||
visualPos = Count(visualLine)
|
||||
}
|
||||
@@ -351,7 +351,7 @@ func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int {
|
||||
|
||||
// GetVisualX returns the x value of the cursor in visual spaces
|
||||
func (c *Cursor) GetVisualX() int {
|
||||
runes := []rune(c.v.Buf.Lines[c.y])
|
||||
runes := []rune(c.Buf.Lines[c.y])
|
||||
tabSize := int(settings["tabsize"].(float64))
|
||||
return c.x + NumOccurences(string(runes[:c.x]), '\t')*(tabSize-1)
|
||||
}
|
||||
@@ -361,23 +361,13 @@ func (c *Cursor) GetVisualX() int {
|
||||
func (c *Cursor) Relocate() {
|
||||
if c.y < 0 {
|
||||
c.y = 0
|
||||
} else if c.y >= c.v.Buf.NumLines {
|
||||
c.y = c.v.Buf.NumLines - 1
|
||||
} else if c.y >= c.Buf.NumLines {
|
||||
c.y = c.Buf.NumLines - 1
|
||||
}
|
||||
|
||||
if c.x < 0 {
|
||||
c.x = 0
|
||||
} else if c.x > Count(c.v.Buf.Lines[c.y]) {
|
||||
c.x = Count(c.v.Buf.Lines[c.y])
|
||||
}
|
||||
}
|
||||
|
||||
// Display draws the cursor to the screen at the correct position
|
||||
func (c *Cursor) Display() {
|
||||
// Don't draw the cursor if it is out of the viewport or if it has a selection
|
||||
if (c.y-c.v.Topline < 0 || c.y-c.v.Topline > c.v.height-1) || c.HasSelection() {
|
||||
screen.HideCursor()
|
||||
} else {
|
||||
screen.ShowCursor(c.GetVisualX()+c.v.lineNumOffset-c.v.leftCol, c.y-c.v.Topline)
|
||||
} else if c.x > Count(c.Buf.Lines[c.y]) {
|
||||
c.x = Count(c.Buf.Lines[c.y])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ type TextEvent struct {
|
||||
// ExecuteTextEvent runs a text event
|
||||
func ExecuteTextEvent(t *TextEvent, buf *Buffer) {
|
||||
if t.eventType == TextEventInsert {
|
||||
buf.Insert(t.start, t.text)
|
||||
buf.insert(t.start, t.text)
|
||||
} else if t.eventType == TextEventRemove {
|
||||
t.text = buf.Remove(t.start, t.end)
|
||||
t.text = buf.remove(t.start, t.end)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,24 +41,24 @@ func UndoTextEvent(t *TextEvent, buf *Buffer) {
|
||||
|
||||
// EventHandler executes text manipulations and allows undoing and redoing
|
||||
type EventHandler struct {
|
||||
v *View
|
||||
buf *Buffer
|
||||
undo *Stack
|
||||
redo *Stack
|
||||
}
|
||||
|
||||
// NewEventHandler returns a new EventHandler
|
||||
func NewEventHandler(v *View) *EventHandler {
|
||||
func NewEventHandler(buf *Buffer) *EventHandler {
|
||||
eh := new(EventHandler)
|
||||
eh.undo = new(Stack)
|
||||
eh.redo = new(Stack)
|
||||
eh.v = v
|
||||
eh.buf = buf
|
||||
return eh
|
||||
}
|
||||
|
||||
// Insert creates an insert text event and executes it
|
||||
func (eh *EventHandler) Insert(start int, text string) {
|
||||
e := &TextEvent{
|
||||
c: eh.v.Cursor,
|
||||
c: eh.buf.Cursor,
|
||||
eventType: TextEventInsert,
|
||||
text: text,
|
||||
start: start,
|
||||
@@ -71,7 +71,7 @@ func (eh *EventHandler) Insert(start int, text string) {
|
||||
// Remove creates a remove text event and executes it
|
||||
func (eh *EventHandler) Remove(start, end int) {
|
||||
e := &TextEvent{
|
||||
c: eh.v.Cursor,
|
||||
c: eh.buf.Cursor,
|
||||
eventType: TextEventRemove,
|
||||
start: start,
|
||||
end: end,
|
||||
@@ -92,7 +92,7 @@ func (eh *EventHandler) Execute(t *TextEvent) {
|
||||
eh.redo = new(Stack)
|
||||
}
|
||||
eh.undo.Push(t)
|
||||
ExecuteTextEvent(t, eh.v.Buf)
|
||||
ExecuteTextEvent(t, eh.buf)
|
||||
}
|
||||
|
||||
// Undo the first event in the undo stack
|
||||
@@ -135,12 +135,12 @@ func (eh *EventHandler) UndoOneEvent() {
|
||||
te := t.(*TextEvent)
|
||||
// Undo it
|
||||
// Modifies the text event
|
||||
UndoTextEvent(te, eh.v.Buf)
|
||||
UndoTextEvent(te, eh.buf)
|
||||
|
||||
// Set the cursor in the right place
|
||||
teCursor := te.c
|
||||
te.c = eh.v.Cursor
|
||||
eh.v.Cursor = teCursor
|
||||
te.c = eh.buf.Cursor
|
||||
eh.buf.Cursor = teCursor
|
||||
|
||||
// Push it to the redo stack
|
||||
eh.redo.Push(te)
|
||||
@@ -183,11 +183,11 @@ func (eh *EventHandler) RedoOneEvent() {
|
||||
|
||||
te := t.(*TextEvent)
|
||||
// Modifies the text event
|
||||
UndoTextEvent(te, eh.v.Buf)
|
||||
UndoTextEvent(te, eh.buf)
|
||||
|
||||
teCursor := te.c
|
||||
te.c = eh.v.Cursor
|
||||
eh.v.Cursor = teCursor
|
||||
te.c = eh.buf.Cursor
|
||||
eh.buf.Cursor = teCursor
|
||||
|
||||
eh.undo.Push(te)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ import (
|
||||
// It stores information about the cursor, and the viewport
|
||||
// that the user sees the buffer from.
|
||||
type View struct {
|
||||
Cursor Cursor
|
||||
// A pointer to the buffer's cursor for ease of access
|
||||
Cursor *Cursor
|
||||
|
||||
// The topmost line, used for vertical scrolling
|
||||
Topline int
|
||||
@@ -33,9 +34,6 @@ type View struct {
|
||||
// How much to offset because of line numbers
|
||||
lineNumOffset int
|
||||
|
||||
// The eventhandler for undo/redo
|
||||
eh *EventHandler
|
||||
|
||||
// Holds the list of gutter messages
|
||||
messages map[string][]GutterMessage
|
||||
|
||||
@@ -90,8 +88,6 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
|
||||
|
||||
v.OpenBuffer(buf)
|
||||
|
||||
v.eh = NewEventHandler(v)
|
||||
|
||||
v.messages = make(map[string][]GutterMessage)
|
||||
|
||||
v.sline = Statusline{
|
||||
@@ -162,18 +158,12 @@ func (v *View) CanClose(msg string) bool {
|
||||
// This resets the topline, event handler and cursor.
|
||||
func (v *View) OpenBuffer(buf *Buffer) {
|
||||
v.Buf = buf
|
||||
v.Cursor = &buf.Cursor
|
||||
v.Topline = 0
|
||||
v.leftCol = 0
|
||||
// Put the cursor at the first spot
|
||||
v.Cursor = Cursor{
|
||||
x: 0,
|
||||
y: 0,
|
||||
v: v,
|
||||
}
|
||||
v.Cursor.ResetSelection()
|
||||
v.messages = make(map[string][]GutterMessage)
|
||||
|
||||
v.eh = NewEventHandler(v)
|
||||
v.matches = Match(v)
|
||||
|
||||
// Set mouseReleased to true because we assume the mouse is not being pressed when
|
||||
@@ -269,7 +259,7 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
v.eh.Insert(v.Cursor.Loc(), string(e.Rune()))
|
||||
v.Buf.Insert(v.Cursor.Loc(), string(e.Rune()))
|
||||
v.Cursor.Right()
|
||||
} else {
|
||||
for key, action := range bindings {
|
||||
@@ -293,7 +283,7 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
clip := e.Text()
|
||||
v.eh.Insert(v.Cursor.Loc(), clip)
|
||||
v.Buf.Insert(v.Cursor.Loc(), clip)
|
||||
v.Cursor.SetLoc(v.Cursor.Loc() + Count(clip))
|
||||
v.freshClip = false
|
||||
case *tcell.EventMouse:
|
||||
@@ -595,10 +585,20 @@ func (v *View) DisplayView() {
|
||||
}
|
||||
}
|
||||
|
||||
// DisplayCursor draws the current buffer's cursor to the screen
|
||||
func (v *View) DisplayCursor() {
|
||||
// Don't draw the cursor if it is out of the viewport or if it has a selection
|
||||
if (v.Cursor.y-v.Topline < 0 || v.Cursor.y-v.Topline > v.height-1) || v.Cursor.HasSelection() {
|
||||
screen.HideCursor()
|
||||
} else {
|
||||
screen.ShowCursor(v.Cursor.GetVisualX()+v.lineNumOffset-v.leftCol, v.Cursor.y-v.Topline)
|
||||
}
|
||||
}
|
||||
|
||||
// Display renders the view, the cursor, and statusline
|
||||
func (v *View) Display() {
|
||||
v.DisplayView()
|
||||
v.Cursor.Display()
|
||||
v.DisplayCursor()
|
||||
if settings["statusline"].(bool) {
|
||||
v.sline.Display()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user