diff options
Diffstat (limited to 'third_party/python/jinxed/jinxed/_terminal.py')
-rw-r--r-- | third_party/python/jinxed/jinxed/_terminal.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/third_party/python/jinxed/jinxed/_terminal.py b/third_party/python/jinxed/jinxed/_terminal.py new file mode 100644 index 0000000000..524a67afc6 --- /dev/null +++ b/third_party/python/jinxed/jinxed/_terminal.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Avram Lubkin, All Rights Reserved + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +""" +Provides a terminal class primarily for accessing functions that depend on +a terminal which has been previously setup as well as those functions +""" + +import importlib +import io +import platform +import sys + +from jinxed.terminfo import BOOL_CAPS, NUM_CAPS +from jinxed._util import BASESTRING, error, raise_from_none + +if platform.system() == 'Windows': # pragma: no branch + from jinxed.win32 import get_term # pragma: no cover +else: + from jinxed._util import get_term + + +TERM = None + + +class Terminal(object): + """ + Persistent terminal object for functions that require a previously configured state + """ + + def __init__(self, term=None, fd=-1): # pylint: disable=invalid-name + + # Type check for term + if term is not None and not isinstance(term, BASESTRING): + raise TypeError('term must be a string or None, not %s' % type(term).__name__) + + # Type check and default handling for fd + if fd == -1: + try: + self.stream_fd = sys.stdout.fileno() + except (AttributeError, TypeError, io.UnsupportedOperation): + self.stream_fd = None + elif not isinstance(fd, int): + raise TypeError('fd must be an integer, not %s' % type(fd).__name__) + else: + self.stream_fd = fd + + # Try to dynamically determine terminal type + if term is None: + term = get_term(self.stream_fd) + + try: + self.terminfo = importlib.import_module('jinxed.terminfo.%s' % term.replace('-', '_')) + except ImportError: + raise_from_none(error('Could not find terminal %s' % term)) + + def tigetstr(self, capname): + """ + Reimplementation of curses.tigetstr() + """ + + return self.terminfo.STR_CAPS.get(capname, None) + + def tigetnum(self, capname): + """ + Reimplementation of curses.tigetnum() + """ + + return self.terminfo.NUM_CAPS.get(capname, -1 if capname in NUM_CAPS else -2) + + def tigetflag(self, capname): + """ + Reimplementation of curses.tigetflag() + """ + + if capname in self.terminfo.BOOL_CAPS: + return 1 + if capname in BOOL_CAPS: + return 0 + return -1 + + +def setupterm(term=None, fd=-1): # pylint: disable=invalid-name + """ + Reimplementation of :py:func:`curses.setupterm` + """ + + global TERM # pylint: disable=global-statement + TERM = Terminal(term, fd) + + +def tigetflag(capname): + """ + Reimplementation of :py:func:`curses.tigetflag` + """ + + if TERM is None: + raise error('Must call setupterm() first') + return TERM.tigetflag(capname) + + +def tigetnum(capname): + """ + Reimplementation of :py:func:`curses.tigetnum` + """ + + if TERM is None: + raise error('Must call setupterm() first') + return TERM.tigetnum(capname) + + +def tigetstr(capname): + """ + Reimplementation of :py:func:`curses.tigetstr` + """ + + if TERM is None: + raise error('Must call setupterm() first') + return TERM.tigetstr(capname) |