Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python CLI Menu with Arrow Keys on Windows

The terminal I use on Windows is Mingw-w64 (Git Bash). I am trying to find or create a CLI menu with Python that I can navigate with arrow keys, however nothing I find works.

The Python library, simple-term-menu, doesn't work on Windows. console-menu doesn't use arrow keys but it just throws an error when I import it anyway. After importing windows-curses, I was able to get it working in CMD but not Git Bash (it says, "Redirection is not supported.")

I know for a fact that what I'm after is possible. The JavaScript framework, Adonis, is capable of it with their create command (yarn create adonis-ts-app hello-world). The NPM one doesn't work but Yarn does. Given this, it's obviously possible, but how?

Given all of this, how can I get the CLI menu I want in Git Bash, or how can I get windows-curses to work?

like image 566
Spedwards Avatar asked May 30 '26 05:05

Spedwards


2 Answers

The cutie library might be what you want. Example:

options = [f'Choice {i}' for i in range(1, 5)]
chosen_idx = cutie.select(options)
chosen = options[chosen_idx]
like image 132
Rahul Avatar answered Jun 01 '26 19:06

Rahul


In Windows OS (and only for 32 bits Python versions), you can use 'unicurses' module. You can download it from pypi.org (https://pypi.org/project/UniCurses/1.2/) and install it as a .exe file.

when you have already installed it, it will appear an 'import module error', all about it is explained on this post here in SOF just in case: UniCurses pdcurses.dll Error

Basically you have to download 'pdcurses.dll' (here is a link: https://www.opendll.com/index.php?file-download=pdcurses.dll&arch=32bit&version=3.4.0.0) and move it to a specific directory. It's detalled on the post above.

Here is an example code of how this module works to use it with Arrow Keys:

from unicurses import *

WIDTH = 30
HEIGHT = 10
startx = 0
starty = 0

choices = ["Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit"]
n_choices = len(choices)

highlight = 1
choice = 0
c = 0

def print_menu(menu_win, highlight):
    x = 2
    y = 2
    box(menu_win, 0, 0)
    for i in range(0, n_choices):
        if (highlight == i + 1):
            wattron(menu_win, A_REVERSE)
            mvwaddstr(menu_win, y, x, choices[i])
            wattroff(menu_win, A_REVERSE)
        else:
            mvwaddstr(menu_win, y, x, choices[i])
        y += 1
    wrefresh(menu_win)

stdscr = initscr()
clear()
noecho()
cbreak()
curs_set(0)
startx = int((80 - WIDTH) / 2)
starty = int((24 - HEIGHT) / 2)

menu_win = newwin(HEIGHT, WIDTH, starty, startx)
keypad(menu_win, True)
mvaddstr(0, 0, "Use arrow keys to go up and down, press ENTER to select a choice")
refresh()
print_menu(menu_win, highlight)

while True:
    c = wgetch(menu_win)
    if c == KEY_UP:
        if highlight == 1:
            highlight == n_choices
        else:
            highlight -= 1
    elif c == KEY_DOWN:
        if highlight == n_choices:
            highlight = 1
        else:
            highlight += 1
    elif c == 10:   # ENTER is pressed
        choice = highlight
        mvaddstr(23, 0, str.format("You chose choice {0} with choice string {1}", choice, choices[choice-1]))
        clrtoeol()
        refresh()
    else:
        mvaddstr(22, 0, str.format("Character pressed is = {0}", c))
        clrtoeol()
        refresh()
    print_menu(menu_win, highlight)
    if choice == 5:
        break

refresh()
endwin()

And here is an image of the result on the command line interface (CMD): enter image description here

like image 23
Diroallu Avatar answered Jun 01 '26 20:06

Diroallu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!