]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/command.go
Use messenger error instead of termerror
[micro.git] / cmd / micro / command.go
index 4264fbdf6b9b4e817bfa36b05817f1f14b0e49c6..7ef885133cc92d5eb2edb85b07efe96d74c86bb5 100644 (file)
@@ -9,17 +9,21 @@ import (
        "os/signal"
        "path/filepath"
        "regexp"
+       "runtime"
        "strconv"
        "strings"
 
+       humanize "github.com/dustin/go-humanize"
        "github.com/mitchellh/go-homedir"
 )
 
+// A Command contains a action (a function to call) as well as information about how to autocomplete the command
 type Command struct {
        action      func([]string)
        completions []Completion
 }
 
+// A StrCommand is similar to a command but keeps the name of the action
 type StrCommand struct {
        action      string
        completions []Completion
@@ -51,6 +55,7 @@ func init() {
                "Pwd":       Pwd,
                "Open":      Open,
                "TabSwitch": TabSwitch,
+               "MemUsage":  MemUsage,
        }
 }
 
@@ -104,6 +109,7 @@ func DefaultCommands() map[string]StrCommand {
                "pwd":       {"Pwd", []Completion{NoCompletion}},
                "open":      {"Open", []Completion{FileCompletion}},
                "tabswitch": {"TabSwitch", []Completion{NoCompletion}},
+               "memusage":  {"MemUsage", []Completion{NoCompletion}},
        }
 }
 
@@ -190,6 +196,7 @@ func PluginCmd(args []string) {
        }
 }
 
