55--- window; j/k/arrows navigate, <CR> confirms, <Esc> cancels.
66
77local config = require (" input-form.config" )
8+ local utils = require (" input-form.utils" )
89
910local M = {}
1011M .__index = M
@@ -47,35 +48,46 @@ local function label_for(options, id)
4748 return " "
4849end
4950
50- local function format_display (options , id )
51- return label_for (options , id )
51+ local CHEVRON_CLOSED = " ▼"
52+ local CHEVRON_OPEN = " ▲"
53+
54+ local function format_display (options , id , width , open )
55+ local label = label_for (options , id )
56+ local chevron = open and CHEVRON_OPEN or CHEVRON_CLOSED
57+ if not width or width <= 0 then
58+ return label .. chevron
59+ end
60+ local label_w = vim .fn .strdisplaywidth (label )
61+ local chev_w = vim .fn .strdisplaywidth (chevron )
62+ local pad = width - label_w - chev_w
63+ if pad < 1 then
64+ pad = 1
65+ end
66+ return label .. string.rep (" " , pad ) .. chevron
5267end
5368
5469function M :_render_display ()
5570 if self .buf and vim .api .nvim_buf_is_valid (self .buf ) then
71+ local line = format_display (self .options , self ._selected_id , self ._width , self ._open )
5672 vim .bo [self .buf ].modifiable = true
57- vim .api .nvim_buf_set_lines (
58- self .buf ,
59- 0 ,
60- - 1 ,
61- false ,
62- { format_display (self .options , self ._selected_id ) }
63- )
73+ vim .api .nvim_buf_set_lines (self .buf , 0 , - 1 , false , { line })
6474 vim .bo [self .buf ].modifiable = false
6575 end
6676end
6777
6878function M :mount (layout )
79+ self ._width = layout .width
6980 self .buf = vim .api .nvim_create_buf (false , true )
7081 vim .bo [self .buf ].buftype = " nofile"
7182 vim .bo [self .buf ].bufhidden = " wipe"
7283 vim .bo [self .buf ].swapfile = false
84+ utils .mark_form_buffer (self .buf )
7385 vim .api .nvim_buf_set_lines (
7486 self .buf ,
7587 0 ,
7688 - 1 ,
7789 false ,
78- { format_display (self .options , self ._selected_id ) }
90+ { format_display (self .options , self ._selected_id , self . _width , self . _open ) }
7991 )
8092 vim .bo [self .buf ].modifiable = false
8193
119131function M :focus ()
120132 if self .win and vim .api .nvim_win_is_valid (self .win ) then
121133 vim .api .nvim_set_current_win (self .win )
134+ -- Park the cursor at col 0 so the terminal cursor block sits on the label
135+ -- (clean state) or on the dirty-shifted chevron's left neighbour (dirty
136+ -- state), never on top of the chevron itself.
137+ pcall (vim .api .nvim_win_set_cursor , self .win , { 1 , 0 })
122138 end
123139end
124140
@@ -140,6 +156,7 @@ function M:open_dropdown()
140156 self .dropdown_buf = vim .api .nvim_create_buf (false , true )
141157 vim .bo [self .dropdown_buf ].buftype = " nofile"
142158 vim .bo [self .dropdown_buf ].bufhidden = " wipe"
159+ utils .mark_form_buffer (self .dropdown_buf )
143160 vim .api .nvim_buf_set_lines (self .dropdown_buf , 0 , - 1 , false , lines )
144161 vim .bo [self .dropdown_buf ].modifiable = false
145162
@@ -160,6 +177,8 @@ function M:open_dropdown()
160177 focusable = true ,
161178 zindex = 100 ,
162179 })
180+ self ._open = true
181+ self :_render_display ()
163182 vim .wo [self .dropdown_win ].cursorline = true
164183 vim .wo [self .dropdown_win ].winhl =
165184 " NormalFloat:InputFormDropdown,CursorLine:InputFormDropdownActive"
@@ -192,6 +211,8 @@ function M:close_dropdown()
192211 end
193212 self .dropdown_win = nil
194213 self .dropdown_buf = nil
214+ self ._open = false
215+ self :_render_display ()
195216 if self .win and vim .api .nvim_win_is_valid (self .win ) then
196217 vim .api .nvim_set_current_win (self .win )
197218 end
0 commit comments