Skip to content

Instantly share code, notes, and snippets.

@sbp
Created September 4, 2015 14:12
Show Gist options
  • Save sbp/318ecce414c00ffd17fe to your computer and use it in GitHub Desktop.
Save sbp/318ecce414c00ffd17fe to your computer and use it in GitHub Desktop.
Choose from a range interactively
#!/usr/bin/env python3
# choice.py, by Sean B. Palmer
import sys
countries = ["Albania", "Andorra", "Austria", "Belarus", "Belgium", "Bulgaria",
"Cyprus", "Czechoslovakia", "Denmark", "Estonia", "Faeroe Islands", "Finland",
"France", "Germany", "Gibraltar", "Greece", "Guernsey", "Hungary", "Iceland",
"Ireland", "Isle of Man", "Italy", "Jan Mayen", "Jersey", "Latvia",
"Liechtenstein", "Lithuania", "Luxembourg", "Malta", "Moldova", "Monaco",
"Netherlands", "Norway", "Poland", "Portugal", "Romania", "San Marino",
"Spain", "Sweden", "Switzerland", "United Kingdom", "Yugoslavia"]
write = sys.stdout.write
# http://stackoverflow.com/a/21659588
def _find_getch():
try: import termios
except ImportError:
# Non-POSIX. Return msvcrt's (Windows') getch.
import msvcrt
return msvcrt.getch
# POSIX system. Create and return a getch that manipulates the tty.
import tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
return _getch
getch = _find_getch()
def select(items, pattern):
if not pattern:
return items[:]
return [item for item in items if pattern in item]
def format(items, pattern, position):
selected = select(items, pattern)
try:
selected_item = selected[position]
selected[position] = "*%s*" % selected[position]
# selected = selected[position:]
except IndexError:
selected_item = None
output = pattern + ": " + ", ".join(selected)
if len(output) > 79:
output = output[:76].rstrip(", ")
output += "..."
write("\r")
write(output + (" " * (79 - len(output))))
sys.stdout.flush()
return len(selected), selected_item
def choose(choices):
pattern = ""
position = 0
count, selected = format(choices, pattern, position)
cancelled = False
while True:
ch = getch()
# print(repr(ch))
if ch in {"\x03", "\x04"}: # C-c C-d
cancelled = True
break
elif ch in {"\n", "\r"}:
break
elif ch == "\x1b":
a = getch()
b = getch()
if (a == "[") and (b == "C"): # Right Arrow
if position < (count - 1):
position += 1
elif (a == "[") and (b == "D"): # Left Arrow
if position > 0:
position -= 1
elif ch == "\x7f":
if pattern:
pattern = pattern[:-1]
elif ch.isprintable():
pattern += ch
count, selected = format(choices, pattern, position)
if not cancelled:
print()
return selected
else:
print()
return None
def main():
selection = choose(countries)
print("Selection:", selection)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment