]> git.lizzy.rs Git - micro.git/blobdiff - internal/display/statusline.go
Fix internal string binding representation
[micro.git] / internal / display / statusline.go
index 6731c2c8c995341a66a020086fd4504075a6b79d..947a3ee7b48b828dce783829f0367ac6f8ddfa2f 100644 (file)
@@ -3,16 +3,19 @@ package display
 import (
        "bytes"
        "fmt"
-       "path"
        "regexp"
        "strconv"
-       "unicode/utf8"
+       "strings"
+
+       luar "layeh.com/gopher-luar"
 
        runewidth "github.com/mattn/go-runewidth"
-       "github.com/zyedidia/micro/internal/buffer"
-       "github.com/zyedidia/micro/internal/config"
-       "github.com/zyedidia/micro/internal/screen"
-       "github.com/zyedidia/micro/internal/util"
+       lua "github.com/yuin/gopher-lua"
+       "github.com/zyedidia/micro/v2/internal/buffer"
+       "github.com/zyedidia/micro/v2/internal/config"
+       ulua "github.com/zyedidia/micro/v2/internal/lua"
+       "github.com/zyedidia/micro/v2/internal/screen"
+       "github.com/zyedidia/micro/v2/internal/util"
 )
 
 // StatusLine represents the information line at the bottom
@@ -25,31 +28,57 @@ type StatusLine struct {
        win *BufWindow
 }
 
-// TODO: plugin modify status line formatter
+var statusInfo = map[string]func(*buffer.Buffer) string{
+       "filename": func(b *buffer.Buffer) string {
+               return b.GetName()
+       },
+       "line": func(b *buffer.Buffer) string {
+               return strconv.Itoa(b.GetActiveCursor().Y + 1)
+       },
+       "col": func(b *buffer.Buffer) string {
+               return strconv.Itoa(b.GetActiveCursor().X + 1)
+       },
+       "modified": func(b *buffer.Buffer) string {
+               if b.Modified() {
+                       return "+ "
+               }
+               if b.Type.Readonly {
+                       return "[ro] "
+               }
+               return ""
+       },
+}
+
+func SetStatusInfoFnLua(fn string) {
+       luaFn := strings.Split(fn, ".")
+       if len(luaFn) <= 1 {
+               return
+       }
+       plName, plFn := luaFn[0], luaFn[1]
+       pl := config.FindPlugin(plName)
+       if pl == nil {
+               return
+       }
+       statusInfo[fn] = func(b *buffer.Buffer) string {
+               if pl == nil || !pl.IsEnabled() {
+                       return ""
+               }
+               val, err := pl.Call(plFn, luar.New(ulua.L, b))
+               if err == nil {
+                       if v, ok := val.(lua.LString); !ok {
+                               screen.TermMessage(plFn, "should return a string")
+                               return ""
+                       } else {
+                               return string(v)
+                       }
+               }
+               return ""
+       }
+}
 
 // NewStatusLine returns a statusline bound to a window
 func NewStatusLine(win *BufWindow) *StatusLine {
        s := new(StatusLine)
-       s.Info = map[string]func(*buffer.Buffer) string{
-               "filename": func(b *buffer.Buffer) string {
-                       if b.Settings["basename"].(bool) {
-                               return path.Base(b.GetName())
-                       }
-                       return b.GetName()
-               },
-               "line": func(b *buffer.Buffer) string {
-                       return strconv.Itoa(b.GetActiveCursor().Y + 1)
-               },
-               "col": func(b *buffer.Buffer) string {
-                       return strconv.Itoa(b.GetActiveCursor().X + 1)
-               },
-               "modified": func(b *buffer.Buffer) string {
-                       if b.Modified() {
-                               return "+ "
-                       }
-                       return ""
-               },
-       }
        s.win = win
        return s
 }
