]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Adding classmethod cursor_position() to class BaseDPXApplication.
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 1 Feb 2024 16:33:32 +0000 (17:33 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 1 Feb 2024 16:33:32 +0000 (17:33 +0100)
lib/pp_admintools/app/__init__.py

index 0ffc86b5b52362f45c1917c11cf8355a432895fa..d2b43326313d94bcbddde7d68337bed5915be9f1 100644 (file)
@@ -10,7 +10,12 @@ from __future__ import absolute_import
 
 # Standard modules
 import logging
+import re
 import shutil
+import sys
+import termios
+
+from collections import namedtuple
 
 # Third party modules
 from fb_tools.cfg_app import FbConfigApplication
@@ -31,8 +36,21 @@ LOG = logging.getLogger(__name__)
 _ = XLATOR.gettext
 ngettext = XLATOR.ngettext
 
-__version__ = '0.8.0'
+__version__ = '0.9.0'
+
+
+# =============================================================================
+class CursorPosition(namedtuple('CursorPosition', ['x', 'y'])):
+    """A CursorPosition object describes the current posion of the terminal cursor."""
+
+    __slots__ = ()
 
+    # -------------------------------------------------------------------------
+    def __str__(self):
+        """Typecasting into a string object."""
+        msg = _("Cursor position:")
+        msg += ' x = {x:3d}, y = {y:3d}'.format(x=self.x, y=self.y)
+        return msg
 
 # =============================================================================
 class BaseDPXApplication(FbConfigApplication):
@@ -43,6 +61,8 @@ class BaseDPXApplication(FbConfigApplication):
     # show_force_option = False
     show_simulate_option = True
 
+    max_term_line_length = 150
+
     # -------------------------------------------------------------------------
     def __init__(
         self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None,
@@ -129,5 +149,42 @@ class BaseDPXApplication(FbConfigApplication):
         else:
             LOG.debug(_("Don't using a logfile."))
 
+    # -------------------------------------------------------------------------
+    @classmethod
+    def cursor_position(cls):
+        """
+        Retrieves the current position of the terminal cursor.
+
+        It returns these position as a CursorPosition object.
+        A position of (-1, -1) means, the position could not be evaluated.
+        """
+        old_stdin_mode = termios.tcgetattr(sys.stdin)
+        stdin_mode = termios.tcgetattr(sys.stdin)
+        stdin_mode[3] = stdin_mode[3] & ~(termios.ECHO | termios.ICANON)
+        termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, stdin_mode)
+        res = None
+
+        try:
+            out = ""
+            sys.stdout.write("\x1b[6n")
+            sys.stdout.flush()
+            while not out.endswith('R'):
+                out += sys.stdin.read(1)
+            res = re.match(r".*\[(?P<y>\d*);(?P<x>\d*)R", out)
+        finally:
+            termios.tcsetattr(sys.stdin, termios.TCSAFLUSH, old_stdin_mode)
+
+        if res:
+            return CursorPosition(int(res.group("x")), int(res.group("y")))
+
+        return CursorPosition(-1, -1)
+
+
+# =============================================================================
+
+if __name__ == '__main__':
+
+    pass
+
 
 # vim: ts=4 et list