Search code examples
pythontext-editorcurses

run terminal text editor from python curses program


I want to use external terminal text editor and pager in my python curses program. I use subprocess library for it. For the most part it works fine except when I exit text editor (same with nemo and vi), I cannot make cursor invisible again. Also, after calling subprocess, library doesn't clean the screen on exit. What do I miss?

P.S. I'm aware of curses.textpad, but I would prefer to use external editor and pager.

Here's a program:

import curses
import subprocess

class tui(object):

    def __init__(self):
        pass

    def setup(self, stdscr):
        self.stdscr = stdscr
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, -1)
        self.maxY, self.maxX = self.stdscr.getmaxyx()
        try:
            curses.curs_set(0)
        except:
            pass
        self.win = curses.newwin(self.maxY, self.maxX, 0, 0)
        self.stdscr.nodelay(0)
        self.draw()
        while True:
            try:
                c = self.win.getch()
                ret = self.keypress(c)
                if (ret == -1):
                    return
            except KeyboardInterrupt:
                break


    def draw(self):
        self.win.erase()
        self.win = curses.newwin(self.maxY, self.maxX, 0, 0)
        self.win.box()
        self.win.refresh()


    def nano(self):
        curses.savetty()
        subprocess.run("nano")
        curses.resetty()
        curses.curs_set(0)

    def less(self):
        curses.savetty()
        subprocess.run(["less", "/etc/fstab"])
        curses.resetty()
        curses.curs_set(0)



    def keypress(self, char):
        if char == curses.KEY_EXIT or char == ord('q'):
            return -1

        if char == ord('e'):
            self.nano()
            self.draw()
            return

        if char == ord('l'):
            self.less()
            self.draw()
            return

if __name__ == '__main__':
    mytui = tui()
    curses.wrapper(mytui.setup)

Solution

  • You didn't tell the curses library that you were leaving (when you left to run nano, for instance), and curses remembered what state you had told it to use for the cursor-visibility. So it's ignoring your change, because it's not changed as far as curses knows.

    If you're going to leave, use the endwin function. When you come back, a refresh undoes that.