@@ -69,16 +98,15 @@ func (s *StatusLine) Display() {
        // We'll draw the line at the lowest line in the window
        y := s.win.Height + s.win.Y - 1
 
+       winX := s.win.X
+
        b := s.win.Buf
+       // autocomplete suggestions (for the buffer, not for the infowindow)
        if b.HasSuggestions && len(b.Suggestions) > 1 {
                statusLineStyle := config.DefStyle.Reverse(true)
                if style, ok := config.Colorscheme["statusline"]; ok {
                        statusLineStyle = style
                }
-               keymenuOffset := 0
-               if config.GetGlobalOption("keymenu").(bool) {
-                       keymenuOffset = len(keydisplay)
-               }
                x := 0
                for j, sug := range b.Suggestions {
                        style := statusLineStyle
@@ -86,13 +114,13 @@ func (s *StatusLine) Display() {
                                style = style.Reverse(true)
                        }
                        for _, r := range sug {
-                               screen.Screen.SetContent(x, y-keymenuOffset, r, nil, style)
+                               screen.SetContent(winX+x, y, r, nil, style)
                                x++
                                if x >= s.win.Width {
                                        return
                                }
                        }
-                       screen.Screen.SetContent(x, y-keymenuOffset, ' ', nil, statusLineStyle)
+                       screen.SetContent(winX+x, y, ' ', nil, statusLineStyle)
                        x++
                        if x >= s.win.Width {
                                return
@@ -100,7 +128,7 @@ func (s *StatusLine) Display() {
                }
 
                for x < s.win.Width {
-                       screen.Screen.SetContent(x, y-keymenuOffset, ' ', nil, statusLineStyle)
+                       screen.SetContent(winX+x, y, ' ', nil, statusLineStyle)
                        x++
                }
                return
@@ -113,20 +141,23 @@ func (s *StatusLine) Display() {
                        return []byte(fmt.Sprint(s.FindOpt(string(option))))
                } else if bytes.HasPrefix(name, []byte("bind")) {
                        binding := string(name[5:])
-                       for k, v := range config.Bindings {
+                       for k, v := range config.Bindings["buffer"] {
                                if v == binding {
                                        return []byte(k)
                                }
                        }
                        return []byte("null")
                } else {
-                       return []byte(s.Info[string(name)](s.win.Buf))
+                       if fn, ok := statusInfo[string(name)]; ok {
+                               return []byte(fn(s.win.Buf))
+                       }
+                       return []byte{}
                }
        }
 
-       leftText := []byte(s.win.Buf.StatusFormatLeft)
+       leftText := []byte(s.win.Buf.Settings["statusformatl"].(string))
        leftText = formatParser.ReplaceAllFunc(leftText, formatter)
-       rightText := []byte(s.win.Buf.StatusFormatRight)
+       rightText := []byte(s.win.Buf.Settings["statusformatr"].(string))
        rightText = formatParser.ReplaceAllFunc(rightText, formatter)
 
        statusLineStyle := config.DefStyle.Reverse(true)
@@ -134,37 +165,38 @@ func (s *StatusLine) Display() {
                statusLineStyle = style
        }
 
-       leftLen := util.StringWidth(leftText, utf8.RuneCount(leftText), 1)
-       rightLen := util.StringWidth(rightText, utf8.RuneCount(rightText), 1)
+       leftLen := util.StringWidth(leftText, util.CharacterCount(leftText), 1)
+       rightLen := util.StringWidth(rightText, util.CharacterCount(rightText), 1)
 
-       winX := s.win.X
        for x := 0; x < s.win.Width; x++ {
                if x < leftLen {
-                       r, size := utf8.DecodeRune(leftText)
+                       r, combc, size := util.DecodeCharacter(leftText)
                        leftText = leftText[size:]
                        rw := runewidth.RuneWidth(r)
                        for j := 0; j < rw; j++ {
                                c := r
                                if j > 0 {
                                        c = ' '
+                                       combc = nil
                                        x++
                                }
-                               screen.Screen.SetContent(winX+x, y, c, nil, statusLineStyle)
+                               screen.SetContent(winX+x, y, c, combc, statusLineStyle)
                        }
                } else if x >= s.win.Width-rightLen && x < rightLen+s.win.Width-rightLen {
-                       r, size := utf8.DecodeRune(rightText)
+                       r, combc, size := util.DecodeCharacter(rightText)
                        rightText = rightText[size:]
                        rw := runewidth.RuneWidth(r)
                        for j := 0; j < rw; j++ {
                                c := r
                                if j > 0 {
                                        c = ' '
+                                       combc = nil
                                        x++
                                }
-                               screen.Screen.SetContent(winX+x, y, c, nil, statusLineStyle)
+                               screen.SetContent(winX+x, y, c, combc, statusLineStyle)
                        }
                } else {
-                       screen.Screen.SetContent(winX+x, y, ' ', nil, statusLineStyle)
+                       screen.SetContent(winX+x, y, ' ', nil, statusLineStyle)
                }
        }
 }