2

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?

Spedwards
  • 4,167
  • 16
  • 49
  • 106
  • Is using wsl a valid option for you? I know you probably have looked into it, but like you have said I don't see a repo that was made for this task. – Kutay Kılıç Jan 24 '23 at 11:09
  • Does this answer your question? [Console select menu in python](https://stackoverflow.com/a/70254575/8601760). Not sure if it supports Git Bash yet ([github.com/wong2/pick/pull/90](https://github.com/wong2/pick/pull/90)). – aaron Jan 27 '23 at 04:00
  • [urwid](https://github.com/urwid/urwid/tree/master/examples) might work for you. It includes a bunch of example programs so you'll be able to quickly assess if it works in Git Bash or not. – Mr. Llama Feb 02 '23 at 19:33
  • Does this answer your question? [Console select menu in python](https://stackoverflow.com/questions/56723852/console-select-menu-in-python) – aaron Feb 04 '23 at 08:33

3 Answers3

1

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

Diroallu
  • 824
  • 1
  • 11
  • 15
1

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]
Rahul
  • 1,056
  • 2
  • 9
  • 26
0

You can use InquirerPy to create a menu like this that works using keyboard navigation

#! /usr/bin/env python3

from InquirerPy import inquirer

fav_lang = inquirer.select(
    message = "What's your favorite language:",
    choices = ["Go", "Kotlin", "Python", "Rust", "Java", "JavaScript"]
).execute()

menu

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134