6 runewidth "github.com/mattn/go-runewidth"
7 "github.com/zyedidia/micro/internal/buffer"
8 "github.com/zyedidia/micro/internal/config"
9 "github.com/zyedidia/micro/internal/info"
10 "github.com/zyedidia/micro/internal/screen"
11 "github.com/zyedidia/micro/internal/util"
12 "github.com/zyedidia/tcell"
15 type InfoWindow struct {
20 func (i *InfoWindow) errStyle() tcell.Style {
21 errStyle := config.DefStyle.
22 Foreground(tcell.ColorBlack).
23 Background(tcell.ColorMaroon)
25 if _, ok := config.Colorscheme["error-message"]; ok {
26 errStyle = config.Colorscheme["error-message"]
32 func (i *InfoWindow) defStyle() tcell.Style {
33 defStyle := config.DefStyle
35 if _, ok := config.Colorscheme["message"]; ok {
36 defStyle = config.Colorscheme["message"]
42 func NewInfoWindow(b *info.InfoBuf) *InfoWindow {
47 iw.Width, iw.Y = screen.Screen.Size()
53 func (i *InfoWindow) Resize(w, h int) {
58 func (i *InfoWindow) SetBuffer(b *buffer.Buffer) {
62 func (i *InfoWindow) Relocate() bool { return false }
63 func (i *InfoWindow) GetView() *View { return i.View }
64 func (i *InfoWindow) SetView(v *View) {}
65 func (i *InfoWindow) SetActive(b bool) {}
67 func (i *InfoWindow) GetMouseLoc(vloc buffer.Loc) buffer.Loc {
68 c := i.Buffer.GetActiveCursor()
69 l := i.Buffer.LineBytes(0)
70 n := utf8.RuneCountInString(i.Msg)
71 return buffer.Loc{c.GetCharPosInLine(l, vloc.X-n), 0}
74 func (i *InfoWindow) Clear() {
75 for x := 0; x < i.Width; x++ {
76 screen.Screen.SetContent(x, i.Y, ' ', nil, i.defStyle())
80 func (i *InfoWindow) displayBuffer() {
82 line := b.LineBytes(0)
83 activeC := b.GetActiveCursor()
86 vlocX := utf8.RuneCountInString(i.Msg)
89 line, nColsBeforeStart, bslice := util.SliceVisualEnd(line, blocX, tabsize)
92 draw := func(r rune, style tcell.Style) {
93 if nColsBeforeStart <= 0 {
94 bloc := buffer.Loc{X: blocX, Y: 0}
95 if activeC.HasSelection() &&
96 (bloc.GreaterEqual(activeC.CurSelection[0]) && bloc.LessThan(activeC.CurSelection[1]) ||
97 bloc.LessThan(activeC.CurSelection[0]) && bloc.GreaterEqual(activeC.CurSelection[1])) {
98 // The current character is selected
99 style = i.defStyle().Reverse(true)
101 if s, ok := config.Colorscheme["selection"]; ok {
107 rw := runewidth.RuneWidth(r)
108 for j := 0; j < rw; j++ {
113 screen.Screen.SetContent(vlocX, i.Y, c, nil, style)
120 totalwidth := blocX - nColsBeforeStart
122 if activeC.X == blocX {
123 screen.Screen.ShowCursor(vlocX, i.Y)
126 r, size := utf8.DecodeRune(line)
128 draw(r, i.defStyle())
135 ts := tabsize - (totalwidth % tabsize)
138 width = runewidth.RuneWidth(r)
145 // Draw any extra characters either spaces for tabs or @ for incomplete wide runes
147 for j := 1; j < width; j++ {
148 draw(char, i.defStyle())
152 if vlocX >= i.Width {
156 if activeC.X == blocX {
157 screen.Screen.ShowCursor(vlocX, i.Y)
161 var keydisplay = []string{"^Q Quit, ^S Save, ^O Open, ^G Help, ^E Command Bar, ^K Cut Line", "^F Find, ^Z Undo, ^Y Redo, ^A Select All, ^D Duplicate Line, ^T New Tab"}
163 func (i *InfoWindow) displayKeyMenu() {
164 // TODO: maybe make this based on the actual keybindings
166 for y := 0; y < len(keydisplay); y++ {
167 for x := 0; x < i.Width; x++ {
168 if x < len(keydisplay[y]) {
169 screen.Screen.SetContent(x, i.Y-len(keydisplay)+y, rune(keydisplay[y][x]), nil, i.defStyle())
171 screen.Screen.SetContent(x, i.Y-len(keydisplay)+y, ' ', nil, i.defStyle())
177 func (i *InfoWindow) Display() {
179 if config.GetGlobalOption("keymenu").(bool) {
183 if i.HasPrompt || config.GlobalSettings["infobar"].(bool) {
184 if !i.HasPrompt && !i.HasMessage && !i.HasError {
188 style := i.defStyle()
195 for _, c := range display {
196 screen.Screen.SetContent(x, i.Y, c, nil, style)
197 x += runewidth.RuneWidth(c)
205 if i.HasSuggestions && len(i.Suggestions) > 1 {
206 statusLineStyle := config.DefStyle.Reverse(true)
207 if style, ok := config.Colorscheme["statusline"]; ok {
208 statusLineStyle = style
211 if config.GetGlobalOption("keymenu").(bool) {
212 keymenuOffset = len(keydisplay)
215 for j, s := range i.Suggestions {
216 style := statusLineStyle
217 if i.CurSuggestion == j {
218 style = style.Reverse(true)
220 for _, r := range s {
221 screen.Screen.SetContent(x, i.Y-keymenuOffset-1, r, nil, style)
227 screen.Screen.SetContent(x, i.Y-keymenuOffset-1, ' ', nil, statusLineStyle)
235 screen.Screen.SetContent(x, i.Y-keymenuOffset-1, ' ', nil, statusLineStyle)