From b3b7e8414d080cd820825d0d407036da34559b1c Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Thu, 17 Mar 2016 18:20:07 -0400 Subject: [PATCH] Add statusline --- buffer.go | 1 + cursor.go | 6 +++++- micro.go | 22 ++++++++++++++++------ statusline.go | 33 +++++++++++++++++++++++++++++++++ view.go | 50 +++++++++++++++++++++++++++++++++++--------------- 5 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 statusline.go diff --git a/buffer.go b/buffer.go index 7e59cf33..9fdc33fc 100644 --- a/buffer.go +++ b/buffer.go @@ -42,6 +42,7 @@ func (b *Buffer) save() error { } func (b *Buffer) saveAs(filename string) error { + b.savedText = b.text err := ioutil.WriteFile(filename, []byte(b.text), 0644) return err } diff --git a/cursor.go b/cursor.go index d5aa48d8..61bf74f9 100644 --- a/cursor.go +++ b/cursor.go @@ -95,6 +95,10 @@ func (c *Cursor) getCharPos(lineNum, visualPos int) int { return visualPos - (tabSize-1)*numTabs } +func (c *Cursor) getVisualX() int { + return c.x + numOccurences(c.v.buf.lines[c.y][:c.x], '\t')*(tabSize-1) +} + func (c *Cursor) distance(x, y int) int { // Same line if y == c.y { @@ -138,7 +142,7 @@ func (c *Cursor) distance(x, y int) int { } func (c *Cursor) display() { - if c.y-c.v.topline < 0 || c.y-c.v.topline > c.v.linesN-1 { + if c.y-c.v.topline < 0 || c.y-c.v.topline > c.v.height-1 { c.v.s.HideCursor() } else { voffset := numOccurences(c.v.buf.lines[c.y][:c.x], '\t') * (tabSize - 1) diff --git a/micro.go b/micro.go index 0b6e21fb..b5a55217 100644 --- a/micro.go +++ b/micro.go @@ -19,12 +19,14 @@ func main() { if len(os.Args) > 1 { filename = os.Args[1] - var err error - input, err = ioutil.ReadFile(filename) + if _, err := os.Stat(filename); err == nil { + var err error + input, err = ioutil.ReadFile(filename) - if err != nil { - fmt.Println(err) - os.Exit(1) + if err != nil { + fmt.Println(err) + os.Exit(1) + } } } else if !isatty.IsTerminal(os.Stdin.Fd()) { bytes, err := ioutil.ReadAll(os.Stdin) @@ -44,9 +46,15 @@ func main() { fmt.Fprintf(os.Stderr, "%v\n", e) os.Exit(1) } + + defStyle := tcell.StyleDefault. + Background(tcell.ColorDefault). + Foreground(tcell.ColorDefault) + + s.SetStyle(defStyle) s.EnableMouse() - v := newViewFromBuffer(newBuffer(string(input), filename), s) + v := newView(newBuffer(string(input), filename), s) // Initially everything needs to be drawn redraw := 2 @@ -55,9 +63,11 @@ func main() { s.Clear() v.display() v.cursor.display() + v.sl.display() s.Show() } else if redraw == 1 { v.cursor.display() + v.sl.display() s.Show() } diff --git a/statusline.go b/statusline.go new file mode 100644 index 00000000..a7529d6d --- /dev/null +++ b/statusline.go @@ -0,0 +1,33 @@ +package main + +import ( + "github.com/gdamore/tcell" + "strconv" +) + +type Statusline struct { + v *View +} + +func (sl *Statusline) display() { + y := sl.v.height + + file := sl.v.buf.name + if file == "" { + file = "Untitled" + } + if sl.v.buf.text != sl.v.buf.savedText { + file += " +" + } + file += " (" + strconv.Itoa(sl.v.cursor.y+1) + "," + strconv.Itoa(sl.v.cursor.getVisualX()+1) + ")" + + statusLineStyle := tcell.StyleDefault.Background(tcell.ColorNavy).Foreground(tcell.ColorBlack) + + for x := 0; x < sl.v.width; x++ { + if x < count(file) { + sl.v.s.SetContent(x, y, []rune(file)[x], nil, statusLineStyle) + } else { + sl.v.s.SetContent(x, y, ' ', nil, statusLineStyle) + } + } +} diff --git a/view.go b/view.go index 67d6cf7e..652485f5 100644 --- a/view.go +++ b/view.go @@ -8,25 +8,31 @@ import ( type View struct { cursor Cursor topline int - linesN int - colsN int + height int + width int + + buf *Buffer + sl Statusline - buf *Buffer mouseReleased bool s tcell.Screen } -func newViewFromBuffer(buf *Buffer, s tcell.Screen) *View { +func newView(buf *Buffer, s tcell.Screen) *View { + w, h := s.Size() + return newViewWidthHeight(buf, s, w, h) +} + +func newViewWidthHeight(buf *Buffer, s tcell.Screen, w, h int) *View { v := new(View) v.buf = buf v.s = s - w, h := s.Size() v.topline = 0 - v.linesN = h - v.colsN = w + v.height = h - 2 + v.width = w v.cursor = Cursor{ x: 0, y: 0, @@ -34,12 +40,16 @@ func newViewFromBuffer(buf *Buffer, s tcell.Screen) *View { v: v, } + v.sl = Statusline{ + v: v, + } + return v } // Returns an int describing how the screen needs to be redrawn // 0: Screen does not need to be redrawn -// 1: Only the cursor needs to be redrawn +// 1: Only the cursor/statusline needs to be redrawn // 2: Everything needs to be redrawn func (v *View) handleEvent(event tcell.Event) int { var ret int @@ -62,6 +72,10 @@ func (v *View) handleEvent(event tcell.Event) int { v.buf.insert(v.cursor.loc, "\n") v.cursor.right() ret = 2 + case tcell.KeySpace: + v.buf.insert(v.cursor.loc, " ") + v.cursor.right() + ret = 2 case tcell.KeyBackspace2: if v.cursor.loc > 0 { v.cursor.left() @@ -72,6 +86,13 @@ func (v *View) handleEvent(event tcell.Event) int { v.buf.insert(v.cursor.loc, "\t") v.cursor.right() ret = 2 + case tcell.KeyCtrlS: + err := v.buf.save() + if err != nil { + // Error! + } + // Need to redraw the status line + ret = 1 case tcell.KeyRune: v.buf.insert(v.cursor.loc, string(e.Rune())) v.cursor.right() @@ -88,8 +109,8 @@ func (v *View) handleEvent(event tcell.Event) int { switch button { case tcell.Button1: - if y-v.topline > v.linesN-1 { - y = v.linesN + v.topline - 1 + if y-v.topline > v.height-1 { + y = v.height + v.topline - 1 } if y > len(v.buf.lines) { y = len(v.buf.lines) - 1 @@ -120,7 +141,7 @@ func (v *View) handleEvent(event tcell.Event) int { return 0 } case tcell.WheelDown: - if v.topline < len(v.buf.lines)-v.linesN { + if v.topline < len(v.buf.lines)-v.height { v.topline++ return 2 } else { @@ -134,8 +155,8 @@ func (v *View) handleEvent(event tcell.Event) int { v.topline = cy ret = 2 } - if cy > v.topline+v.linesN-1 { - v.topline = cy - v.linesN + 1 + if cy > v.topline+v.height-1 { + v.topline = cy - v.height + 1 ret = 2 } @@ -143,9 +164,8 @@ func (v *View) handleEvent(event tcell.Event) int { } func (v *View) display() { - var charNum int - for lineN := 0; lineN < v.linesN; lineN++ { + for lineN := 0; lineN < v.height; lineN++ { if lineN+v.topline >= len(v.buf.lines) { break }