From 5825353f64b8d8927c2b4a0198882f17985e5c1c Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 14 Jan 2019 00:57:39 -0500 Subject: [PATCH] Add some commands --- cmd/micro/action/bufhandler.go | 23 +++++++- cmd/micro/action/command.go | 101 ++++++++++++++++++++++++++++++++ cmd/micro/action/infohandler.go | 2 +- cmd/micro/action/pane.go | 8 +-- cmd/micro/buffer/buffer.go | 16 ++--- cmd/micro/display/bufwindow.go | 4 ++ cmd/micro/display/infowindow.go | 4 ++ cmd/micro/display/window.go | 5 ++ cmd/micro/util/util.go | 12 ++++ 9 files changed, 160 insertions(+), 15 deletions(-) diff --git a/cmd/micro/action/bufhandler.go b/cmd/micro/action/bufhandler.go index d23a40b6..23362eb0 100644 --- a/cmd/micro/action/bufhandler.go +++ b/cmd/micro/action/bufhandler.go @@ -53,7 +53,7 @@ func BufMapMouse(k MouseEvent, action string) { // The ActionHandler can access the window for necessary info about // visual positions for mouse clicks and scrolling type BufHandler struct { - display.Window + display.BWindow Buf *buffer.Buffer @@ -98,10 +98,10 @@ type BufHandler struct { splitID uint64 } -func NewBufHandler(buf *buffer.Buffer, win display.Window) *BufHandler { +func NewBufHandler(buf *buffer.Buffer, win display.BWindow) *BufHandler { h := new(BufHandler) h.Buf = buf - h.Window = win + h.BWindow = win h.Cursor = h.Buf.GetActiveCursor() h.mouseReleased = true @@ -109,6 +109,23 @@ func NewBufHandler(buf *buffer.Buffer, win display.Window) *BufHandler { return h } +func (h *BufHandler) OpenBuffer(b *buffer.Buffer) { + h.Buf.Close() + h.Buf = b + h.BWindow.SetBuffer(b) + h.Cursor = b.GetActiveCursor() + v := new(display.View) + h.SetView(v) + h.Relocate() + // Set mouseReleased to true because we assume the mouse is not being pressed when + // the editor is opened + h.mouseReleased = true + // Set isOverwriteMode to false, because we assume we are in the default mode when editor + // is opened + h.isOverwriteMode = false + h.lastClickTime = time.Time{} +} + func (h *BufHandler) ID() uint64 { return h.splitID } diff --git a/cmd/micro/action/command.go b/cmd/micro/action/command.go index e4525ab0..9240b088 100644 --- a/cmd/micro/action/command.go +++ b/cmd/micro/action/command.go @@ -2,6 +2,9 @@ package action import ( "os" + "path/filepath" + "strconv" + "strings" "github.com/zyedidia/micro/cmd/micro/buffer" "github.com/zyedidia/micro/cmd/micro/config" @@ -152,10 +155,55 @@ func (h *BufHandler) RawCmd(args []string) { // TabSwitchCmd switches to a given tab either by name or by number func (h *BufHandler) TabSwitchCmd(args []string) { + if len(args) > 0 { + num, err := strconv.Atoi(args[0]) + if err != nil { + // Check for tab with this name + + found := false + for i, t := range Tabs.List { + if t.Panes[t.active].Name() == args[0] { + Tabs.SetActive(i) + found = true + } + } + if !found { + InfoBar.Error("Could not find tab: ", err) + } + } else { + num-- + if num >= 0 && num < len(Tabs.List) { + Tabs.SetActive(num) + } else { + InfoBar.Error("Invalid tab index") + } + } + } } // CdCmd changes the current working directory func (h *BufHandler) CdCmd(args []string) { + if len(args) > 0 { + path, err := util.ReplaceHome(args[0]) + if err != nil { + InfoBar.Error(err) + return + } + err = os.Chdir(path) + if err != nil { + InfoBar.Error(err) + return + } + wd, _ := os.Getwd() + for _, b := range buffer.OpenBuffers { + if len(b.Path) > 0 { + b.Path, _ = util.MakeRelative(b.AbsPath, wd) + if p, _ := filepath.Abs(b.Path); !strings.Contains(p, wd) { + b.Path = b.AbsPath + } + } + } + } } // MemUsageCmd prints micro's memory usage @@ -181,6 +229,39 @@ func (h *BufHandler) PwdCmd(args []string) { // OpenCmd opens a new buffer with a given filename func (h *BufHandler) OpenCmd(args []string) { + if len(args) > 0 { + filename := args[0] + // the filename might or might not be quoted, so unquote first then join the strings. + args, err := shellwords.Split(filename) + if err != nil { + InfoBar.Error("Error parsing args ", err) + return + } + filename = strings.Join(args, " ") + + open := func() { + b, err := buffer.NewBufferFromFile(filename, buffer.BTDefault) + if err != nil { + InfoBar.Error(err) + return + } + h.OpenBuffer(b) + } + if h.Buf.Modified() { + InfoBar.YNPrompt("Save changes to "+h.Buf.GetName()+" before closing? (y,n,esc)", func(yes, canceled bool) { + if !canceled && !yes { + open() + } else if !canceled && yes { + h.Save() + open() + } + }) + } else { + open() + } + } else { + InfoBar.Error("No filename") + } } // ToggleLogCmd toggles the log view @@ -341,6 +422,24 @@ func (h *BufHandler) SetLocalCmd(args []string) { // ShowCmd shows the value of the given option func (h *BufHandler) ShowCmd(args []string) { + if len(args) < 1 { + InfoBar.Error("Please provide an option to show") + return + } + + var option interface{} + if opt, ok := h.Buf.Settings[args[0]]; ok { + option = opt + } else if opt, ok := config.GlobalSettings[args[0]]; ok { + option = opt + } + + if option == nil { + InfoBar.Error(args[0], " is not a valid option") + return + } + + InfoBar.Message(option) } // ShowKeyCmd displays the action that a key is bound to @@ -376,10 +475,12 @@ func (h *BufHandler) RunCmd(args []string) { // QuitCmd closes the main view func (h *BufHandler) QuitCmd(args []string) { + h.Quit() } // SaveCmd saves the buffer in the main view func (h *BufHandler) SaveCmd(args []string) { + h.Save() } // ReplaceCmd runs search and replace diff --git a/cmd/micro/action/infohandler.go b/cmd/micro/action/infohandler.go index bc0a5ad1..337393bf 100644 --- a/cmd/micro/action/infohandler.go +++ b/cmd/micro/action/infohandler.go @@ -15,7 +15,7 @@ type InfoHandler struct { *info.InfoBuf } -func NewInfoHandler(ib *info.InfoBuf, w display.Window) *InfoHandler { +func NewInfoHandler(ib *info.InfoBuf, w display.BWindow) *InfoHandler { ih := new(InfoHandler) ih.InfoBuf = ib ih.BufHandler = NewBufHandler(ib.Buffer, w) diff --git a/cmd/micro/action/pane.go b/cmd/micro/action/pane.go index f7db4b68..8da64e5e 100644 --- a/cmd/micro/action/pane.go +++ b/cmd/micro/action/pane.go @@ -15,12 +15,12 @@ type Pane interface { } type EditPane struct { - display.Window + display.BWindow *BufHandler } type InfoPane struct { - display.Window + display.BWindow *InfoHandler *info.InfoBuf } @@ -29,7 +29,7 @@ func NewBufEditPane(x, y, width, height int, b *buffer.Buffer) *EditPane { e := new(EditPane) // TODO: can probably replace editpane with bufhandler entirely w := display.NewBufWindow(x, y, width, height, b) - e.Window = w + e.BWindow = w e.BufHandler = NewBufHandler(b, w) return e @@ -39,7 +39,7 @@ func NewInfoBar() *InfoPane { e := new(InfoPane) ib := info.NewBuffer() w := display.NewInfoWindow(ib) - e.Window = w + e.BWindow = w e.InfoHandler = NewInfoHandler(ib, w) e.InfoBuf = ib diff --git a/cmd/micro/buffer/buffer.go b/cmd/micro/buffer/buffer.go index 9fd6a5f3..f5c83ea0 100644 --- a/cmd/micro/buffer/buffer.go +++ b/cmd/micro/buffer/buffer.go @@ -133,13 +133,15 @@ func NewBuffer(reader io.Reader, size int64, path string, cursorPosition []strin config.InitLocalSettings(b.Settings, b.Path) found := false - for _, buf := range OpenBuffers { - if buf.AbsPath == absPath { - found = true - b.LineArray = buf.LineArray - b.EventHandler = buf.EventHandler - b.ModTime = buf.ModTime - b.isModified = buf.isModified + if len(path) > 0 { + for _, buf := range OpenBuffers { + if buf.AbsPath == absPath { + found = true + b.LineArray = buf.LineArray + b.EventHandler = buf.EventHandler + b.ModTime = buf.ModTime + b.isModified = buf.isModified + } } } diff --git a/cmd/micro/display/bufwindow.go b/cmd/micro/display/bufwindow.go index e22703cb..cee7164d 100644 --- a/cmd/micro/display/bufwindow.go +++ b/cmd/micro/display/bufwindow.go @@ -41,6 +41,10 @@ func NewBufWindow(x, y, width, height int, buf *buffer.Buffer) *BufWindow { return w } +func (w *BufWindow) SetBuffer(b *buffer.Buffer) { + w.Buf = b +} + func (v *View) GetView() *View { return v } diff --git a/cmd/micro/display/infowindow.go b/cmd/micro/display/infowindow.go index 44a5b48d..d559693c 100644 --- a/cmd/micro/display/infowindow.go +++ b/cmd/micro/display/infowindow.go @@ -53,6 +53,10 @@ func (i *InfoWindow) Resize(w, h int) { i.y = h } +func (i *InfoWindow) SetBuffer(b *buffer.Buffer) { + i.InfoBuf.Buffer = b +} + // func (i *InfoWindow) YesNoPrompt() (bool, bool) { // for { // i.Clear() diff --git a/cmd/micro/display/window.go b/cmd/micro/display/window.go index c83a453a..5983de70 100644 --- a/cmd/micro/display/window.go +++ b/cmd/micro/display/window.go @@ -24,3 +24,8 @@ type Window interface { Resize(w, h int) SetActive(b bool) } + +type BWindow interface { + Window + SetBuffer(b *buffer.Buffer) +} diff --git a/cmd/micro/util/util.go b/cmd/micro/util/util.go index bec680f1..53cac87a 100644 --- a/cmd/micro/util/util.go +++ b/cmd/micro/util/util.go @@ -195,6 +195,18 @@ func RunePos(b []byte, i int) int { return utf8.RuneCount(b[:i]) } +// MakeRelative will attempt to make a relative path between path and base +func MakeRelative(path, base string) (string, error) { + if len(path) > 0 { + rel, err := filepath.Rel(base, path) + if err != nil { + return path, err + } + return rel, nil + } + return path, nil +} + // TODO: consider changing because of snap segfault // ReplaceHome takes a path as input and replaces ~ at the start of the path with the user's // home directory. Does nothing if the path does not start with '~'.