Ask the user to select an item from the list |items|. Presents the user with |prompt| followed by a numbered list of |items|, from which they select one. The user is asked to enter the number of an item or click it. |items| should not contain leading ordinals: they are added automatically.
( prompt, items )
| 805 | |
| 806 | |
| 807 | def SelectFromList( prompt, items ): |
| 808 | """Ask the user to select an item from the list |items|. |
| 809 | |
| 810 | Presents the user with |prompt| followed by a numbered list of |items|, |
| 811 | from which they select one. The user is asked to enter the number of an |
| 812 | item or click it. |
| 813 | |
| 814 | |items| should not contain leading ordinals: they are added automatically. |
| 815 | |
| 816 | Returns the 0-based index in the list |items| that the user selected, or an |
| 817 | exception if no valid item was selected. |
| 818 | |
| 819 | See also :help inputlist().""" |
| 820 | |
| 821 | vim_items = [ prompt ] |
| 822 | vim_items.extend( [ f"{ i + 1 }: { item }" |
| 823 | for i, item in enumerate( items ) ] ) |
| 824 | |
| 825 | # The vim documentation warns not to present lists larger than the number of |
| 826 | # lines of display. This is sound advice, but there really isn't any sensible |
| 827 | # thing we can do in that scenario. Testing shows that Vim just pages the |
| 828 | # message; that behaviour is as good as any, so we don't manipulate the list, |
| 829 | # or attempt to page it. |
| 830 | |
| 831 | # For an explanation of the purpose of inputsave() / inputrestore(), |
| 832 | # see :help input(). Briefly, it makes inputlist() work as part of a mapping. |
| 833 | vim.eval( 'inputsave()' ) |
| 834 | try: |
| 835 | # Vim returns the number the user entered, or the line number the user |
| 836 | # clicked. This may be wildly out of range for our list. It might even be |
| 837 | # negative. |
| 838 | # |
| 839 | # The first item is index 0, and this maps to our "prompt", so we subtract 1 |
| 840 | # from the result and return that, assuming it is within the range of the |
| 841 | # supplied list. If not, we return negative. |
| 842 | # |
| 843 | # See :help input() for explanation of the use of inputsave() and inpput |
| 844 | # restore(). It is done in try/finally in case vim.eval ever throws an |
| 845 | # exception (such as KeyboardInterrupt) |
| 846 | selected = GetIntValue( "inputlist( " + json.dumps( vim_items ) + " )" ) - 1 |
| 847 | except KeyboardInterrupt: |
| 848 | selected = -1 |
| 849 | finally: |
| 850 | vim.eval( 'inputrestore()' ) |
| 851 | |
| 852 | if selected < 0 or selected >= len( items ): |
| 853 | # User selected something outside of the range |
| 854 | raise RuntimeError( NO_SELECTION_MADE_MSG ) |
| 855 | |
| 856 | return selected |
| 857 | |
| 858 | |
| 859 | def EscapeForVim( text ): |
nothing calls this directly
no test coverage detected