func (ui *UI) getViewTotalRows(v *gocui.View) int {
	var rows int
	buffer := v.ViewBuffer()
	for _, char := range []byte(buffer) {
		if string(char) == "\n" {
			rows++
		}
	}
	return rows
}
getViewTotalRows returns the total number of rows of the current view
package ui
import (
	"strings"
	"github.com/jroimartin/gocui"
)
type editor struct {
	ui            *UI
	editor        gocui.Editor
	backTabEscape bool
}
var cache []byte
func newEditor(ui *UI, handler gocui.Editor) *editor {
	if handler == nil {
		handler = gocui.DefaultEditor
	}
	return &editor{ui, handler, true}
}
func (e *editor) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
	if ch == '[' && mod == gocui.ModAlt {
		e.backTabEscape = true
		return
	}
	if e.backTabEscape {
		if ch == 'Z' {
			e.ui.prevView(true)
			e.backTabEscape = false
			return
		}
	}
	if (key == gocui.KeyArrowDown || key == gocui.KeyArrowRight) && mod == gocui.ModNone {
		_, cy := v.Cursor()
		if _, err := v.Line(cy); err != nil {
			return
		}
	}
	switch key {
	case gocui.KeyArrowRight:
		cx, cy := v.Cursor()
		maxY := strings.Count(v.Buffer(), "\n")
		if cy == maxY-1 {
			if cx >= e.ui.getViewRowCount(v, cy) {
				return
			}
		}
	case gocui.KeyHome:
		_, cy := v.Cursor()
		v.SetCursor(0, cy)
	case gocui.KeyEnd:
		_, cy := v.Cursor()
		maxX := e.ui.getViewRowCount(v, cy)
		v.SetCursor(maxX, cy)
	case gocui.KeyPgup:
		vx, vy := v.Origin()
		if err := v.SetCursor(0, 0); err != nil && vy > 0 {
			if err := v.SetOrigin(vx, 0); err != nil {
				return
			}
		}
	case gocui.KeyPgdn:
		maxX := e.ui.getViewLastRowCount(v)
		maxY := strings.Count(v.ViewBuffer(), "\n") - 1
		v.SetCursor(maxX, maxY)
	case gocui.KeyCtrlX:
		if v.Name() == DIAGRAM_PANEL {
			cache = []byte(v.ViewBuffer())
			e.ui.ClearView(v.Name())
			v.SetCursor(0, 0)
		}
	case gocui.KeyCtrlZ:
		if len(cache) > 0 {
			v.Write(cache)
			cache = []byte{}
		}
	}
	e.editor.Edit(v, key, ch, mod)
}
type staticViewEditor editor
func (e *staticViewEditor) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
	_, y := v.Cursor()
	maxY := strings.Count(v.Buffer(), "\n")
	switch key {
	case gocui.KeyArrowDown:
		if y < maxY {
			v.MoveCursor(0, 1, true)
		}
	case gocui.KeyArrowUp:
		v.MoveCursor(0, -1, false)
	case gocui.KeyArrowLeft:
		v.MoveCursor(-1, 0, false)
	case gocui.KeyArrowRight:
		v.MoveCursor(1, 0, false)
	}
}
type modalSaveEditor struct {
	maxWidth int
}
func (e *modalSaveEditor) Edit(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
	x, _ := v.Cursor()
	switch {
	case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
		v.EditDelete(true)
		return
	case key == gocui.KeyDelete:
		v.EditDelete(false)
		return
	case key == gocui.KeyArrowLeft:
		v.MoveCursor(-1, 0, false)
		return
	case key == gocui.KeyArrowRight:
		if x < len(v.Buffer())-1 {
			v.MoveCursor(1, 0, false)
		}
		return
	case key == gocui.KeyArrowDown:
		return
	case key == gocui.KeyEnter:
		return
	default:
		if x > e.maxWidth {
			return
		}
	}
	gocui.DefaultEditor.Edit(v, key, ch, mod)
}
func (ui *UI) getViewRow(v *gocui.View, y int) []string {
	var row string
	rows := []string{}
	buffer := v.ViewBuffer()
	for _, char := range []byte(buffer) {
		if string(char) == "\n" {
			rows = append(rows, row)
			row = ""
		} else {
			row = row + string(char)
		}
	}
	if len(rows) > 0 && (y > -1 && y < len(rows)) {
		return []string{rows[y]}
	}
	return []string{""}
}
func (ui *UI) getViewLastRow(v *gocui.View) []string {
	var row string
	rows := []string{}
	buffer := v.ViewBuffer()
	for _, char := range []byte(buffer) {
		if string(char) == "\n" {
			rows = append(rows, row)
			row = ""
		} else {
			row = row + string(char)
		}
	}
	if len(rows) > 0 {
		fn := func(rows []string) int {
			var idx = 1
			for {
				current := string(rows[len(rows)-idx:][0])
				if current == "" {
					idx++
				} else {
					break
				}
			}
			return idx
		}
		index := fn(rows)
		return rows[len(rows)-index:]
	}
	return []string{""}
}
func (ui *UI) getViewRowCount(v *gocui.View, y int) int {
	row := ui.getViewRow(v, y)
	return len(strings.Split(row[0], ""))
}
func (ui *UI) getViewLastRowCount(v *gocui.View) int {
	lastRow := ui.getViewLastRow(v)
	return len(strings.Split(lastRow[0], ""))
}