h--
v.width = int(float32(w) * float32(v.widthPercent) / 100)
// We subtract 1 for the statusline
- v.height = int(float32(h)*float32(v.heightPercent)/100) - 1
+ v.height = int(float32(h) * float32(v.heightPercent) / 100)
+ if settings["statusline"].(bool) {
+ // Make room for the status line if it is enabled
+ v.height--
+ }
}
// ScrollUp scrolls the view up n lines (if possible)
// causing them to lose the unsaved changes
// The message is what to print after saying "You have unsaved changes. "
func (v *View) CanClose(msg string) bool {
- if v.Buf.IsDirty() {
+ if v.Buf.IsModified {
quit, canceled := messenger.Prompt("You have unsaved changes. " + msg)
if !canceled {
if strings.ToLower(quit) == "yes" || strings.ToLower(quit) == "y" {
v.Buf = buf
v.matches = Match(v)
v.Cursor.Relocate()
- v.Relocate()
+ v.Relocate(0)
}
}
// 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() bool {
+func (v *View) Relocate(x int) bool {
ret := false
cy := v.Cursor.y
- if cy < v.Topline {
+ if cy < v.Topline+x && cy > x-1 {
+ v.Topline = cy - x
+ 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
+ if cy > v.Topline+v.height-1-x {
+ v.Topline = cy - v.height + 1 + x
ret = true
}
// This bool determines whether the view is relocated at the end of the function
// By default it's true because most events should cause a relocate
relocate := true
+ scrollmargin := int(settings["scrollmargin"].(float64))
switch e := event.(type) {
case *tcell.EventResize:
v.Cursor.Right()
} else {
for key, action := range bindings {
- if e.Key() == key {
- relocate = action(v)
- for _, pl := range loadedPlugins {
- funcName := strings.Split(runtime.FuncForPC(reflect.ValueOf(action).Pointer()).Name(), ".")
- err := Call(pl + "_on" + funcName[len(funcName)-1])
- if err != nil {
- TermMessage(err)
+ if e.Key() == key.keyCode {
+ if e.Modifiers() == key.modifiers {
+ relocate = action(v)
+ for _, pl := range loadedPlugins {
+ funcName := strings.Split(runtime.FuncForPC(reflect.ValueOf(action).Pointer()).Name(), ".")
+ err := Call(pl + "_on" + funcName[len(funcName)-1])
+ if err != nil {
+ TermMessage(err)
+ }
}
}
}
x, y := e.Position()
x -= v.lineNumOffset - v.leftCol
y += v.Topline
+ // Don't relocate for mouse events
+ relocate = false
button := e.Buttons()
switch button {
case tcell.Button1:
// Left click
- if v.mouseReleased && !e.HasMotion() {
+ if v.mouseReleased {
v.MoveToMouseClick(x, y)
if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold {
if v.doubleClick {
}
v.mouseReleased = true
}
- // We don't want to relocate because otherwise the view will be relocated
- // every time the user moves the cursor
- relocate = false
case tcell.WheelUp:
- // Scroll up two lines
- v.ScrollUp(2)
- // We don't want to relocate if the user is scrolling
- relocate = false
+ // Scroll up
+ scrollspeed := int(settings["scrollspeed"].(float64))
+ v.ScrollUp(scrollspeed)
case tcell.WheelDown:
- // Scroll down two lines
- v.ScrollDown(2)
- // We don't want to relocate if the user is scrolling
- relocate = false
+ // Scroll down
+ scrollspeed := int(settings["scrollspeed"].(float64))
+ v.ScrollDown(scrollspeed)
}
}
if relocate {
- v.Relocate()
+ v.Relocate(scrollmargin)
}
if settings["syntax"].(bool) {
v.matches = Match(v)
v.messages[section] = append(messages, gutterMsg)
}
+// ClearGutterMessages clears all gutter messages from a given section
func (v *View) ClearGutterMessages(section string) {
v.messages[section] = []GutterMessage{}
}
+// ClearAllGutterMessages clears all the gutter messages
+func (v *View) ClearAllGutterMessages() {
+ for k := range v.messages {
+ v.messages[k] = []GutterMessage{}
+ }
+}
+
// DisplayView renders the view to the screen
func (v *View) DisplayView() {
// The character number of the character in the top left of the screen
}
if ch == '\t' {
- screen.SetContent(x+tabchars, lineN, ' ', nil, lineStyle)
+ lineIndentStyle := defStyle
+ if style, ok := colorscheme["indent-char"]; ok {
+ lineIndentStyle = style
+ }
+ if v.Cursor.HasSelection() &&
+ (charNum >= v.Cursor.curSelection[0] && charNum < v.Cursor.curSelection[1] ||
+ charNum < v.Cursor.curSelection[0] && charNum >= v.Cursor.curSelection[1]) {
+
+ lineIndentStyle = tcell.StyleDefault.Reverse(true)
+
+ if style, ok := colorscheme["selection"]; ok {
+ lineIndentStyle = style
+ }
+ }
+ indentChar := []rune(settings["indentchar"].(string))
+ screen.SetContent(x-v.leftCol+tabchars, lineN, indentChar[0], nil, lineIndentStyle)
tabSize := int(settings["tabsize"].(float64))
for i := 0; i < tabSize-1; i++ {
tabchars++
func (v *View) Display() {
v.DisplayView()
v.Cursor.Display()
- v.sline.Display()
+ if settings["statusline"].(bool) {
+ v.sline.Display()
+ }
}