Skip to content

Instantly share code, notes, and snippets.

@gsw945
Created October 9, 2018 15:18
Show Gist options
  • Save gsw945/3f41738e9641a330c64bf2f5a9a97fdf to your computer and use it in GitHub Desktop.
Save gsw945/3f41738e9641a330c64bf2f5a9a97fdf to your computer and use it in GitHub Desktop.
python-prompt-toolkit selection list
# -*- coding: utf-8 -*-
from prompt_toolkit.layout.margins import ScrollbarMargin
from prompt_toolkit.formatted_text import to_formatted_text
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.keys import Keys
from prompt_toolkit.key_binding.key_bindings import KeyBindings
from prompt_toolkit.formatted_text import HTML
class NewRadioList(object):
"""
List of radio buttons. Only one can be checked at the same time.
:param values: List of (value, label) tuples.
modified from: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/prompt_toolkit/widgets/base.py
"""
def __init__(self, values):
assert isinstance(values, list)
assert len(values) > 0
assert all(isinstance(i, tuple) and len(i) == 2
for i in values)
self.values = values
self.current_value = values[0][0]
self._selected_index = 0
# Key bindings.
kb = KeyBindings()
@kb.add('up')
def _(event):
self._selected_index = max(0, self._selected_index - 1)
self.current_value = self.values[self._selected_index][0]
@kb.add('down')
def _(event):
self._selected_index = min(
len(self.values) - 1,
self._selected_index + 1
)
self.current_value = self.values[self._selected_index][0]
@kb.add(Keys.Any)
def _(event):
# We first check values after the selected value, then all values.
for value in self.values[self._selected_index + 1:] + self.values:
if value[0].startswith(event.data):
self._selected_index = self.values.index(value)
return
# Control and window.
self.control = FormattedTextControl(
self._get_text_fragments,
key_bindings=kb,
focusable=True)
self.window = Window(
content=self.control,
style='class:radio-list',
right_margins=[
ScrollbarMargin(display_arrows=True),
],
dont_extend_height=True)
def _get_text_fragments(self):
result = []
for i, value in enumerate(self.values):
checked = (value[0] == self.current_value)
selected = (i == self._selected_index)
style = ''
if checked:
style += ' class:radio-checked'
if selected:
style += ' class:radio-selected'
result.append((style, ''))
if selected:
result.append(('[SetCursorPosition]', ''))
display = value[1]
if checked:
result.append((style, '->'))
display = HTML('<style bg="#999" fg="red">{0}</style>'.format(display))
else:
result.append((style, ' '))
result.append((style, ''))
result.append(('class:radio', ' '))
result.extend(to_formatted_text(display, style='class:radio'))
result.append(('', '\n'))
result.pop() # Remove last newline.
return result
def __pt_container__(self):
return self.window
# -*- coding: utf-8 -*-
from prompt_toolkit.application import Application
from prompt_toolkit.layout import Layout
from prompt_toolkit.key_binding.defaults import load_key_bindings
from prompt_toolkit.key_binding.key_bindings import KeyBindings, merge_key_bindings
from prompt_toolkit.formatted_text import ANSI
from prompt_toolkit import print_formatted_text
from new_radio_list import NewRadioList
print('-' * 70)
print('press [up] or [down] to switch selection')
print('press [enter] to choose')
print('-' * 70)
values = [
('python', 'Python'),
('php', 'PHP'),
('csharp', 'C#'),
('java', 'Java'),
]
rdo = NewRadioList(values)
def do_exit(event):
# get_app().exit()
event.app.exit(result=rdo.current_value)
def do_up_down(event):
print(event)
pass
bindings = KeyBindings()
bindings.add('enter')(do_exit)
app_bindings = merge_key_bindings([
load_key_bindings(),
bindings
])
selected = Application(layout=Layout(rdo), key_bindings=app_bindings).run()
print('your choice is:', end=' ')
# refer: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/examples/print-text/ansi.py
print_formatted_text(ANSI('\x1b[91m{0}'.format(selected)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment