// 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
// 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
v.OpenBuffer(buf)
- v.eh = NewEventHandler(v)
-
v.messages = make(map[string][]GutterMessage)
v.sline = Statusline{
// 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
v.Buf = buf
v.matches = Match(v)
v.Cursor.Relocate()
- v.Relocate(0)
+ v.Relocate()
}
}
// Relocate moves the view window so that the cursor is in view
// This is useful if the user has scrolled far away, and then starts typing
-func (v *View) Relocate(x int) bool {
+func (v *View) Relocate() bool {
ret := false
cy := v.Cursor.y
- if cy < v.Topline {
- v.Topline = cy - x
+ scrollmargin := int(settings["scrollmargin"].(float64))
+ if cy < v.Topline+scrollmargin && cy > scrollmargin-1 {
+ v.Topline = cy - scrollmargin
+ ret = true
+ } else if cy < v.Topline {
+ v.Topline = cy
ret = true
}
- if cy > v.Topline+v.height-1 {
- v.Topline = cy - v.height + 1 + x
+ if cy > v.Topline+v.height-1-scrollmargin {
+ v.Topline = cy - v.height + 1 + scrollmargin
ret = true
}
// Window resized
v.Resize(e.Size())
case *tcell.EventKey:
- if e.Key() == tcell.KeyRune {
+ if e.Key() == tcell.KeyRune && e.Modifiers() == 0 {
// Insert a character
if v.Cursor.HasSelection() {
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 {
if e.Key() == key.keyCode {
+ if e.Key() == tcell.KeyRune {
+ if e.Rune() != key.r {
+ continue
+ }
+ }
if e.Modifiers() == key.modifiers {
relocate = action(v)
for _, pl := range loadedPlugins {
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:
}
case tcell.WheelUp:
// Scroll up
- scrollSpeed := int(settings["scrollSpeed"].(float64))
- v.ScrollUp(scrollSpeed)
+ scrollspeed := int(settings["scrollspeed"].(float64))
+ v.ScrollUp(scrollspeed)
case tcell.WheelDown:
// Scroll down
- scrollSpeed := int(settings["scrollSpeed"].(float64))
- v.ScrollDown(scrollSpeed)
+ scrollspeed := int(settings["scrollspeed"].(float64))
+ v.ScrollDown(scrollspeed)
}
}
if relocate {
- v.Relocate(0)
+ v.Relocate()
}
if settings["syntax"].(bool) {
v.matches = Match(v)
}
}
+// 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()
}