Added: Support for non truecolor terminals through 24-bit to 256-color conversion

pull/236/head
aristocratos 2021-01-06 16:25:43 +01:00
parent b80217e63c
commit 50ef08ef58
2 changed files with 74 additions and 18 deletions

View File

@ -98,6 +98,7 @@ Upgrade psutil with `sudo pip3 install psutil --upgrade`
For correct display, a terminal with support for: For correct display, a terminal with support for:
* 24-bit truecolor ([See list of terminals with truecolor support](https://gist.github.com/XVilka/8346728)) * 24-bit truecolor ([See list of terminals with truecolor support](https://gist.github.com/XVilka/8346728))
* 256-color terminals are supported through 24-bit to 256-color conversion when setting "truecolor" to False in the options or with "-lc/--low-color" argument.
* Wide characters (Are sometimes problematic in web-based terminals) * Wide characters (Are sometimes problematic in web-based terminals)
Also needs a UTF8 locale and a font that covers: Also needs a UTF8 locale and a font that covers:
@ -346,14 +347,17 @@ Config files stored in "$HOME/.config/bpytop" folder
"/etc/bpytop.conf" will be used as default seed for config file creation if it exists. "/etc/bpytop.conf" will be used as default seed for config file creation if it exists.
```bash ```bash
#? Config file for bpytop v. 1.0.54 #? Config file for bpytop v. 1.0.57
#* Color theme, looks for a .theme file in "/usr/[local/]share/bpytop/themes" and "~/.config/bpytop/themes", "Default" for builtin default theme. #* Color theme, looks for a .theme file in "/usr/[local/]share/bpytop/themes" and "~/.config/bpytop/themes", "Default" for builtin default theme.
#* Prefix name by a plus sign (+) for a theme located in user themes folder, i.e. color_theme="+monokai" #* Prefix name by a plus sign (+) for a theme located in user themes folder, i.e. color_theme="+monokai"
color_theme="monokai" color_theme="Default"
#* If the theme set background should be shown, set to False if you want terminal background transparency #* If the theme set background should be shown, set to False if you want terminal background transparency
theme_background=True theme_background=False
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
truecolor=True
#* Manually set which boxes to show. Available values are "cpu mem net proc", seperate values with whitespace. #* Manually set which boxes to show. Available values are "cpu mem net proc", seperate values with whitespace.
shown_boxes="cpu mem net proc" shown_boxes="cpu mem net proc"
@ -424,6 +428,12 @@ swap_disk=True
#* If mem box should be split to also show disks info. #* If mem box should be split to also show disks info.
show_disks=True show_disks=True
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
only_physical=True
#* Read disks list from /etc/fstab. This also disables only_physical.
use_fstab=False
#* Set fixed values for network graphs, default "10M" = 10 Mibibytes, possible units "K", "M", "G", append with "bit" for bits instead of bytes, i.e "100mbit" #* Set fixed values for network graphs, default "10M" = 10 Mibibytes, possible units "K", "M", "G", append with "bit" for bits instead of bytes, i.e "100mbit"
net_download="100Mbit" net_download="100Mbit"
net_upload="100Mbit" net_upload="100Mbit"
@ -437,6 +447,9 @@ net_sync=True
#* If the network graphs color gradient should scale to bandwith usage or auto scale, bandwith usage is based on "net_download" and "net_upload" values #* If the network graphs color gradient should scale to bandwith usage or auto scale, bandwith usage is based on "net_download" and "net_upload" values
net_color_fixed=False net_color_fixed=False
#* Starts with the Network Interface specified here.
net_iface=""
#* Show battery stats in top right if battery is present #* Show battery stats in top right if battery is present
show_battery=True show_battery=True
@ -455,14 +468,15 @@ log_level=DEBUG
#### Command line options: #### Command line options:
``` text ``` text
usage: bpytop.py [-h] [-b BOXES] [-v] [--debug] usage: bpytop.py [-h] [-b BOXES] [-lc] [-v] [--debug]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
-b BOXES, --boxes BOXES -b BOXES, --boxes BOXES
Which boxes to show at start, example: -b "cpu mem net proc" which boxes to show at start, example: -b "cpu mem net proc"
-v, --version Show version info and exit -lc, --low-color disable truecolor, converts 24-bit colors to 256-color
--debug Start with loglevel set to DEBUG overriding value set in config -v, --version show version info and exit
--debug start with loglevel set to DEBUG overriding value set in config
``` ```
## TODO ## TODO

View File

@ -59,9 +59,10 @@ VERSION: str = "1.0.56"
#? Argument parser -------------------------------------------------------------------------------> #? Argument parser ------------------------------------------------------------------------------->
args = argparse.ArgumentParser() args = argparse.ArgumentParser()
args.add_argument("-b", "--boxes", action="store", dest="boxes", help ="Which boxes to show at start, example: -b \"cpu mem net proc\"") args.add_argument("-b", "--boxes", action="store", dest="boxes", help = "which boxes to show at start, example: -b \"cpu mem net proc\"")
args.add_argument("-v", "--version", action="store_true" ,help ="Show version info and exit") args.add_argument("-lc", "--low-color", action="store_true", help = "disable truecolor, converts 24-bit colors to 256-color")
args.add_argument("--debug", action="store_true" ,help ="Start with loglevel set to DEBUG overriding value set in config") args.add_argument("-v", "--version", action="store_true", help = "show version info and exit")
args.add_argument("--debug", action="store_true", help = "start with loglevel set to DEBUG overriding value set in config")
stdargs = args.parse_args() stdargs = args.parse_args()
if stdargs.version: if stdargs.version:
@ -70,8 +71,8 @@ if stdargs.version:
raise SystemExit(0) raise SystemExit(0)
ARG_BOXES: str = stdargs.boxes ARG_BOXES: str = stdargs.boxes
LOW_COLOR: bool = stdargs.low_color
DEBUG = stdargs.debug DEBUG: bool = stdargs.debug
#? Variables -------------------------------------------------------------------------------------> #? Variables ------------------------------------------------------------------------------------->
@ -94,6 +95,9 @@ color_theme="$color_theme"
#* If the theme set background should be shown, set to False if you want terminal background transparency #* If the theme set background should be shown, set to False if you want terminal background transparency
theme_background=$theme_background theme_background=$theme_background
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
truecolor=$truecolor
#* Manually set which boxes to show. Available values are "cpu mem net proc", seperate values with whitespace. #* Manually set which boxes to show. Available values are "cpu mem net proc", seperate values with whitespace.
shown_boxes="$shown_boxes" shown_boxes="$shown_boxes"
@ -183,7 +187,7 @@ net_sync=$net_sync
net_color_fixed=$net_color_fixed net_color_fixed=$net_color_fixed
#* Starts with the Network Interface specified here. #* Starts with the Network Interface specified here.
net_iface=$net_iface net_iface="$net_iface"
#* Show battery stats in top right if battery is present #* Show battery stats in top right if battery is present
show_battery=$show_battery show_battery=$show_battery
@ -367,10 +371,12 @@ class Config:
keys: List[str] = ["color_theme", "update_ms", "proc_sorting", "proc_reversed", "proc_tree", "check_temp", "draw_clock", "background_update", "custom_cpu_name", keys: List[str] = ["color_theme", "update_ms", "proc_sorting", "proc_reversed", "proc_tree", "check_temp", "draw_clock", "background_update", "custom_cpu_name",
"proc_colors", "proc_gradient", "proc_per_core", "proc_mem_bytes", "disks_filter", "update_check", "log_level", "mem_graphs", "show_swap", "proc_colors", "proc_gradient", "proc_per_core", "proc_mem_bytes", "disks_filter", "update_check", "log_level", "mem_graphs", "show_swap",
"swap_disk", "show_disks", "use_fstab", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "theme_background", "swap_disk", "show_disks", "use_fstab", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "theme_background",
"net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes", "net_iface", "only_physical"] "net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes", "net_iface", "only_physical",
"truecolor"]
conf_dict: Dict[str, Union[str, int, bool]] = {} conf_dict: Dict[str, Union[str, int, bool]] = {}
color_theme: str = "Default" color_theme: str = "Default"
theme_background: bool = True theme_background: bool = True
truecolor: bool = True
shown_boxes: str = "cpu mem net proc" shown_boxes: str = "cpu mem net proc"
update_ms: int = 2000 update_ms: int = 2000
proc_update_mult: int = 2 proc_update_mult: int = 2
@ -1067,6 +1073,9 @@ class Color:
self.red, self.green, self.blue = self.dec self.red, self.green, self.blue = self.dec
self.escape = f'\033[{38 if self.depth == "fg" else 48};2;{";".join(str(c) for c in self.dec)}m' self.escape = f'\033[{38 if self.depth == "fg" else 48};2;{";".join(str(c) for c in self.dec)}m'
if not CONFIG.truecolor or LOW_COLOR:
self.escape = f'{self.truecolor_to_256(rgb=self.dec, depth=self.depth)}'
def __str__(self) -> str: def __str__(self) -> str:
return self.escape return self.escape
@ -1080,6 +1089,19 @@ class Color:
if len(args) < 1: return "" if len(args) < 1: return ""
return f'{self.escape}{"".join(args)}{getattr(Term, self.depth)}' return f'{self.escape}{"".join(args)}{getattr(Term, self.depth)}'
@staticmethod
def truecolor_to_256(rgb: Tuple[int, int, int], depth: str="fg") -> str:
out: str = ""
pre: str = f'\033[{"38" if depth == "fg" else "48"};5;'
greyscale: Tuple[int, int, int] = ( rgb[0] // 11, rgb[1] // 11, rgb[2] // 11 )
if greyscale[0] == greyscale[1] == greyscale[2]:
out = f'{pre}{232 + greyscale[0]}m'
else:
out = f'{pre}{round(rgb[0] / 51) * 36 + round(rgb[1] / 51) * 6 + round(rgb[2] / 51) + 16}m'
return out
@staticmethod @staticmethod
def escape_color(hexa: str = "", r: int = 0, g: int = 0, b: int = 0, depth: str = "fg") -> str: def escape_color(hexa: str = "", r: int = 0, g: int = 0, b: int = 0, depth: str = "fg") -> str:
"""Returns escape sequence to set color """Returns escape sequence to set color
@ -1093,13 +1115,22 @@ class Color:
try: try:
if len(hexa) == 3: if len(hexa) == 3:
c = int(hexa[1:], base=16) c = int(hexa[1:], base=16)
color = f'\033[{dint};2;{c};{c};{c}m' if CONFIG.truecolor and not LOW_COLOR:
color = f'\033[{dint};2;{c};{c};{c}m'
else:
color = f'{Color.truecolor_to_256(rgb=(c, c, c), depth=depth)}'
elif len(hexa) == 7: elif len(hexa) == 7:
color = f'\033[{dint};2;{int(hexa[1:3], base=16)};{int(hexa[3:5], base=16)};{int(hexa[5:7], base=16)}m' if CONFIG.truecolor and not LOW_COLOR:
color = f'\033[{dint};2;{int(hexa[1:3], base=16)};{int(hexa[3:5], base=16)};{int(hexa[5:7], base=16)}m'
else:
color = f'{Color.truecolor_to_256(rgb=(int(hexa[1:3], base=16), int(hexa[3:5], base=16), int(hexa[5:7], base=16)), depth=depth)}'
except ValueError as e: except ValueError as e:
errlog.exception(f'{e}') errlog.exception(f'{e}')
else: else:
color = f'\033[{dint};2;{r};{g};{b}m' if CONFIG.truecolor and not LOW_COLOR:
color = f'\033[{dint};2;{r};{g};{b}m'
else:
color = f'{Color.truecolor_to_256(rgb=(r, g, b), depth=depth)}'
return color return color
@classmethod @classmethod
@ -3961,6 +3992,16 @@ class Menu:
'', '',
'Set to False if you want terminal background', 'Set to False if you want terminal background',
'transparency.'], 'transparency.'],
"truecolor" : [
'Sets if 24-bit truecolor should be used.',
'(Requires restart to take effect!)',
'',
'Will convert 24-bit colors to 256 color',
'(6x6x6 color cube) if False.',
'',
'Set to False if your terminal doesn\'t have',
'truecolor support and can\'t convert to',
'256-color.'],
"shown_boxes" : [ "shown_boxes" : [
'Manually set which boxes to show.', 'Manually set which boxes to show.',
'', '',
@ -3978,7 +4019,7 @@ class Menu:
'Max value: 86400000 ms = 24 hours.'], 'Max value: 86400000 ms = 24 hours.'],
"draw_clock" : [ "draw_clock" : [
'Draw a clock at top of screen.', 'Draw a clock at top of screen.',
'Only visible if cpu box is enabled.' '(Only visible if cpu box is enabled!)',
'', '',
'Formatting according to strftime, empty', 'Formatting according to strftime, empty',
'string to disable.', 'string to disable.',
@ -4001,6 +4042,7 @@ class Menu:
'too much for a comfortable experience.'], 'too much for a comfortable experience.'],
"show_battery" : [ "show_battery" : [
'Show battery stats.', 'Show battery stats.',
'(Only visible if cpu box is enabled!)',
'', '',
'Show battery stats in the top right corner', 'Show battery stats in the top right corner',
'if a battery is present.'], 'if a battery is present.'],