Save the current state of the terminal modes in a buffer, usable by
:func:`resetty`.
+.. function:: scr_dump(filename)
+
+ Write the current contents of the virtual screen to *filename*, which may be
+ a string or a :term:`path-like object`. The file can later be read by
+ :func:`scr_restore`, :func:`scr_init` or :func:`scr_set`. This is the
+ whole-screen counterpart of :meth:`window.putwin`.
+
+ .. versionadded:: next
+
+.. function:: scr_restore(filename)
+
+ Set the virtual screen to the contents of *filename*, which must have been
+ written by :func:`scr_dump`. The next call to :func:`doupdate` or
+ :meth:`window.refresh` restores the screen to those contents.
+
+ .. versionadded:: next
+
+.. function:: scr_init(filename)
+
+ Initialize the assumed contents of the terminal from *filename*, which must
+ have been written by :func:`scr_dump`. Use it when the terminal already
+ displays those contents, for example after another program has drawn the
+ screen, so that curses does not redraw what is already there.
+
+ .. versionadded:: next
+
+.. function:: scr_set(filename)
+
+ Use *filename*, which must have been written by :func:`scr_dump`, as both
+ the virtual screen and the assumed terminal contents. This combines the
+ effects of :func:`scr_restore` and :func:`scr_init`.
+
+ .. versionadded:: next
+
.. function:: get_escdelay()
Retrieves the value set by :func:`set_escdelay`.
returns a new window that is an independent duplicate of an existing one.
(Contributed by Serhiy Storchaka in :gh:`152258`.)
+* Add the :mod:`curses` functions :func:`~curses.scr_dump`,
+ :func:`~curses.scr_restore`, :func:`~curses.scr_init` and
+ :func:`~curses.scr_set`, which dump the whole screen to a file and restore it.
+ (Contributed by Serhiy Storchaka in :gh:`152260`.)
+
gzip
----
self.assertEqual(win.getmaxyx(), (5, 12))
self.assertEqual(win.instr(2, 0), b' Lorem ipsum')
+ def test_scr_dump(self):
+ # Test scr_dump(), scr_restore(), scr_init() and scr_set().
+ # scr_dump() writes the virtual screen to a named file; the other three
+ # functions load it back. The dumped image is internal curses state,
+ # not a window, so the round-trip is checked by comparing dump files
+ # rather than reading cells.
+ stdscr = self.stdscr
+ stdscr.erase()
+ stdscr.addstr(0, 0, 'screen dump test')
+ stdscr.refresh()
+ with tempfile.TemporaryDirectory() as d:
+ dump = os.path.join(d, 'dump')
+ self.assertIsNone(curses.scr_dump(dump))
+ # Dumping the same screen again is deterministic.
+ dump2 = os.path.join(d, 'dump2')
+ curses.scr_dump(dump2)
+ with open(dump, 'rb') as f1, open(dump2, 'rb') as f2:
+ self.assertEqual(f1.read(), f2.read())
+ # scr_restore() reloads that virtual screen, so dumping it again
+ # reproduces the original file even after the screen has changed.
+ stdscr.erase()
+ stdscr.addstr(0, 0, 'something else')
+ stdscr.refresh()
+ self.assertIsNone(curses.scr_restore(dump))
+ restored = os.path.join(d, 'restored')
+ curses.scr_dump(restored)
+ with open(dump, 'rb') as f1, open(restored, 'rb') as f2:
+ self.assertEqual(f1.read(), f2.read())
+ # scr_init() and scr_set() accept a dump file and return None.
+ self.assertIsNone(curses.scr_init(dump))
+ self.assertIsNone(curses.scr_set(dump))
+ # A bytes (path-like) filename is accepted too.
+ curses.scr_dump(os.fsencode(dump))
+ # Restoring from a missing file is an error.
+ self.assertRaises(curses.error,
+ curses.scr_restore, os.path.join(d, 'nope'))
+
def test_borders_and_lines(self):
win = curses.newwin(5, 10, 5, 2)
win.border('|', '!', '-', '_',
--- /dev/null
+Add the :mod:`curses` functions :func:`~curses.scr_dump`,
+:func:`~curses.scr_restore`, :func:`~curses.scr_init` and
+:func:`~curses.scr_set`, which dump the whole screen to a file and restore it.
mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr
mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr
mvwinchnstr mvwinchstr mvwinnstr
- restartterm ripoffline scr_dump
- scr_init scr_restore scr_set scrl set_curterm setterm
+ restartterm ripoffline
+ scrl set_curterm setterm
tgetent tgetflag tgetnum tgetstr tgoto timeout tputs
vidattr vidputs waddchnstr waddchstr
wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl
Py_RETURN_NONE; \
}
+/*
+ * Function body for a module function that dumps or restores the whole screen
+ * through a file named by a single filesystem-path argument (filename).
+ */
+#define ScreenDumpFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ PyObject *bytes; \
+ if (!PyUnicode_FSConverter(filename, &bytes)) { \
+ return NULL; \
+ } \
+ int rtn = X(PyBytes_AS_STRING(bytes)); \
+ Py_DECREF(bytes); \
+ return curses_check_err(module, rtn, # X, NULL); \
+}
+
/*********************************************************************
Global Functions
**********************************************************************/
return res;
}
+/*[clinic input]
+_curses.scr_dump
+
+ filename: object
+ The file to write to.
+ /
+
+Write the current contents of the virtual screen to a file.
+
+The file can later be used to restore the screen with scr_restore(),
+scr_init() or scr_set().
+[clinic start generated code]*/
+
+static PyObject *
+_curses_scr_dump(PyObject *module, PyObject *filename)
+/*[clinic end generated code: output=4425cfa505ac9577 input=358db4b370975345]*/
+ScreenDumpFunctionBody(scr_dump)
+
+/*[clinic input]
+_curses.scr_restore
+
+ filename: object
+ The file to read from.
+ /
+
+Set the virtual screen to the contents of a file made by scr_dump().
+
+The next call to doupdate() or refresh() restores the screen to those
+contents.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_scr_restore(PyObject *module, PyObject *filename)
+/*[clinic end generated code: output=71d669fb560fa57b input=30b1d6b2c328dd55]*/
+ScreenDumpFunctionBody(scr_restore)
+
+/*[clinic input]
+_curses.scr_init
+
+ filename: object
+ The file to read from.
+ /
+
+Initialize the assumed terminal contents from a scr_dump() file.
+
+Use it as what the terminal currently displays, for example after
+another program has drawn the screen.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_scr_init(PyObject *module, PyObject *filename)
+/*[clinic end generated code: output=2e861d381d710419 input=81c45e4702124ef6]*/
+ScreenDumpFunctionBody(scr_init)
+
+/*[clinic input]
+_curses.scr_set
+
+ filename: object
+ The file to read from.
+ /
+
+Use a scr_dump() file as both the virtual screen and the terminal.
+
+This combines the effects of scr_restore() and scr_init().
+[clinic start generated code]*/
+
+static PyObject *
+_curses_scr_set(PyObject *module, PyObject *filename)
+/*[clinic end generated code: output=6056fdec12c5935f input=d248c20543cc289b]*/
+ScreenDumpFunctionBody(scr_set)
+
/*[clinic input]
_curses.halfdelay
_CURSES_RESIZETERM_METHODDEF
_CURSES_RESIZE_TERM_METHODDEF
_CURSES_SAVETTY_METHODDEF
+ _CURSES_SCR_DUMP_METHODDEF
+ _CURSES_SCR_INIT_METHODDEF
+ _CURSES_SCR_RESTORE_METHODDEF
+ _CURSES_SCR_SET_METHODDEF
#if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102
_CURSES_GET_ESCDELAY_METHODDEF
_CURSES_SET_ESCDELAY_METHODDEF
#define _CURSES_GETWIN_METHODDEF \
{"getwin", (PyCFunction)_curses_getwin, METH_O, _curses_getwin__doc__},
+PyDoc_STRVAR(_curses_scr_dump__doc__,
+"scr_dump($module, filename, /)\n"
+"--\n"
+"\n"
+"Write the current contents of the virtual screen to a file.\n"
+"\n"
+" filename\n"
+" The file to write to.\n"
+"\n"
+"The file can later be used to restore the screen with scr_restore(),\n"
+"scr_init() or scr_set().");
+
+#define _CURSES_SCR_DUMP_METHODDEF \
+ {"scr_dump", (PyCFunction)_curses_scr_dump, METH_O, _curses_scr_dump__doc__},
+
+PyDoc_STRVAR(_curses_scr_restore__doc__,
+"scr_restore($module, filename, /)\n"
+"--\n"
+"\n"
+"Set the virtual screen to the contents of a file made by scr_dump().\n"
+"\n"
+" filename\n"
+" The file to read from.\n"
+"\n"
+"The next call to doupdate() or refresh() restores the screen to those\n"
+"contents.");
+
+#define _CURSES_SCR_RESTORE_METHODDEF \
+ {"scr_restore", (PyCFunction)_curses_scr_restore, METH_O, _curses_scr_restore__doc__},
+
+PyDoc_STRVAR(_curses_scr_init__doc__,
+"scr_init($module, filename, /)\n"
+"--\n"
+"\n"
+"Initialize the assumed terminal contents from a scr_dump() file.\n"
+"\n"
+" filename\n"
+" The file to read from.\n"
+"\n"
+"Use it as what the terminal currently displays, for example after\n"
+"another program has drawn the screen.");
+
+#define _CURSES_SCR_INIT_METHODDEF \
+ {"scr_init", (PyCFunction)_curses_scr_init, METH_O, _curses_scr_init__doc__},
+
+PyDoc_STRVAR(_curses_scr_set__doc__,
+"scr_set($module, filename, /)\n"
+"--\n"
+"\n"
+"Use a scr_dump() file as both the virtual screen and the terminal.\n"
+"\n"
+" filename\n"
+" The file to read from.\n"
+"\n"
+"This combines the effects of scr_restore() and scr_init().");
+
+#define _CURSES_SCR_SET_METHODDEF \
+ {"scr_set", (PyCFunction)_curses_scr_set, METH_O, _curses_scr_set__doc__},
+
PyDoc_STRVAR(_curses_halfdelay__doc__,
"halfdelay($module, tenths, /)\n"
"--\n"
#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=9d7ca194927796d8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=864fa5c0f22fcad3 input=a9049054013a1b77]*/