+// TabSwitch switches to a given tab either by name or by number
 func TabSwitch(args []string) {
        if len(args) > 0 {
                num, err := strconv.Atoi(args[0])
@@ -200,7 +207,7 @@ func TabSwitch(args []string) {
                        for _, t := range tabs {
                                v := t.views[t.CurView]
                                if v.Buf.GetName() == args[0] {
-                                       curTab = v.Num
+                                       curTab = v.TabNum
                                        found = true
                                }
                        }
@@ -218,6 +225,7 @@ func TabSwitch(args []string) {
        }
 }
 
+// Cd changes the current working directory
 func Cd(args []string) {
        if len(args) > 0 {
                home, _ := homedir.Dir()
@@ -235,6 +243,21 @@ func Cd(args []string) {
        }
 }
 
+// MemUsage prints micro's memory usage
+// Alloc shows how many bytes are currently in use
+// Sys shows how many bytes have been requested from the operating system
+// NumGC shows how many times the GC has been run
+// Note that Go commonly reserves more memory from the OS than is currently in-use/required
+// Additionally, even if Go returns memory to the OS, the OS does not always claim it because
+// there may be plenty of memory to spare
+func MemUsage(args []string) {
+       var mem runtime.MemStats
+       runtime.ReadMemStats(&mem)
+
+       messenger.Message(fmt.Sprintf("Alloc: %v, Sys: %v, NumGC: %v", humanize.Bytes(mem.Alloc), humanize.Bytes(mem.Sys), mem.NumGC))
+}
+
+// Pwd prints the current working directory
 func Pwd(args []string) {
        wd, err := os.Getwd()
        if err != nil {
@@ -244,6 +267,7 @@ func Pwd(args []string) {
        }
 }
 
+// Open opens a new buffer with a given filename
 func Open(args []string) {
        if len(args) > 0 {
                filename := args[0]
@@ -256,6 +280,7 @@ func Open(args []string) {
        }
 }
 
+// ToggleLog toggles the log view
 func ToggleLog(args []string) {
        buffer := messenger.getBuffer()
        if CurView().Type != vtLog {
@@ -271,6 +296,7 @@ func ToggleLog(args []string) {
        }
 }
 
+// Reload reloads all files (syntax files, colorschemes...)
 func Reload(args []string) {
        LoadAll()
 }
@@ -294,20 +320,27 @@ func Help(args []string) {
 // If no file is given, it opens an empty buffer in a new split
 func VSplit(args []string) {
        if len(args) == 0 {
-               CurView().VSplit(NewBuffer(strings.NewReader(""), ""))
+               CurView().VSplit(NewBufferFromString("", ""))
        } else {
                filename := args[0]
                home, _ := homedir.Dir()
                filename = strings.Replace(filename, "~", home, 1)
                file, err := os.Open(filename)
+               fileInfo, _ := os.Stat(filename)
+
+               if err == nil && fileInfo.IsDir() {
+                       messenger.Error(filename, " is a directory")
+                       return
+               }
+
                defer file.Close()
 
                var buf *Buffer
                if err != nil {
                        // File does not exist -- create an empty buffer with that name
-                       buf = NewBuffer(strings.NewReader(""), filename)
+                       buf = NewBufferFromString("", filename)
                } else {
-                       buf = NewBuffer(file, filename)
+                       buf = NewBuffer(file, FSize(file), filename)
                }
                CurView().VSplit(buf)
        }
@@ -317,20 +350,27 @@ func VSplit(args []string) {
 // If no file is given, it opens an empty buffer in a new split
 func HSplit(args []string) {
        if len(args) == 0 {
-               CurView().HSplit(NewBuffer(strings.NewReader(""), ""))
+               CurView().HSplit(NewBufferFromString("", ""))
        } else {
                filename := args[0]
                home, _ := homedir.Dir()
                filename = strings.Replace(filename, "~", home, 1)
                file, err := os.Open(filename)
+               fileInfo, _ := os.Stat(filename)
+
+               if err == nil && fileInfo.IsDir() {
+                       messenger.Error(filename, " is a directory")
+                       return
+               }
+
                defer file.Close()
 
                var buf *Buffer
                if err != nil {
                        // File does not exist -- create an empty buffer with that name
-                       buf = NewBuffer(strings.NewReader(""), filename)
+                       buf = NewBufferFromString("", filename)
                } else {
-                       buf = NewBuffer(file, filename)
+                       buf = NewBuffer(file, FSize(file), filename)
                }
                CurView().HSplit(buf)
        }
@@ -356,10 +396,24 @@ func NewTab(args []string) {
                filename := args[0]
                home, _ := homedir.Dir()
                filename = strings.Replace(filename, "~", home, 1)
-               file, _ := os.Open(filename)
+               file, err := os.Open(filename)
+               fileInfo, _ := os.Stat(filename)
+
+               if err == nil && fileInfo.IsDir() {
+                       messenger.Error(filename, " is a directory")
+                       return
+               }
+
                defer file.Close()
 
-               tab := NewTabFromView(NewView(NewBuffer(file, filename)))
+               var buf *Buffer
+               if err != nil {
+                       buf = NewBufferFromString("", filename)
+               } else {
+                       buf = NewBuffer(file, FSize(file), filename)
+               }
+
+               tab := NewTabFromView(NewView(buf))
                tab.SetNum(len(tabs))
                tabs = append(tabs, tab)
                curTab = len(tabs) - 1
@@ -511,29 +565,25 @@ func Replace(args []string) {
                        }
                }
        } else {
-               bufStr := view.Buf.String()
-               matches := regex.FindAllStringIndex(bufStr, -1)
-               if matches != nil && len(matches) > 0 {
-                       prevMatchCount := runePos(matches[0][0], bufStr)
-                       searchCount := runePos(matches[0][1], bufStr) - prevMatchCount
-                       from := FromCharPos(matches[0][0], view.Buf)
-                       to := from.Move(searchCount, view.Buf)
-                       adjust := Count(replace) - searchCount
-                       view.Buf.Replace(from, to, replace)
-                       found++
-                       if len(matches) > 1 {
-                               for _, match := range matches[1:] {
-                                       found++
-                                       matchCount := runePos(match[0], bufStr)
-                                       searchCount = runePos(match[1], bufStr) - matchCount
-                                       from = from.Move(matchCount-prevMatchCount+adjust, view.Buf)
-                                       to = from.Move(searchCount, view.Buf)
+               // var deltas []Delta
+               for i := 0; i < view.Buf.LinesNum(); i++ {
+                       // view.Buf.lines[i].data = regex.ReplaceAll(view.Buf.lines[i].data, []byte(replace))
+                       for {
+                               m := regex.FindIndex(view.Buf.lines[i].data)
+
+                               if m != nil {
+                                       from := Loc{m[0], i}
+                                       to := Loc{m[1], i}
+
+                                       // deltas = append(deltas, Delta{replace, from, to})
                                        view.Buf.Replace(from, to, replace)
-                                       prevMatchCount = matchCount
-                                       adjust = Count(replace) - searchCount
+                                       found++
+                               } else {
+                                       break
                                }
                        }
                }
+               // view.Buf.MultipleReplace(deltas)
        }
        view.Cursor.Relocate()