]> git.lizzy.rs Git - micro.git/blob - cmd/micro/display/infowindow.go
Infobar prompts
[micro.git] / cmd / micro / display / infowindow.go
1 package display
2
3 import (
4         "unicode/utf8"
5
6         runewidth "github.com/mattn/go-runewidth"
7         "github.com/zyedidia/micro/cmd/micro/buffer"
8         "github.com/zyedidia/micro/cmd/micro/config"
9         "github.com/zyedidia/micro/cmd/micro/info"
10         "github.com/zyedidia/micro/cmd/micro/screen"
11         "github.com/zyedidia/micro/cmd/micro/util"
12         "github.com/zyedidia/tcell"
13 )
14
15 type InfoWindow struct {
16         *info.Bar
17         *View
18
19         defStyle tcell.Style
20         errStyle tcell.Style
21
22         width int
23         y     int
24 }
25
26 func NewInfoWindow(b *info.Bar) *InfoWindow {
27         iw := new(InfoWindow)
28         iw.Bar = b
29         iw.View = new(View)
30
31         iw.defStyle = config.DefStyle
32
33         if _, ok := config.Colorscheme["message"]; ok {
34                 iw.defStyle = config.Colorscheme["message"]
35         }
36
37         iw.errStyle = config.DefStyle.
38                 Foreground(tcell.ColorBlack).
39                 Background(tcell.ColorMaroon)
40
41         if _, ok := config.Colorscheme["error-message"]; ok {
42                 iw.errStyle = config.Colorscheme["error-message"]
43         }
44
45         iw.width, iw.y = screen.Screen.Size()
46         iw.y--
47
48         return iw
49 }
50
51 func (i *InfoWindow) Relocate() bool  { return false }
52 func (i *InfoWindow) GetView() *View  { return i.View }
53 func (i *InfoWindow) SetView(v *View) {}
54
55 func (i *InfoWindow) Clear() {
56         for x := 0; x < i.width; x++ {
57                 screen.Screen.SetContent(x, i.y, ' ', nil, config.DefStyle)
58         }
59 }
60
61 func (i *InfoWindow) displayBuffer() {
62         b := i.Buffer
63         line := b.LineBytes(0)
64         activeC := b.GetActiveCursor()
65
66         blocX := 0
67         vlocX := utf8.RuneCountInString(i.Msg)
68
69         tabsize := 4
70         line, nColsBeforeStart := util.SliceVisualEnd(line, blocX, tabsize)
71
72         draw := func(r rune, style tcell.Style) {
73                 if nColsBeforeStart <= 0 {
74                         bloc := buffer.Loc{X: blocX, Y: 0}
75                         if activeC.HasSelection() &&
76                                 (bloc.GreaterEqual(activeC.CurSelection[0]) && bloc.LessThan(activeC.CurSelection[1]) ||
77                                         bloc.LessThan(activeC.CurSelection[0]) && bloc.GreaterEqual(activeC.CurSelection[1])) {
78                                 // The current character is selected
79                                 style = config.DefStyle.Reverse(true)
80
81                                 if s, ok := config.Colorscheme["selection"]; ok {
82                                         style = s
83                                 }
84
85                         }
86
87                         screen.Screen.SetContent(vlocX, i.y, r, nil, style)
88                         vlocX++
89                 }
90                 nColsBeforeStart--
91         }
92
93         totalwidth := blocX - nColsBeforeStart
94         for len(line) > 0 {
95                 if activeC.X == blocX {
96                         screen.Screen.ShowCursor(vlocX, i.y)
97                 }
98
99                 r, size := utf8.DecodeRune(line)
100
101                 draw(r, i.defStyle)
102
103                 width := 0
104
105                 char := ' '
106                 switch r {
107                 case '\t':
108                         ts := tabsize - (totalwidth % tabsize)
109                         width = ts
110                 default:
111                         width = runewidth.RuneWidth(r)
112                         char = '@'
113                 }
114
115                 blocX++
116                 line = line[size:]
117
118                 // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
119                 if width > 1 {
120                         for j := 1; j < width; j++ {
121                                 draw(char, i.defStyle)
122                         }
123                 }
124                 totalwidth += width
125                 if vlocX >= i.width {
126                         break
127                 }
128         }
129         if activeC.X == blocX {
130                 screen.Screen.ShowCursor(vlocX, i.y)
131         }
132 }
133
134 func (i *InfoWindow) Display() {
135         x := 0
136         if i.HasPrompt || config.GlobalSettings["infobar"].(bool) {
137                 if !i.HasPrompt && !i.HasMessage && !i.HasError {
138                         return
139                 }
140                 style := i.defStyle
141
142                 if i.HasError {
143                         style = i.errStyle
144                 }
145
146                 display := i.Msg
147                 for _, c := range display {
148                         screen.Screen.SetContent(x, i.y, c, nil, style)
149                         x += runewidth.RuneWidth(c)
150                 }
151
152                 if i.HasPrompt {
153                         i.displayBuffer()
154                 }
155         }
156 }