changeset 3046:d9f328374473

jp: dark and light theme: - `background` setting can now be used in sat.conf to indicate if the terminal use a `dark` or a `light` colour - if `background` is not set or set to `auto`, the background colour is autodetected - Jp.get_config (or CommandBase.get_config) method can now be used to retrieve a setting
author Goffi <goffi@goffi.org>
date Tue, 01 Oct 2019 22:49:10 +0200
parents 6af44ca3beac
children cf843dd7c345
files doc/configuration.rst sat_frontends/jp/base.py sat_frontends/jp/cmd_blog.py sat_frontends/jp/common.py
diffstat 4 files changed, 65 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/doc/configuration.rst	Tue Oct 01 22:49:10 2019 +0200
+++ b/doc/configuration.rst	Tue Oct 01 22:49:10 2019 +0200
@@ -103,6 +103,9 @@
     hosts_dict = {
         "example.org": {"host": "127.0.0.1"}
         }
+    ; background luminance, used by terminal frontends
+    ; can be "auto" (default) to autodetect, "dark" or "light"
+    background = auto
 
     [plugin account]
     ; where a new account must be created
--- a/sat_frontends/jp/base.py	Tue Oct 01 22:49:10 2019 +0200
+++ b/sat_frontends/jp/base.py	Tue Oct 01 22:49:10 2019 +0200
@@ -30,6 +30,8 @@
 import os.path
 import argparse
 import inspect
+import tty
+import termios
 from pathlib import Path
 from glob import iglob
 from importlib import import_module
@@ -38,6 +40,8 @@
 from sat.tools.common import dynamic_import
 from sat.tools.common import uri
 from sat.tools.common import date_utils
+from sat.tools.common import utils
+from sat.tools.common.ansi import ANSI as A
 from sat.core import exceptions
 import sat_frontends.jp
 from sat_frontends.jp.loops import QuitException, getJPLoop
@@ -100,6 +104,8 @@
         @attribute progress_failure(callable): method to call when progress failed
             by default display a message
         """
+        self.sat_conf = main_config
+        self.set_color_theme()
         bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
         if bridge_module is None:
             log.error("Can't import {} bridge".format(bridge_name))
@@ -108,6 +114,57 @@
         self.bridge = bridge_module.AIOBridge()
         self._onQuitCallbacks = []
 
+    def get_config(self, name, section='jp', default=None):
+        """Retrieve a setting value from sat.conf"""
+        return config.getConfig(self.sat_conf, section, name, default=default)
+
+    def guess_background(self):
+        stdin_fd = sys.stdin.fileno()
+        old_settings = termios.tcgetattr(stdin_fd)
+        try:
+            tty.setraw(sys.stdin.fileno())
+            # we request background color
+            sys.stdout.write("\033]11;?\a")
+            sys.stdout.flush()
+            expected = "\033]11;rgb:"
+            for c in expected:
+                ch = sys.stdin.read(1)
+                if ch != c:
+                    # background id is not supported
+                    # TODO: log something?
+                    return
+            red, green, blue = [int(c, 16)/65535 for c in sys.stdin.read(14).split('/')]
+            # '\a' is the last character
+            sys.stdin.read(1)
+        finally:
+            termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
+
+        lum = utils.per_luminance(red, green, blue)
+        if lum <= 0.5:
+            return 'dark'
+        else:
+            return 'light'
+
+    def set_color_theme(self):
+        background = self.get_config('background', default='auto')
+        if background == 'auto':
+            background = self.guess_background()
+        if background not in ('dark', 'light'):
+            raise exceptions.ConfigError(_(
+                f'Invalid value set for "background" ({background!r}), please check '
+                f'your settings in sat.conf'))
+        if background == 'light':
+            C.A_HEADER = A.FG_MAGENTA
+            C.A_SUBHEADER = A.BOLD + A.FG_RED
+            C.A_LEVEL_COLORS = (C.A_HEADER, A.BOLD + A.FG_BLUE, A.FG_MAGENTA, A.FG_CYAN)
+            C.A_SUCCESS = A.FG_GREEN
+            C.A_FAILURE = A.BOLD + A.FG_RED
+            C.A_WARNING = A.FG_RED
+            C.A_PROMPT_PATH = A.FG_BLUE
+            C.A_PROMPT_SUF = A.BOLD
+            C.A_DIRECTORY = A.BOLD + A.FG_MAGENTA
+            C.A_FILE = A.FG_BLACK
+
     def _bridgeConnected(self):
         self.parser = argparse.ArgumentParser(
             formatter_class=argparse.RawDescriptionHelpFormatter, description=DESCRIPTION)
@@ -898,6 +955,10 @@
         self.add_parser_options()
 
     @property
+    def sat_conf(self):
+        return self.host.sat_conf
+
+    @property
     def args(self):
         return self.host.args
 
--- a/sat_frontends/jp/cmd_blog.py	Tue Oct 01 22:49:10 2019 +0200
+++ b/sat_frontends/jp/cmd_blog.py	Tue Oct 01 22:49:10 2019 +0200
@@ -719,7 +719,7 @@
         else:
             aionotify = None
 
-        sat_conf = config.parseMainConf()
+        sat_conf = self.sat_conf
         SYNTAX_EXT.update(config.getConfig(sat_conf, "jp", CONF_SYNTAX_EXT, {}))
 
         try:
--- a/sat_frontends/jp/common.py	Tue Oct 01 22:49:10 2019 +0200
+++ b/sat_frontends/jp/common.py	Tue Oct 01 22:49:10 2019 +0200
@@ -126,7 +126,6 @@
             and vice versa
         """
         self.host = host
-        self.sat_conf = config.parseMainConf()
         self.cat_dir = cat_dir
         self.use_metadata = use_metadata