Python curses Module

The curses module in Python provides an interface to create text-based user interfaces. It allows you to manipulate the terminal screen, handle keyboard input, and manage windows and text attributes, making it ideal for building terminal applications.

Table of Contents

  1. Introduction
  2. Key Concepts
    • Windows
    • Pads
    • Colors
    • Attributes
  3. Key Functions and Methods
    • initscr()
    • endwin()
    • newwin()
    • addstr()
    • refresh()
    • getch()
    • keypad()
    • noecho()
    • curs_set()
  4. Examples
    • Basic Usage
    • Handling Keyboard Input
    • Using Colors
    • Creating Multiple Windows
  5. Real-World Use Case
  6. Conclusion
  7. References

Introduction

The curses module is used for creating text-based user interfaces. It provides control over the terminal screen, allowing for the creation of complex text interfaces, including windows, colors, and input handling.

Key Concepts

Windows

Windows are the basic building blocks in curses and represent areas of the screen where you can write text and handle input.

Pads

Pads are like windows but can be larger than the screen, allowing for the creation of scrollable areas.

Colors

curses supports color text if the terminal supports it. You can define and use color pairs for text.

Attributes

Attributes are used to apply styles to text, such as bold, underline, or reverse video.

Key Functions and Methods

initscr()

Initializes the curses application and returns a window object representing the entire screen.

import curses

stdscr = curses.initscr()

endwin()

Restores the terminal to its original operating mode.

curses.endwin()

newwin()

Creates a new window.

win = curses.newwin(nlines, ncols, begin_y, begin_x)

addstr()

Adds a string to a window at the current cursor position.

win.addstr('Hello, World!')

refresh()

Refreshes the window, updating the actual screen with changes made.

win.refresh()

getch()

Waits for a key press and returns the ASCII value of the key.

key = win.getch()

keypad()

Enables or disables the keypad mode. When enabled, special keys are interpreted by curses.

win.keypad(True)

noecho()

Disables echoing of characters typed by the user.

curses.noecho()

curs_set()

Sets the visibility of the cursor.

curses.curs_set(0)  # Hide cursor
curses.curs_set(1)  # Show cursor

Examples

Basic Usage

import curses

def main(stdscr):
    curses.curs_set(0)  # Hide cursor
    stdscr.addstr(0, 0, 'Hello, World!')
    stdscr.refresh()
    stdscr.getch()

curses.wrapper(main)

Handling Keyboard Input

import curses

def main(stdscr):
    curses.curs_set(0)
    stdscr.addstr(0, 0, 'Press any key to see its value, q to exit.')
    while True:
        key = stdscr.getch()
        if key == ord('q'):
            break
        stdscr.clear()
        stdscr.addstr(0, 0, f'Key pressed: {key}')
        stdscr.refresh()

curses.wrapper(main)

Using Colors

import curses

def main(stdscr):
    curses.start_color()
    curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
    stdscr.addstr(0, 0, 'This is red text', curses.color_pair(1))
    stdscr.refresh()
    stdscr.getch()

curses.wrapper(main)

Creating Multiple Windows

import curses

def main(stdscr):
    curses.curs_set(0)
    height, width = 5, 40
    win1 = curses.newwin(height, width, 0, 0)
    win2 = curses.newwin(height, width, height, 0)
    win1.addstr(0, 0, 'Window 1')
    win2.addstr(0, 0, 'Window 2')
    win1.refresh()
    win2.refresh()
    stdscr.getch()

curses.wrapper(main)

Real-World Use Case

Simple Text Editor

import curses

def main(stdscr):
    curses.curs_set(1)
    stdscr.keypad(True)
    curses.noecho()

    buffer = []
    cursor_x = 0
    cursor_y = 0

    while True:
        stdscr.clear()
        for y, line in enumerate(buffer):
            stdscr.addstr(y, 0, line)
        stdscr.move(cursor_y, cursor_x)
        stdscr.refresh()
        
        key = stdscr.getch()
        
        if key == curses.KEY_EXIT or key == ord('q'):
            break
        elif key == curses.KEY_BACKSPACE or key == 127:
            if cursor_x > 0:
                buffer[cursor_y] = buffer[cursor_y][:cursor_x-1] + buffer[cursor_y][cursor_x:]
                cursor_x -= 1
            elif cursor_y > 0:
                cursor_x = len(buffer[cursor_y - 1])
                buffer[cursor_y - 1] += buffer[cursor_y]
                buffer.pop(cursor_y)
                cursor_y -= 1
        elif key == curses.KEY_ENTER or key == 10:
            buffer.insert(cursor_y + 1, buffer[cursor_y][cursor_x:])
            buffer[cursor_y] = buffer[cursor_y][:cursor_x]
            cursor_y += 1
            cursor_x = 0
        elif key == curses.KEY_LEFT:
            if cursor_x > 0:
                cursor_x -= 1
        elif key == curses.KEY_RIGHT:
            if cursor_x < len(buffer[cursor_y]):
                cursor_x += 1
        elif key == curses.KEY_UP:
            if cursor_y > 0:
                cursor_y -= 1
                cursor_x = min(cursor_x, len(buffer[cursor_y]))
        elif key == curses.KEY_DOWN:
            if cursor_y < len(buffer) - 1:
                cursor_y += 1
                cursor_x = min(cursor_x, len(buffer[cursor_y]))
        else:
            buffer[cursor_y] = buffer[cursor_y][:cursor_x] + chr(key) + buffer[cursor_y][cursor_x:]
            cursor_x += 1

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

Conclusion

The curses module in Python provides a powerful way to create text-based user interfaces. It offers extensive functionality for manipulating the terminal screen, handling keyboard input, and managing windows and text attributes. This makes it an ideal tool for building terminal applications.

References

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare