aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/_pyrepl/_minimal_curses.py
diff options
context:
space:
mode:
authorPablo Galindo Salgado <Pablogsal@gmail.com>2024-05-05 21:32:23 +0200
committerGitHub <noreply@github.com>2024-05-05 21:32:23 +0200
commitf27f8c790af1233d499b795af1c0d1b36aaecaf5 (patch)
tree22c502c6382512fafbb63e3020c8462e5400d4df /Lib/_pyrepl/_minimal_curses.py
parent40cc809902304f60c6e1c933191dd4d64e570e28 (diff)
downloadcpython-f27f8c790af1233d499b795af1c0d1b36aaecaf5.tar.gz
cpython-f27f8c790af1233d499b795af1c0d1b36aaecaf5.zip
gh-111201: A new Python REPL (GH-111567)
Co-authored-by: Łukasz Langa <lukasz@langa.pl> Co-authored-by: Marta Gómez Macías <mgmacias@google.com> Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Diffstat (limited to 'Lib/_pyrepl/_minimal_curses.py')
-rw-r--r--Lib/_pyrepl/_minimal_curses.py68
1 files changed, 68 insertions, 0 deletions
diff --git a/Lib/_pyrepl/_minimal_curses.py b/Lib/_pyrepl/_minimal_curses.py
new file mode 100644
index 00000000000..0757fb2c664
--- /dev/null
+++ b/Lib/_pyrepl/_minimal_curses.py
@@ -0,0 +1,68 @@
+"""Minimal '_curses' module, the low-level interface for curses module
+which is not meant to be used directly.
+
+Based on ctypes. It's too incomplete to be really called '_curses', so
+to use it, you have to import it and stick it in sys.modules['_curses']
+manually.
+
+Note that there is also a built-in module _minimal_curses which will
+hide this one if compiled in.
+"""
+
+import ctypes
+import ctypes.util
+
+
+class error(Exception):
+ pass
+
+
+def _find_clib():
+ trylibs = ["ncursesw", "ncurses", "curses"]
+
+ for lib in trylibs:
+ path = ctypes.util.find_library(lib)
+ if path:
+ return path
+ raise ModuleNotFoundError("curses library not found", name="_pyrepl._minimal_curses")
+
+
+_clibpath = _find_clib()
+clib = ctypes.cdll.LoadLibrary(_clibpath)
+
+clib.setupterm.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
+clib.setupterm.restype = ctypes.c_int
+
+clib.tigetstr.argtypes = [ctypes.c_char_p]
+clib.tigetstr.restype = ctypes.POINTER(ctypes.c_char)
+
+clib.tparm.argtypes = [ctypes.c_char_p] + 9 * [ctypes.c_int] # type: ignore[operator]
+clib.tparm.restype = ctypes.c_char_p
+
+OK = 0
+ERR = -1
+
+# ____________________________________________________________
+
+
+def setupterm(termstr, fd):
+ err = ctypes.c_int(0)
+ result = clib.setupterm(termstr, fd, ctypes.byref(err))
+ if result == ERR:
+ raise error("setupterm() failed (err=%d)" % err.value)
+
+
+def tigetstr(cap):
+ if not isinstance(cap, bytes):
+ cap = cap.encode("ascii")
+ result = clib.tigetstr(cap)
+ if ctypes.cast(result, ctypes.c_void_p).value == ERR:
+ return None
+ return ctypes.cast(result, ctypes.c_char_p).value
+
+
+def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
+ result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
+ if result is None:
+ raise error("tparm() returned NULL")
+ return result