]> git.lizzy.rs Git - micro.git/commitdiff
Add the ability to close splits and change splits using the mouse
authorZachary Yedidia <zyedidia@gmail.com>
Fri, 1 Jul 2016 22:12:37 +0000 (18:12 -0400)
committerZachary Yedidia <zyedidia@gmail.com>
Sat, 2 Jul 2016 21:41:23 +0000 (17:41 -0400)
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.

cmd/micro/bindings.go
cmd/micro/command.go
cmd/micro/micro.go
cmd/micro/view.go

index 613b80fb1299f43f087444f1bb47ce10ebc92b13..c3af4cb9cf50f12fba1d9270797db7a5c3a7819e 100644 (file)
@@ -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 {
index 05dd764584093181aeab4654dabd4c654026e087..54c2aa3d4e47d04ba5e08b17809122c24318acb9 100644 (file)
@@ -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
index 859277ab2e0b76ef5085d7e9b61080a79ff51f86..e62c93fafef491e10e428fb697b2b1d61b479be7 100644 (file)
@@ -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
+                                       }
+                               }
                        }
                }
 
index ff004fb94858d03b17b19549f70f69d903db185a..79d1dfa331e1bc297462c9020d4d2edd6f17799b 100644 (file)
@@ -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()
        }