X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fview.go;h=269acd43c0862991c1abe3438267e942c1e169bf;hb=37ae99ccd9b7b3a658a2e773af74ca08c88c0d07;hp=0d37cba7089fda8e98fea75113ba4b7db92f1ce5;hpb=199c295f1f19b4218b8678fa822ef6ac1baaf35a;p=micro.git diff --git a/cmd/micro/view.go b/cmd/micro/view.go index 0d37cba7..269acd43 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -1,7 +1,7 @@ package main import ( - "io/ioutil" + "os" "strconv" "strings" "time" @@ -35,8 +35,11 @@ type View struct { 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 @@ -100,8 +103,8 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View { v.x, v.y = 0, 0 - v.width = w - v.height = h + v.Width = w + v.Height = h v.ToggleTabbar() @@ -114,7 +117,7 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View { } if v.Buf.Settings["statusline"].(bool) { - v.height-- + v.Height-- } for _, pl := range loadedPlugins { @@ -131,9 +134,9 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View { // 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++ } } @@ -142,13 +145,13 @@ func (v *View) ToggleTabbar() { 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++ } } } @@ -180,9 +183,9 @@ func (v *View) ScrollUp(n int) { // 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++ } } @@ -197,7 +200,7 @@ func (v *View) CanClose() bool { 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' { @@ -239,13 +242,14 @@ func (v *View) OpenBuffer(buf *Buffer) { 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) } @@ -270,17 +274,31 @@ func (v *View) ReOpen() { } // 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 @@ -296,7 +314,7 @@ func (v *View) GetSoftWrapLocation(vx, vy int) (int, int) { colN := 0 for _, ch := range line { - if screenX >= v.width-v.lineNumOffset { + if screenX >= v.Width-v.lineNumOffset { screenX = 0 screenY++ } @@ -323,14 +341,18 @@ func (v *View) GetSoftWrapLocation(vx, vy int) (int, int) { } 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++ } @@ -346,7 +368,7 @@ func (v *View) Bottomline() int { screenY++ numLines++ - if screenY >= v.height { + if screenY >= v.Height { break } } @@ -381,8 +403,8 @@ func (v *View) Relocate() bool { 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 } } @@ -392,12 +414,9 @@ func (v *View) Relocate() bool { // 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 @@ -481,18 +500,7 @@ func (v *View) HandleEvent(event tcell.Event) { 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: @@ -620,8 +628,8 @@ func (v *View) openHelp(helpPage string) { 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) @@ -633,7 +641,7 @@ func (v *View) openHelp(helpPage string) { } 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) } } @@ -687,14 +695,14 @@ func (v *View) DisplayView() { 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 } @@ -706,7 +714,7 @@ func (v *View) DisplayView() { // 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) } @@ -768,7 +776,7 @@ func (v *View) DisplayView() { 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 } } @@ -797,7 +805,7 @@ func (v *View) DisplayView() { 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) @@ -806,7 +814,7 @@ func (v *View) DisplayView() { } } - 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) } @@ -832,7 +840,7 @@ func (v *View) DisplayView() { // 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) @@ -858,7 +866,7 @@ func (v *View) DisplayView() { 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) @@ -878,6 +886,7 @@ func (v *View) DisplayView() { 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) @@ -888,19 +897,20 @@ func (v *View) DisplayView() { 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) } @@ -921,9 +931,9 @@ func (v *View) DisplayView() { 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) @@ -953,15 +963,15 @@ func (v *View) DisplayCursor(x, y int) { 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)) } } }