]> git.lizzy.rs Git - micro.git/blob - cmd/micro/display/infowindow.go
Minor infobar improvements
[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) YesNoPrompt() (bool, bool) {
52 //      for {
53 //              i.Clear()
54 //              i.Display()
55 //              screen.Screen.ShowCursor(utf8.RuneCountInString(i.Msg), i.y)
56 //              screen.Show()
57 //              event := <-events
58 //
59 //              switch e := event.(type) {
60 //              case *tcell.EventKey:
61 //                      switch e.Key() {
62 //                      case tcell.KeyRune:
63 //                              if e.Rune() == 'y' || e.Rune() == 'Y' {
64 //                                      i.HasPrompt = false
65 //                                      return true, false
66 //                              } else if e.Rune() == 'n' || e.Rune() == 'N' {
67 //                                      i.HasPrompt = false
68 //                                      return false, false
69 //                              }
70 //                      case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
71 //                              i.Clear()
72 //                              i.Reset()
73 //                              i.HasPrompt = false
74 //                              return false, true
75 //                      }
76 //              }
77 //      }
78 // }
79
80 func (i *InfoWindow) Relocate() bool  { return false }
81 func (i *InfoWindow) GetView() *View  { return i.View }
82 func (i *InfoWindow) SetView(v *View) {}
83
84 func (i *InfoWindow) Clear() {
85         for x := 0; x < i.width; x++ {
86                 screen.Screen.SetContent(x, i.y, ' ', nil, config.DefStyle)
87         }
88 }
89
90 func (i *InfoWindow) displayBuffer() {
91         b := i.Buffer
92         line := b.LineBytes(0)
93         activeC := b.GetActiveCursor()
94
95         blocX := 0
96         vlocX := utf8.RuneCountInString(i.Msg)
97
98         tabsize := 4
99         line, nColsBeforeStart := util.SliceVisualEnd(line, blocX, tabsize)
100
101         draw := func(r rune, style tcell.Style) {
102                 if nColsBeforeStart <= 0 {
103                         bloc := buffer.Loc{X: blocX, Y: 0}
104                         if activeC.HasSelection() &&
105                                 (bloc.GreaterEqual(activeC.CurSelection[0]) && bloc.LessThan(activeC.CurSelection[1]) ||
106                                         bloc.LessThan(activeC.CurSelection[0]) && bloc.GreaterEqual(activeC.CurSelection[1])) {
107                                 // The current character is selected
108                                 style = config.DefStyle.Reverse(true)
109
110                                 if s, ok := config.Colorscheme["selection"]; ok {
111                                         style = s
112                                 }
113
114                         }
115
116                         screen.Screen.SetContent(vlocX, i.y, r, nil, style)
117                         vlocX++
118                 }
119                 nColsBeforeStart--
120         }
121
122         totalwidth := blocX - nColsBeforeStart
123         for len(line) > 0 {
124                 if activeC.X == blocX {
125                         screen.Screen.ShowCursor(vlocX, i.y)
126                 }
127
128                 r, size := utf8.DecodeRune(line)
129
130                 draw(r, i.defStyle)
131
132                 width := 0
133
134                 char := ' '
135                 switch r {
136                 case '\t':
137                         ts := tabsize - (totalwidth % tabsize)
138                         width = ts
139                 default:
140                         width = runewidth.RuneWidth(r)
141                         char = '@'
142                 }
143
144                 blocX++
145                 line = line[size:]
146
147                 // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
148                 if width > 1 {
149                         for j := 1; j < width; j++ {
150                                 draw(char, i.defStyle)
151                         }
152                 }
153                 totalwidth += width
154                 if vlocX >= i.width {
155                         break
156                 }
157         }
158         if activeC.X == blocX {
159                 screen.Screen.ShowCursor(vlocX, i.y)
160         }
161 }
162
163 func (i *InfoWindow) Display() {
164         x := 0
165         if i.HasPrompt || config.GlobalSettings["infobar"].(bool) {
166                 if !i.HasPrompt && !i.HasMessage && !i.HasError {
167                         return
168                 }
169                 style := i.defStyle
170
171                 if i.HasError {
172                         style = i.errStyle
173                 }
174
175                 display := i.Msg
176                 for _, c := range display {
177                         screen.Screen.SetContent(x, i.y, c, nil, style)
178                         x += runewidth.RuneWidth(c)
179                 }
180
181                 if i.HasPrompt {
182                         i.displayBuffer()
183                 }
184         }
185 }