package main
import (
- "io/ioutil"
+ "os"
"strconv"
"strings"
"time"
Type ViewType
// Actual width and height
- width int
- height int
+ Width int
+ Height int
+
+ LockWidth bool
+ LockHeight bool
// Where this view is located
x, y int
v.x, v.y = 0, 0
- v.width = w
- v.height = h
+ v.Width = w
+ v.Height = h
v.ToggleTabbar()
}
if v.Buf.Settings["statusline"].(bool) {
- v.height--
+ v.Height--
}
for _, pl := range loadedPlugins {
// ToggleStatusLine creates an extra row for the statusline if necessary
func (v *View) ToggleStatusLine() {
if v.Buf.Settings["statusline"].(bool) {
- v.height--
+ v.Height--
} else {
- v.height++
+ v.Height++
}
}
if len(tabs) > 1 {
if v.y == 0 {
// Include one line for the tab bar at the top
- v.height--
+ v.Height--
v.y = 1
}
} else {
if v.y == 1 {
v.y = 0
- v.height++
+ v.Height++
}
}
}
// ScrollDown scrolls the view down n lines (if possible)
func (v *View) ScrollDown(n int) {
// Try to scroll by n but if it would overflow, scroll by 1
- if v.Topline+n <= v.Buf.NumLines-v.height {
+ if v.Topline+n <= v.Buf.NumLines-v.Height {
v.Topline += n
- } else if v.Topline < v.Buf.NumLines-v.height {
+ } else if v.Topline < v.Buf.NumLines-v.Height {
v.Topline++
}
}
if v.Buf.Settings["autosave"].(bool) {
char = 'y'
} else {
- char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.Name+" before closing? (y,n,esc) ", 'y', 'n')
+ char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.GetName()+" before closing? (y,n,esc) ", 'y', 'n')
}
if !canceled {
if char == 'y' {
func (v *View) Open(filename string) {
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
- file, err := ioutil.ReadFile(filename)
+ file, err := os.Open(filename)
+ defer file.Close()
var buf *Buffer
if err != nil {
messenger.Message(err.Error())
// File does not exist -- create an empty buffer with that name
- buf = NewBuffer([]byte{}, filename)
+ buf = NewBuffer(strings.NewReader(""), filename)
} else {
buf = NewBuffer(file, filename)
}
}
// HSplit opens a horizontal split with the given buffer
-func (v *View) HSplit(buf *Buffer) bool {
- v.splitNode.HSplit(buf)
- tabs[v.TabNum].Resize()
- return false
+func (v *View) HSplit(buf *Buffer) {
+ i := 0
+ if v.Buf.Settings["splitBottom"].(bool) {
+ i = 1
+ }
+ v.splitNode.HSplit(buf, v.Num+i)
}
// VSplit opens a vertical split with the given buffer
-func (v *View) VSplit(buf *Buffer) bool {
- v.splitNode.VSplit(buf)
- tabs[v.TabNum].Resize()
- return false
+func (v *View) VSplit(buf *Buffer) {
+ i := 0
+ if v.Buf.Settings["splitRight"].(bool) {
+ i = 1
+ }
+ v.splitNode.VSplit(buf, v.Num+i)
+}
+
+// HSplitIndex opens a horizontal split with the given buffer at the given index
+func (v *View) HSplitIndex(buf *Buffer, splitIndex int) {
+ v.splitNode.HSplit(buf, splitIndex)
+}
+
+// VSplitIndex opens a vertical split with the given buffer at the given index
+func (v *View) VSplitIndex(buf *Buffer, splitIndex int) {
+ v.splitNode.VSplit(buf, splitIndex)
}
// GetSoftWrapLocation gets the location of a visual click on the screen and converts it to col,line
colN := 0
for _, ch := range line {
- if screenX >= v.width-v.lineNumOffset {
+ if screenX >= v.Width-v.lineNumOffset {
screenX = 0
screenY++
}
}
func (v *View) Bottomline() int {
+ if !v.Buf.Settings["softwrap"].(bool) {
+ return v.Topline + v.Height
+ }
+
screenX, screenY := 0, 0
numLines := 0
- for lineN := v.Topline; lineN < v.Topline+v.height; lineN++ {
+ for lineN := v.Topline; lineN < v.Topline+v.Height; lineN++ {
line := v.Buf.Line(lineN)
colN := 0
for _, ch := range line {
- if screenX >= v.width-v.lineNumOffset {
+ if screenX >= v.Width-v.lineNumOffset {
screenX = 0
screenY++
}
screenY++
numLines++
- if screenY >= v.height {
+ if screenY >= v.Height {
break
}
}
v.leftCol = cx
ret = true
}
- if cx+v.lineNumOffset+1 > v.leftCol+v.width {
- v.leftCol = cx - v.width + v.lineNumOffset + 1
+ if cx+v.lineNumOffset+1 > v.leftCol+v.Width {
+ v.leftCol = cx - v.Width + v.lineNumOffset + 1
ret = true
}
}
// MoveToMouseClick moves the cursor to location x, y assuming x, y were given
// by a mouse click
func (v *View) MoveToMouseClick(x, y int) {
- if y-v.Topline > v.height-1 {
+ if y-v.Topline > v.Height-1 {
v.ScrollDown(1)
- y = v.height + v.Topline - 1
- }
- if y >= v.Buf.NumLines {
- y = v.Buf.NumLines - 1
+ y = v.Height + v.Topline - 1
}
if y < 0 {
y = 0
break
}
- leadingWS := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))
-
- if v.Cursor.HasSelection() {
- v.Cursor.DeleteSelection()
- v.Cursor.ResetSelection()
- }
- clip := e.Text()
- clip = strings.Replace(clip, "\n", "\n"+leadingWS, -1)
- v.Buf.Insert(v.Cursor.Loc, clip)
- v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
- v.freshClip = false
- messenger.Message("Pasted clipboard")
+ v.paste(e.Text())
PostActionCall("Paste", v)
case *tcell.EventMouse:
if data, err := FindRuntimeFile(RTHelp, helpPage).Data(); err != nil {
TermMessage("Unable to load help text", helpPage, "\n", err)
} else {
- helpBuffer := NewBuffer(data, helpPage+".md")
- helpBuffer.Name = "Help"
+ helpBuffer := NewBuffer(strings.NewReader(string(data)), helpPage+".md")
+ helpBuffer.name = "Help"
if v.Type == vtHelp {
v.OpenBuffer(helpBuffer)
}
func (v *View) drawCell(x, y int, ch rune, combc []rune, style tcell.Style) {
- if x >= v.x && x < v.x+v.width && y >= v.y && y < v.y+v.height {
+ if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
screen.SetContent(x, y, ch, combc, style)
}
}
curLineN := 0
// ViewLine is the current line from the top of the viewport
- for viewLine := 0; viewLine < v.height; viewLine++ {
+ for viewLine := 0; viewLine < v.Height; viewLine++ {
screenY++
screenX = v.x
// This is the current line number of the buffer that we are drawing
curLineN = viewLine + v.Topline
- if screenY-v.y >= v.height {
+ if screenY-v.y >= v.Height {
break
}
// If the buffer is smaller than the view height we have to clear all this space
if curLineN >= v.Buf.NumLines {
- for i := screenX; i < v.x+v.width; i++ {
+ for i := screenX; i < v.x+v.Width; i++ {
v.drawCell(i, screenY, ' ', nil, defStyle)
}
lineNumStyle = style
}
if style, ok := colorscheme["current-line-number"]; ok {
- if curLineN == v.Cursor.Y && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() {
+ if curLineN == v.Cursor.Y && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() {
lineNumStyle = style
}
}
tabSize := int(v.Buf.Settings["tabsize"].(float64))
for _, ch := range line {
if v.Buf.Settings["softwrap"].(bool) {
- if screenX-v.x >= v.width {
+ if screenX-v.x >= v.Width {
screenY++
for i := 0; i < v.lineNumOffset; i++ {
screen.SetContent(v.x+i, screenY, ' ', nil, lineNumStyle)
}
}
- if tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
+ if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
v.DisplayCursor(screenX-v.leftCol, screenY)
}
// We need to display the background of the linestyle with the correct color if cursorline is enabled
// and this is the current view and there is no selection on this line and the cursor is on this line
- if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
+ if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
lineIndentStyle = style
}
}
- if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
+ if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
fg, _, _ := style.Decompose()
lineIndentStyle = lineIndentStyle.Background(fg)
v.drawCell(screenX-v.leftCol, screenY, ' ', nil, lineStyle)
}
}
+ strWidth += remainder
} else if runewidth.RuneWidth(ch) > 1 {
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX, screenY, ch, nil, lineStyle)
v.drawCell(screenX-v.leftCol, screenY, '<', nil, lineStyle)
}
}
+ strWidth += StringWidth(string(ch), tabSize)
} else {
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, ch, nil, lineStyle)
}
+ strWidth += StringWidth(string(ch), tabSize)
}
charNum = charNum.Move(1, v.Buf)
screenX++
colN++
- strWidth += StringWidth(string(ch), tabSize)
}
// Here we are at a newline
- if tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
+ if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
v.DisplayCursor(screenX-v.leftCol, screenY)
}
charNum = charNum.Move(1, v.Buf)
- for i := 0; i < v.width; i++ {
+ for i := 0; i < v.Width; i++ {
lineStyle := defStyle
- if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
+ if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
if style, ok := colorscheme["cursor-line"]; ok {
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
func (v *View) Display() {
v.DisplayView()
// 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() {
+ if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || v.Cursor.HasSelection() {
screen.HideCursor()
}
_, screenH := screen.Size()
if v.Buf.Settings["statusline"].(bool) {
v.sline.Display()
- } else if (v.y + v.height) != screenH-1 {
- for x := 0; x < v.width; x++ {
- screen.SetContent(v.x+x, v.y+v.height, '-', nil, defStyle.Reverse(true))
+ } else if (v.y + v.Height) != screenH-1 {
+ for x := 0; x < v.Width; x++ {
+ screen.SetContent(v.x+x, v.y+v.Height, '-', nil, defStyle.Reverse(true))
}
}
}