@@ -50,6 +50,9 @@ def __init__(self, options):
50
50
self .height = len (options )
51
51
self ._selection = None
52
52
53
+ def get_index (self ):
54
+ return self ._selection
55
+
53
56
def get_selection (self ):
54
57
"""Return the currently selected option, if there is one."""
55
58
if self ._selection is not None :
@@ -77,6 +80,7 @@ def select_up(self, event=None):
77
80
78
81
def _insert_text (self , event ):
79
82
if event is not None :
83
+ event .current_buffer .reset ()
80
84
event .current_buffer .document = Document (self .get_selection ())
81
85
82
86
def preferred_width (self , cli , max_available_width ):
@@ -121,7 +125,27 @@ def _get_menu_item_tokens(self, option, is_current):
121
125
def create_select_menu_layout (msg , menu_control ,
122
126
show_meta = False ,
123
127
reserve_space_for_menu = True ):
124
- """Construct a layout for the given message and menu control."""
128
+ """Construct a layout for the given message and menu control.
129
+
130
+ :type msg: str
131
+ :param msg: The message to be used when showing the prompt.
132
+
133
+ :type msg: :class:`SelectMenuControl`
134
+ :param msg: The menu controller that manages the state and rendering of the
135
+ currently selected option.
136
+
137
+ :type show_meta: bool
138
+ :param show_meta: (Optional) Whether or not the meta information should be
139
+ displayed below the prompt.
140
+
141
+ :type reserve_space_for_menu: bool
142
+ :param reserve_space_for_menu: (Optional) Whether or not the prompt should
143
+ force that there be enough lines for the completion menu to completely
144
+ render.
145
+
146
+ :rtype: :class:`prompt_toolkit.layout.containers.Container`
147
+ :return: The layout to be used for a select menu prompt.
148
+ """
125
149
def get_prompt_tokens (cli ):
126
150
return [(Token .Prompt , msg )]
127
151
@@ -201,7 +225,7 @@ def __init__(self, message, options, *args, **kwargs):
201
225
202
226
# create and apply the default and info buffers
203
227
options_meta = kwargs .pop ('options_meta' , None )
204
- kwargs ['buffers' ] = self ._initialize_buffers (options_meta )
228
+ kwargs ['buffers' ] = self ._initialize_buffers (options , options_meta )
205
229
206
230
# create and apply the new layout
207
231
kwargs ['layout' ] = create_select_menu_layout (
@@ -212,10 +236,12 @@ def __init__(self, message, options, *args, **kwargs):
212
236
213
237
super (SelectMenuApplication , self ).__init__ (* args , ** kwargs )
214
238
215
- def _initialize_buffers (self , options_meta ):
239
+ def _initialize_buffers (self , options , options_meta ):
216
240
# Return the currently selected option
217
241
def return_selection (cli , buf ):
218
- cli .set_return_value (self .menu_control .get_selection ())
242
+ selection = self .menu_control .get_selection ()
243
+ index = self .menu_control .get_index ()
244
+ cli .set_return_value ((selection , index ))
219
245
220
246
buffers = {}
221
247
@@ -228,11 +254,13 @@ def return_selection(cli, buf):
228
254
229
255
# Optionally show meta information if present
230
256
if options_meta is not None :
257
+ assert len (options ) == len (options_meta )
231
258
info_buf = Buffer (is_multiline = True )
232
259
buffers ['INFO' ] = info_buf
233
260
234
261
def selection_changed (cli ):
235
- info = options_meta [buffers [DEFAULT_BUFFER ].text ]
262
+ index = self .menu_control .get_index ()
263
+ info = options_meta [index ]
236
264
formatted_info = json .dumps (info , indent = 4 , sort_keys = True ,
237
265
ensure_ascii = False )
238
266
buffers ['INFO' ].text = formatted_info
@@ -277,7 +305,22 @@ def _(_):
277
305
278
306
279
307
def select_prompt (message , options , * args , ** kwargs ):
280
- """Construct and run the select menu application, returning the result."""
308
+ """Construct and run the select menu application, returning the result.
309
+
310
+ :type message: str
311
+ :param message: The message to be used when showing the prompt.
312
+
313
+ :type options: list of str
314
+ :param options: The options to be displayed in the drop down list.
315
+
316
+ :type options_meta: list of dict
317
+ :param options_meta: (Optional) List of detailed objects for each option in
318
+ the list. This list is parallel to options and must equal in length.
319
+
320
+ :rtype: tuple of (str, int)
321
+ :return: The tuple containing the selected option, and its index in the
322
+ list of options.
323
+ """
281
324
runner = kwargs .pop ('runner' , run_application )
282
325
app = SelectMenuApplication (message , options , * args , ** kwargs )
283
326
return runner (app )
0 commit comments