Source code for osrf_pycommon.terminal_utils

# Copyright 2014 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
This module has a miscellaneous set of functions for working with terminals.

You can use the :py:func:`get_terminal_dimensions` to get the width and
height of the terminal as a tuple.

You can also use the :py:func:`is_tty` function to determine if a given object
is a tty.
"""

import os
import struct
import subprocess

__all__ = ['GetTerminalDimensionsError', 'get_terminal_dimensions', 'is_tty']


[docs]class GetTerminalDimensionsError(Exception): """Raised when the terminal dimensions cannot be determined.""" pass
def _get_terminal_dimensions_windows(): try: from ctypes import create_string_buffer from ctypes import windll except ImportError as exc: raise GetTerminalDimensionsError("Failed to get dimensions: {0}" .format(exc)) STDOUT = -11 h = windll.kernel32.GetStdHandle(STDOUT) buffer_info = create_string_buffer(22) if not windll.kernel32.GetConsoleScreenBufferInfo(h, buffer_info): raise GetTerminalDimensionsError( "Call to windll.kernel32.GetConsoleScreenBufferInfo failed") try: (_, _, _, _, _, left, top, right, bottom, _, _) \ = struct.unpack("hhhhHhhhhhh", buffer_info.raw) except struct.error as exc: raise GetTerminalDimensionsError("Failed to unpack data: {0}" .format(exc)) width = right - left + 1 height = bottom - top + 1 return width, height def _get_terminal_dimensions_unix(): # This function uses `tput` and should work on any Unix system # See: http://en.wikipedia.org/wiki/Tput try: width = subprocess.check_output(['tput', 'cols']) width = int(width.strip()) except (subprocess.CalledProcessError, ValueError) as exc: raise GetTerminalDimensionsError("Failed to get width: {0}" .format(exc)) try: height = subprocess.check_output(['tput', 'lines']) height = int(height.strip()) except (subprocess.CalledProcessError, ValueError) as exc: raise GetTerminalDimensionsError("Failed to get height: {0}" .format(exc)) return width, height
[docs]def get_terminal_dimensions(): """Returns the width and height of the terminal. :returns: width and height in that order as a tuple :rtype: tuple :raises: GetTerminalDimensionsError when the terminal dimensions cannot be determined """ if os.name in ['nt']: return _get_terminal_dimensions_windows() return _get_terminal_dimensions_unix()
[docs]def is_tty(stream): """Returns True if the given stream is a tty, else False :param stream: object to be checked for being a tty :returns: True if the given object is a tty, otherwise False :rtype: bool """ return hasattr(stream, 'isatty') and stream.isatty()