Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9095687
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T23:40:06+00:00 2026-06-16T23:40:06+00:00

AFAIK, there is no curses menu extension available in Python yet so you have

  • 0

AFAIK, there is no curses menu extension available in Python yet so you have to roll your own solution. I know about this patch http://bugs.python.org/issue1723038 but I don’t what’s the current state of it. I found a nice class for Python that wraps what I want called ‘cmenu’ here http://www.promisc.org/blog/?p=33 but I have a problem with that too. I want to make a menu where user can choose a highlighted element but instead of executing a particular action right away I want to display another menu, and then maybe another, ask for some input etc. My first thought was to remove the existing cmenu with screen.clear() or cleanup() but the old menu is not removed before the new one is drawn and the new menu looks like this:

    0. top
    1. Exit
    2. Another menu
-- end of the old menu that should go away --
    3. first
    4. second
    5. third

There is no remove() method for removing an item in cmenu(). I guess the fact that the old menu is not cleared is caused by ‘while True’ loop in display() method but when I removed it some weird stuff was going on. I am using Python 2.7, this is my current code:

#!/usr/bin/python
#
# Adapted from:
# http://blog.skeltonnetworks.com/2010/03/python-curses-custom-menu/
#
# Goncalo Gomes
# http://promisc.org
#

import signal
signal.signal(signal.SIGINT, signal.SIG_IGN)

import os
import sys
import curses
import traceback
import atexit
import time

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

class cmenu(object):
    datum = {}
    ordered = []
    pos = 0

    def __init__(self, options, title="python curses menu"):
        curses.initscr()
        curses.start_color()
        curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
        curses.curs_set(0)
        self.screen = curses.initscr()
        self.screen.keypad(1)

        self.h = curses.color_pair(1)
        self.n = curses.A_NORMAL

        for item in options:
            k, v = item.items()[0]
            self.datum[k] = v
            self.ordered.append(k)

        self.title = title

        atexit.register(self.cleanup)

    def cleanup(self):
        curses.doupdate()
        curses.endwin()

    def upKey(self):
        if self.pos == (len(self.ordered) - 1):
            self.pos = 0
        else:
            self.pos += 1

    def downKey(self):
        if self.pos <= 0:
            self.pos = len(self.ordered) - 1
        else:
            self.pos -= 1

    def display(self):
        screen = self.screen

        while True:
            screen.clear()
            screen.addstr(2, 2, self.title, curses.A_STANDOUT|curses.A_BOLD)
            screen.addstr(4, 2, "Please select an interface...", curses.A_BOLD)

            ckey = None
            func = None

            while ckey != ord('\n'):
                for n in range(0, len(self.ordered)):
                    optn = self.ordered[n]

                    if n != self.pos:
                        screen.addstr(5 + n, 4, "%d. %s" % (n, optn), self.n)
                    else:
                        screen.addstr(5 + n, 4, "%d. %s" % (n, optn), self.h)
                screen.refresh()

                ckey = screen.getch()

                if ckey == 258:
                    self.upKey()

                if ckey == 259:
                    self.downKey()

            ckey = 0
            self.cleanup()
            if self.pos >= 0 and self.pos < len(self.ordered):
                self.datum[self.ordered[self.pos]]()
                self.pos = -1
            else:
                curses.flash()



def top():
    os.system("top")

def exit():
    sys.exit(1)

def submenu():
    # c.screen.clear()     # nope
    # c.cleanup()          # nope
    submenu_list = [{"first": exit}, {"second": exit}, {"third": exit}]
    submenu = cmenu(submenu_list)
    submenu.display()

try:

    list = [{ "top": top }, {"Exit": exit}, {"Another menu": submenu}]

    c = cmenu(list)

    c.display()

except SystemExit:
    pass
else:
    #log(traceback.format_exc())
    c.cleanup()
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T23:40:08+00:00Added an answer on June 16, 2026 at 11:40 pm

    I really recommend you look into using panels. Anytime you will have widgets that could possibly overlap, it makes life alot easier. This is a simple example that should get you started. (Neither curses.beep() or curses.flash() seem to work on my terminal, but that is beside the point)

    #!/usr/bin/env python
    
    import curses
    from curses import panel
    
    
    class Menu(object):
        def __init__(self, items, stdscreen):
            self.window = stdscreen.subwin(0, 0)
            self.window.keypad(1)
            self.panel = panel.new_panel(self.window)
            self.panel.hide()
            panel.update_panels()
    
            self.position = 0
            self.items = items
            self.items.append(("exit", "exit"))
    
        def navigate(self, n):
            self.position += n
            if self.position < 0:
                self.position = 0
            elif self.position >= len(self.items):
                self.position = len(self.items) - 1
    
        def display(self):
            self.panel.top()
            self.panel.show()
            self.window.clear()
    
            while True:
                self.window.refresh()
                curses.doupdate()
                for index, item in enumerate(self.items):
                    if index == self.position:
                        mode = curses.A_REVERSE
                    else:
                        mode = curses.A_NORMAL
    
                    msg = "%d. %s" % (index, item[0])
                    self.window.addstr(1 + index, 1, msg, mode)
    
                key = self.window.getch()
    
                if key in [curses.KEY_ENTER, ord("\n")]:
                    if self.position == len(self.items) - 1:
                        break
                    else:
                        self.items[self.position][1]()
    
                elif key == curses.KEY_UP:
                    self.navigate(-1)
    
                elif key == curses.KEY_DOWN:
                    self.navigate(1)
    
            self.window.clear()
            self.panel.hide()
            panel.update_panels()
            curses.doupdate()
    
    
    class MyApp(object):
        def __init__(self, stdscreen):
            self.screen = stdscreen
            curses.curs_set(0)
    
            submenu_items = [("beep", curses.beep), ("flash", curses.flash)]
            submenu = Menu(submenu_items, self.screen)
    
            main_menu_items = [
                ("beep", curses.beep),
                ("flash", curses.flash),
                ("submenu", submenu.display),
            ]
            main_menu = Menu(main_menu_items, self.screen)
            main_menu.display()
    
    
    if __name__ == "__main__":
        curses.wrapper(MyApp)
    

    Some things to note when looking over your code.

    Using curses.wrapper(callable) to launch your application is cleaner than doing your own try/except with cleanup.

    Your class calls initscr twice which will probably generate two screens (havent tested if it returns the same screen if its setup), and then when you have multiple menus there is no proper handling of (what should be) different windows/screens. I think its clearer and better bookkeeping to pass the menu the screen to use and let the menu make a subwindow to display in as in my example.

    Naming a list 'list' isn’t a great idea, because it shadows the list() function.

    If you want to launch another terminal app like ‘top’, it is probably better to let python exit curses cleanly first then launch in order to prevent any futzing with terminal settings.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I know C# is getting a lot of parallel programming support, but AFAIK there
Possible Duplicate: JavaScript: var functionName = function() {} vs function functionName() {} AFAIK, there
This question is about the public key that every .NET assembly has AFAIK (looking
I'd like to know if derivatives in glsl are working on GL_LINES primitives. AFAIK
AFAIK, there is no dedicated element--like <caption> for tables, <figcaption> for figures, etc.--to mark
I'm wondering how one can do that. Afaik there is BeanFactoryPostProcessor interface that let
AFAIK there is no DOS in vista and windows 7, but I need to
How do I accumulate values in T-SQL? AFAIK there is no ARRAY type. I
AFAIK, there are two ways of passing data to the view from controller :
I'm a novice at programming although I've been teaching myself Python for about a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.