mirror of
https://github.com/zyedidia/micro.git
synced 2026-02-04 22:20:20 +09:00
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:
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user