Bash Python script I made to create a menu in the terminal window

Thought maybe some other ppl people might appreciate this. I just use it for common commands instead of using aliases.
I bound it to the m key to start it up. Easy to edit for your own commands.

Python:
#!/usr/bin/env python3

import curses
import subprocess
import os

def main(stdscr):
    curses.curs_set(0)
    stdscr.clear()

    options = ["Ping Google", "Check VPN", "Option 1", "Option 2", "Exit", "Option 4", "Option 5"]
    num_columns = 2
    current_option = 0

    # Initialize color pairs
    curses.start_color()
    curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)  # Red on black
    curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)  # White on black

    header = "Welcome to the Menu!"
    header_color = curses.color_pair(1)  # Red text
    header_row = 1

    while True:
        stdscr.clear()

        screen_height, screen_width = stdscr.getmaxyx()

        column_width = max(len(option) for option in options) + 2
        column_height = len(options) // num_columns
        spacing = 2  # Vertical spacing between columns

        # Display the header
        stdscr.addstr(header_row, (screen_width - len(header)) // 2, header, header_color)

        for column in range(num_columns):
            start_col = (screen_width - column_width * num_columns - spacing * (num_columns - 1)) // 2 + column * (column_width + spacing)
            for i in range(column_height):
                option_index = column * column_height + i
                if option_index < len(options):
                    if option_index == current_option:
                        stdscr.addstr(i + header_row + 2, start_col, f"> {options[option_index]}", curses.color_pair(1) | curses.A_REVERSE)  # Red text with reverse video
                    else:
                        stdscr.addstr(i + header_row + 2, start_col, f"  {options[option_index]}", curses.color_pair(2))  # White text

        stdscr.refresh()

        key = stdscr.getch()

        if key == curses.KEY_DOWN and current_option < len(options) - 1:
            current_option += 1
        elif key == curses.KEY_UP and current_option > 0:
            current_option -= 1
        elif key == curses.KEY_RIGHT or key == curses.KEY_LEFT:
            # Toggle column for right and left arrow keys
            current_option = (current_option % column_height) + ((current_option // column_height) ^ 1) * column_height
        elif key == 10:  # Enter key
            if current_option == len(options) - 1:
                break
            elif current_option == 0:
                stdscr.clear()
                stdscr.refresh()
                ping_output = subprocess.check_output(["ping", "-c", "8", "8.8.8.8"], text=True)
                display_output(stdscr, ping_output, options)
            elif current_option == 1:
                stdscr.clear()
                stdscr.refresh()
                vpn_output = subprocess.check_output(["setfib", "1", "curl", "icanhazip.com"], text=True)
                display_output(stdscr, vpn_output, options)
            elif current_option == 4:
                break
            else:
                stdscr.clear()
                stdscr.refresh()
                option_output = f"Selected Option: {options[current_option]}"
                display_output(stdscr, option_output, options)

def display_output(stdscr, output, options):
    stdscr.clear()
    rows, cols = stdscr.getmaxyx()
    lines = output.split('\n')

    menu_height = len(options) // 2 + 2  # Height of the menu

    for i, line in enumerate(lines):
        if i + menu_height < rows - 1:
            stdscr.addstr(i + menu_height, (cols - len(line)) // 2, line, curses.color_pair(2))  # White text
        else:
            stdscr.addstr(rows - 1, 0, "Press any key to continue...", curses.color_pair(2))
            stdscr.refresh()
            stdscr.getch()
            break

    stdscr.refresh()
    stdscr.getch()  # Wait for a key press

if __name__ == "__main__":
    curses.wrapper(main)
 
Back
Top