@@ -232,10 +232,13 @@ function! arduino#GetBoards() abort
232232 if g: arduino_use_cli
233233 let boards_data = s: get_json_output (' arduino-cli board listall --format json' )
234234 for board in boards_data[' boards' ]
235- let boardname = board[' fqbn' ]
236- call add (boards, boardname)
235+ call add (boards, {
236+ \ ' label' : board[' name' ],
237+ \ ' value' : board[' fqbn' ]
238+ \ })
237239 endfor
238240 else
241+ let seen = {}
239242 for [dir ,meta] in items (s: hardware_dirs )
240243 if ! isdirectory (dir )
241244 continue
@@ -252,15 +255,19 @@ function! arduino#GetBoards() abort
252255 let linesplit = split (line , ' =' )
253256 let name = linesplit[1 ]
254257 let board = meta.package . ' :' . meta.arch . ' :' . board
255- if index (boards, board) == -1
256- call add (boards, board)
258+ if index (boards, board) == -1 && ! has_key (seen, board)
259+ let seen[board] = 1
260+ call add (boards, {
261+ \ ' label' : name,
262+ \ ' value' : board
263+ \ })
257264 endif
258265 endif
259266 endfor
260267 unlet dir meta
261268 endfor
262269 endif
263- call sort (boards, ' s:BoardOrder ' )
270+ call sort (boards, ' s:ChooserItemOrder ' )
264271 return boards
265272endfunction
266273
@@ -275,7 +282,10 @@ function! arduino#GetBoardOptions(board) abort
275282 for opt in opts
276283 let values = []
277284 for entry in opt [' values' ]
278- call add (values , entry[' value' ])
285+ call add (values , {
286+ \ ' label' : entry[' value_label' ],
287+ \ ' value' : entry[' value' ]
288+ \ })
279289 endfor
280290 let ret [opt [' option' ]] = values
281291 endfor
@@ -328,11 +338,14 @@ function! arduino#GetProgrammers() abort
328338 if g: arduino_use_cli
329339 let data = s: get_json_output (' arduino-cli board details ' . g: arduino_board . ' --list-programmers --format json' )
330340 for entry in data[' programmers' ]
331- call add (programmers, entry[' id' ])
341+ call add (programmers, {
342+ \ ' label' : entry[' name' ],
343+ \ ' value' : entry[' id' ],
344+ \ })
332345 endfor
333346 " I'm running into some issues with 3rd party boards (e.g. adafruit:avr:gemma) where the programmer list is empty. If so, fall back to the hardware directory method
334347 if ! empty (programmers)
335- return sort (programmers)
348+ return sort (programmers, ' s:ChooserItemOrder ' )
336349 endif
337350 endif
338351 for [dir ,meta] in items (s: hardware_dirs )
@@ -366,10 +379,10 @@ function! arduino#RebuildMakePrg() abort
366379 endif
367380endfunction
368381
369- function ! s: BoardOrder (b1, b2 ) abort
370- let c1 = split (a: b1 , ' : ' )[ 2 ]
371- let c2 = split (a: b2 , ' : ' )[ 2 ]
372- return c1 == c2 ? 0 : c1 > c2 ? 1 : -1
382+ function ! s: ChooserItemOrder (i1, i2 ) abort
383+ let l1 = has_key (a: i1 , ' label ' ) ? a: i1 [ ' label ' ] : a: i1 [ ' value ' ]
384+ let l2 = has_key (a: i2 , ' label ' ) ? a: i2 [ ' label ' ] : a: i2 [ ' value ' ]
385+ return l1 == l2 ? 0 : l1 > l2 ? 1 : -1
373386endfunction
374387
375388" Port selection {{{2
@@ -597,39 +610,85 @@ function! s:fzf_leave(callback, item)
597610 let s: fzf_counter -= 1
598611endfunction
599612function ! s: mk_fzf_callback (callback)
600- return { item - > s: fzf_leave (a: callback , item) }
613+ return { item - > s: fzf_leave (a: callback , s: ChooserValueFromLabel ( item) ) }
601614endfunction
602615
603- function ! arduino#Choose (title , items , callback) abort
616+ function ! s: ConvertItemsToLabels (items ) abort
617+ let longest = 1
618+ for item in a: items
619+ if has_key (item, ' label' )
620+ let longest = max ([longest, strchars (item[' label' ])])
621+ endif
622+ endfor
623+ return map (copy (a: items ), ' s:ChooserItemLabel(v:val, ' . longest . ' )' )
624+ endfunction
625+
626+ function ! s: ChooserItemLabel (item, ... ) abort
627+ let pad_amount = a: 0 ? a: 1 : 0
628+ if has_key (a: item , ' label' )
629+ let label = a: item [' label' ]
630+ let spacing = 1 + max ([pad_amount - strchars (label ), 0 ])
631+ return label . repeat (' ' , spacing) . ' [' . a: item [' value' ] . ' ]'
632+ endif
633+ return a: item [' value' ]
634+ endfunction
635+
636+ function ! s: ChooserValueFromLabel (label ) abort
637+ " The label may be in the format 'label [value]'.
638+ " If so, we need to parse out the value
639+ let groups = matchlist (a: label , ' \[\(.*\)\]$' )
640+ if empty (groups)
641+ return a: label
642+ else
643+ return groups[1 ]
644+ endif
645+ endfunction
646+
647+ " items should be a list of dictionary items with the following keys:
648+ " label (optional) The string to display
649+ " value The corresponding value passed to the callback
650+ " items may also be a raw list of strings. They will be treated as values
651+ function ! arduino#Choose (title , raw_items, callback) abort
652+ let items = []
653+ let dict_type = type ({})
654+ for item in a: raw_items
655+ if type (item) == dict_type
656+ call add (items , item)
657+ else
658+ call add (items , {' value' : item})
659+ endif
660+ endfor
661+
604662 if g: arduino_ctrlp_enabled
605663 let ext_data = get (g: ctrlp_ext_vars , s: ctrlp_idx )
606664 let ext_data.lname = a: title
607- let s: ctrlp_list = a: items
665+ let s: ctrlp_list = items
608666 let s: ctrlp_callback = a: callback
609667 call ctrlp#init (s: ctrlp_id )
610668 elseif g: arduino_fzf_enabled
611669 let s: fzf_counter += 1
612- call fzf#run ({' source' :a: items , ' sink' :s: mk_fzf_callback (a: callback ), ' options' :' --prompt="' .a: title .' : "' })
670+ call fzf#run ({
671+ \ ' source' : s: ConvertItemsToLabels (items ),
672+ \ ' sink' : s: mk_fzf_callback (a: callback ),
673+ \ ' options' : ' --prompt="' .a: title .' : "'
674+ \ })
613675 " neovim got a problem with startinsert for the second fzf call, therefore feedkeys("i")
614676 " see https://github.com/junegunn/fzf/issues/426
615677 " see https://github.com/junegunn/fzf.vim/issues/21
616678 if has (" nvim" ) && mode () != " i" && s: fzf_counter > 1
617679 call feedkeys (' i' )
618680 endif
619681 else
620- let labels = [" " . a: title ]
621- let idx = 1
622- for item in a: items
623- if idx<10
624- call add (labels, " " . idx . " ) " . item)
625- else
626- call add (labels, idx . " ) " . item)
627- endif
628- let idx += 1
629- endfor
682+ let labels = s: ConvertItemsToLabels (items )
683+ call map (labels, {i , l - >
684+ \ i < 9
685+ \ ? ' ' .(i + 1 ).' ) ' .l
686+ \ : (i + 1 ).' ) ' .l
687+ \ })
688+ let labels = [" " . a: title ] + labels
630689 let choice = inputlist (labels)
631690 if choice > 0
632- call call (a: callback , [a: items [choice- 1 ]])
691+ call call (a: callback , [items [choice- 1 ][ ' value ' ]])
633692 endif
634693 endif
635694endfunction
@@ -693,7 +752,9 @@ endfunction
693752
694753" Ctrlp extension {{{1
695754if exists (' g:ctrlp_ext_vars' )
696- let g: arduino_ctrlp_enabled = 1
755+ if ! exists (' g:arduino_ctrlp_enabled' )
756+ let g: arduino_ctrlp_enabled = 1
757+ endif
697758 let s: ctrlp_idx = len (g: ctrlp_ext_vars )
698759 call add (g: ctrlp_ext_vars , {
699760 \ ' init' : ' arduino#ctrlp_GetData()' ,
@@ -709,16 +770,17 @@ else
709770endif
710771
711772function ! arduino#ctrlp_GetData () abort
712- return s: ctrlp_list
773+ return s: ConvertItemsToLabels ( s: ctrlp_list)
713774endfunction
714775
715776function ! arduino#ctrlp_Callback (mode , str) abort
716777 call ctrlp#exit ()
717- call call (s: ctrlp_callback , [a: str ])
778+ let value = s: ChooserValueFromLabel (a: str )
779+ call call (s: ctrlp_callback , [value])
718780endfunction
719781
720782" fzf extension {{{1
721- if exists (" *fzf#run" )
783+ if exists (" *fzf#run" ) && ! exists ( ' g:arduino_fzf_enabled ' )
722784 let g: arduino_fzf_enabled = 1
723785else
724786 let g: arduino_fzf_enabled = 0
0 commit comments