Add the ability to close splits and change splits using the mouse
This commits adds split navigation with the mouse and the ability to close splits. You can now also open a file directly with the hsplit and vsplit commands.
This commit is contained in:
parent
d2b11c2f98
commit
4a15a1d3c8
4 changed files with 112 additions and 13 deletions
|
@ -915,11 +915,13 @@ func (v *View) OpenFile() bool {
|
|||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
messenger.Error(err.Error())
|
||||
return false
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer([]byte{}, filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
}
|
||||
buf := NewBuffer(file, filename)
|
||||
v.OpenBuffer(buf)
|
||||
return true
|
||||
}
|
||||
|
@ -1090,7 +1092,27 @@ func (v *View) Quit() bool {
|
|||
// Make sure not to quit if there are unsaved changes
|
||||
if v.CanClose("Quit anyway? (yes, no, save) ") {
|
||||
v.CloseBuffer()
|
||||
if len(tabs) > 1 {
|
||||
if len(tabs[curTab].views) > 1 {
|
||||
var view *View
|
||||
if v.splitChild != nil {
|
||||
view = v.splitChild
|
||||
view.splitParent = v.splitParent
|
||||
} else if v.splitParent != nil {
|
||||
view = v.splitParent
|
||||
v.splitParent.splitChild = nil
|
||||
}
|
||||
view.x, view.y = view.splitOrigPos[0], view.splitOrigPos[1]
|
||||
view.widthPercent, view.heightPercent = view.splitOrigDimensions[0], view.splitOrigDimensions[1]
|
||||
view.Resize(screen.Size())
|
||||
if settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
}
|
||||
tabs[curTab].views = tabs[curTab].views[:v.Num+copy(tabs[curTab].views[v.Num:], tabs[curTab].views[v.Num+1:])]
|
||||
for i, v := range tabs[curTab].views {
|
||||
v.Num = i
|
||||
}
|
||||
tabs[curTab].curView = view.Num
|
||||
} else if len(tabs) > 1 {
|
||||
if len(tabs[v.TabNum].views) == 1 {
|
||||
tabs = tabs[:v.TabNum+copy(tabs[v.TabNum:], tabs[v.TabNum+1:])]
|
||||
for i, t := range tabs {
|
||||
|
|
|
@ -2,11 +2,14 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
var commands map[string]func([]string)
|
||||
|
@ -63,11 +66,48 @@ func DefaultCommands() map[string]string {
|
|||
}
|
||||
}
|
||||
|
||||
// VSplit opens a vertical split with file given in the first argument
|
||||
// If no file is given, it opens an empty buffer in a new split
|
||||
func VSplit(args []string) {
|
||||
CurView().VSplit()
|
||||
if len(args) == 0 {
|
||||
CurView().VSplit(NewBuffer([]byte{}, ""))
|
||||
} else {
|
||||
filename := args[0]
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer([]byte{}, filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
}
|
||||
CurView().VSplit(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// HSplit opens a horizontal split with file given in the first argument
|
||||
// If no file is given, it opens an empty buffer in a new split
|
||||
func HSplit(args []string) {
|
||||
CurView().HSplit()
|
||||
if len(args) == 0 {
|
||||
CurView().HSplit(NewBuffer([]byte{}, ""))
|
||||
} else {
|
||||
filename := args[0]
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer([]byte{}, filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
}
|
||||
CurView().HSplit(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets an option
|
||||
|
|
|
@ -281,11 +281,17 @@ func main() {
|
|||
case *tcell.EventMouse:
|
||||
if e.Buttons() == tcell.Button1 {
|
||||
_, h := screen.Size()
|
||||
_, y := e.Position()
|
||||
x, y := e.Position()
|
||||
if y == h-1 && messenger.message != "" {
|
||||
clipboard.WriteAll(messenger.message)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range tabs[curTab].views {
|
||||
if x >= v.x && x < v.x+v.width && y >= v.y && y < v.y+v.height {
|
||||
tabs[curTab].curView = v.Num
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ type View struct {
|
|||
matches SyntaxMatches
|
||||
// The matches from the last frame
|
||||
lastMatches SyntaxMatches
|
||||
|
||||
splitParent *View
|
||||
splitChild *View
|
||||
splitOrigDimensions [2]int
|
||||
splitOrigPos [2]int
|
||||
}
|
||||
|
||||
// NewView returns a new fullscreen view
|
||||
|
@ -222,32 +227,56 @@ func (v *View) ReOpen() {
|
|||
}
|
||||
}
|
||||
|
||||
func (v *View) HSplit() bool {
|
||||
// HSplit opens a horizontal split with the given buffer
|
||||
func (v *View) HSplit(buf *Buffer) bool {
|
||||
origDimensions := [2]int{v.widthPercent, v.heightPercent}
|
||||
origPos := [2]int{v.x, v.y}
|
||||
|
||||
v.heightPercent /= 2
|
||||
v.Resize(screen.Size())
|
||||
|
||||
newView := NewViewWidthHeight(NewBuffer([]byte{}, ""), v.widthPercent, v.heightPercent)
|
||||
newView := NewViewWidthHeight(buf, v.widthPercent, v.heightPercent)
|
||||
|
||||
v.splitOrigDimensions = origDimensions
|
||||
v.splitOrigPos = origPos
|
||||
newView.splitOrigDimensions = origDimensions
|
||||
newView.splitOrigPos = origPos
|
||||
|
||||
newView.TabNum = v.TabNum
|
||||
newView.y = v.y + v.height + 1
|
||||
newView.x = v.x
|
||||
tab := tabs[v.TabNum]
|
||||
tab.curView++
|
||||
newView.Num = len(tab.views)
|
||||
newView.splitParent = v
|
||||
v.splitChild = newView
|
||||
tab.views = append(tab.views, newView)
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *View) VSplit() bool {
|
||||
// VSplit opens a vertical split with the given buffer
|
||||
func (v *View) VSplit(buf *Buffer) bool {
|
||||
origDimensions := [2]int{v.widthPercent, v.heightPercent}
|
||||
origPos := [2]int{v.x, v.y}
|
||||
|
||||
v.widthPercent /= 2
|
||||
v.Resize(screen.Size())
|
||||
|
||||
newView := NewViewWidthHeight(NewBuffer([]byte{}, ""), v.widthPercent, v.heightPercent)
|
||||
newView := NewViewWidthHeight(buf, v.widthPercent, v.heightPercent)
|
||||
|
||||
v.splitOrigDimensions = origDimensions
|
||||
v.splitOrigPos = origPos
|
||||
newView.splitOrigDimensions = origDimensions
|
||||
newView.splitOrigPos = origPos
|
||||
|
||||
newView.TabNum = v.TabNum
|
||||
newView.y = v.y
|
||||
newView.x = v.x + v.width
|
||||
tab := tabs[v.TabNum]
|
||||
tab.curView++
|
||||
newView.Num = len(tab.views)
|
||||
newView.splitParent = v
|
||||
v.splitChild = newView
|
||||
tab.views = append(tab.views, newView)
|
||||
return false
|
||||
}
|
||||
|
@ -638,7 +667,7 @@ func (v *View) DisplayView() {
|
|||
lineStyle = highlightStyle
|
||||
}
|
||||
|
||||
if settings["cursorline"].(bool) && !v.Cursor.HasSelection() && v.Cursor.Y == lineN+v.Topline {
|
||||
if settings["cursorline"].(bool) && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == lineN+v.Topline {
|
||||
if style, ok := colorscheme["cursor-line"]; ok {
|
||||
fg, _, _ := style.Decompose()
|
||||
lineStyle = lineStyle.Background(fg)
|
||||
|
@ -742,7 +771,9 @@ func (v *View) DisplayCursor() {
|
|||
// Display renders the view, the cursor, and statusline
|
||||
func (v *View) Display() {
|
||||
v.DisplayView()
|
||||
v.DisplayCursor()
|
||||
if v.Num == tabs[curTab].curView {
|
||||
v.DisplayCursor()
|
||||
}
|
||||
if settings["statusline"].(bool) {
|
||||
v.sline.Display()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue