mirror of https://github.com/aristocratos/bpytop
Changed: All boxes are now toggeable with key 1-4
parent
24432152a7
commit
3cde5a3f9d
430
bpytop.py
430
bpytop.py
|
@ -59,11 +59,9 @@ VERSION: str = "1.0.54"
|
||||||
|
|
||||||
#? Argument parser ------------------------------------------------------------------------------->
|
#? Argument parser ------------------------------------------------------------------------------->
|
||||||
args = argparse.ArgumentParser()
|
args = argparse.ArgumentParser()
|
||||||
args.add_argument("-f" , "--full" ,action="store_true" ,help ="Start in full mode showing all boxes [default]")
|
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("-p" , "--proc" ,action="store_true" ,help ="Start in minimal mode without memory and net boxes")
|
args.add_argument("-v", "--version", action="store_true" ,help ="Show version info and exit")
|
||||||
args.add_argument("-s" , "--stat" ,action="store_true" ,help ="Start in minimal mode without process box")
|
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:
|
||||||
|
@ -71,14 +69,7 @@ if stdargs.version:
|
||||||
f'psutil version: {".".join(str(x) for x in psutil.version_info)}')
|
f'psutil version: {".".join(str(x) for x in psutil.version_info)}')
|
||||||
raise SystemExit(0)
|
raise SystemExit(0)
|
||||||
|
|
||||||
ARG_MODE: str = ""
|
ARG_BOXES: str = stdargs.boxes
|
||||||
|
|
||||||
if stdargs.full:
|
|
||||||
ARG_MODE = "full"
|
|
||||||
elif stdargs.proc:
|
|
||||||
ARG_MODE = "proc"
|
|
||||||
elif stdargs.stat:
|
|
||||||
ARG_MODE = "stat"
|
|
||||||
|
|
||||||
DEBUG = stdargs.debug
|
DEBUG = stdargs.debug
|
||||||
|
|
||||||
|
@ -103,8 +94,8 @@ 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
|
||||||
|
|
||||||
#* Set bpytop view mode, "full" for everything shown, "proc" for cpu stats and processes, "stat" for cpu, mem, disks and net stats shown.
|
#* Manually set which boxes to show. Available values are "cpu mem net proc", seperate values with whitespace.
|
||||||
view_mode=$view_mode
|
shown_boxes="$shown_boxes"
|
||||||
|
|
||||||
#* Update time in milliseconds, increases automatically if set below internal loops processing time, recommended 2000 ms or above for better sample times for graphs.
|
#* Update time in milliseconds, increases automatically if set below internal loops processing time, recommended 2000 ms or above for better sample times for graphs.
|
||||||
update_ms=$update_ms
|
update_ms=$update_ms
|
||||||
|
@ -310,6 +301,8 @@ UNITS: Dict[str, Tuple[str, ...]] = {
|
||||||
"byte" : ("Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB")
|
"byte" : ("Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBSCRIPT: Tuple[str, ...] = ("₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉")
|
||||||
|
|
||||||
#? Setup error logger ---------------------------------------------------------------->
|
#? Setup error logger ---------------------------------------------------------------->
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -363,11 +356,12 @@ class Config:
|
||||||
'''Holds all config variables and functions for loading from and saving to disk'''
|
'''Holds all config variables and functions for loading from and saving to disk'''
|
||||||
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", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "view_mode", "theme_background",
|
"swap_disk", "show_disks", "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"]
|
"net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes"]
|
||||||
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
|
||||||
|
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
|
||||||
proc_sorting: str = "cpu lazy"
|
proc_sorting: str = "cpu lazy"
|
||||||
|
@ -397,7 +391,6 @@ class Config:
|
||||||
net_sync: bool = False
|
net_sync: bool = False
|
||||||
show_battery: bool = True
|
show_battery: bool = True
|
||||||
show_init: bool = True
|
show_init: bool = True
|
||||||
view_mode: str = "full"
|
|
||||||
log_level: str = "WARNING"
|
log_level: str = "WARNING"
|
||||||
|
|
||||||
warnings: List[str] = []
|
warnings: List[str] = []
|
||||||
|
@ -406,8 +399,6 @@ class Config:
|
||||||
sorting_options: List[str] = ["pid", "program", "arguments", "threads", "user", "memory", "cpu lazy", "cpu responsive"]
|
sorting_options: List[str] = ["pid", "program", "arguments", "threads", "user", "memory", "cpu lazy", "cpu responsive"]
|
||||||
log_levels: List[str] = ["ERROR", "WARNING", "INFO", "DEBUG"]
|
log_levels: List[str] = ["ERROR", "WARNING", "INFO", "DEBUG"]
|
||||||
|
|
||||||
view_modes: List[str] = ["full", "proc", "stat"]
|
|
||||||
|
|
||||||
cpu_sensors: List[str] = [ "Auto" ]
|
cpu_sensors: List[str] = [ "Auto" ]
|
||||||
|
|
||||||
if hasattr(psutil, "sensors_temperatures"):
|
if hasattr(psutil, "sensors_temperatures"):
|
||||||
|
@ -494,9 +485,6 @@ class Config:
|
||||||
if "log_level" in new_config and not new_config["log_level"] in self.log_levels:
|
if "log_level" in new_config and not new_config["log_level"] in self.log_levels:
|
||||||
new_config["log_level"] = "_error_"
|
new_config["log_level"] = "_error_"
|
||||||
self.warnings.append(f'Config key "log_level" didn\'t get an acceptable value!')
|
self.warnings.append(f'Config key "log_level" didn\'t get an acceptable value!')
|
||||||
if "view_mode" in new_config and not new_config["view_mode"] in self.view_modes:
|
|
||||||
new_config["view_mode"] = "_error_"
|
|
||||||
self.warnings.append(f'Config key "view_mode" didn\'t get an acceptable value!')
|
|
||||||
if "update_ms" in new_config and int(new_config["update_ms"]) < 100:
|
if "update_ms" in new_config and int(new_config["update_ms"]) < 100:
|
||||||
new_config["update_ms"] = 100
|
new_config["update_ms"] = 100
|
||||||
self.warnings.append(f'Config key "update_ms" can\'t be lower than 100!')
|
self.warnings.append(f'Config key "update_ms" can\'t be lower than 100!')
|
||||||
|
@ -506,6 +494,12 @@ class Config:
|
||||||
if "cpu_sensor" in new_config and not new_config["cpu_sensor"] in self.cpu_sensors:
|
if "cpu_sensor" in new_config and not new_config["cpu_sensor"] in self.cpu_sensors:
|
||||||
new_config["cpu_sensor"] = "_error_"
|
new_config["cpu_sensor"] = "_error_"
|
||||||
self.warnings.append(f'Config key "cpu_sensor" does not contain an available sensor!')
|
self.warnings.append(f'Config key "cpu_sensor" does not contain an available sensor!')
|
||||||
|
if "shown_boxes" in new_config and not new_config["shown_boxes"] == "":
|
||||||
|
for box in new_config["shown_boxes"].split(): #type: ignore
|
||||||
|
if not box in ["cpu", "mem", "net", "proc"]:
|
||||||
|
new_config["shown_boxes"] = "_error_"
|
||||||
|
self.warnings.append(f'Config key "shown_boxes" contains invalid box names!')
|
||||||
|
break
|
||||||
return new_config
|
return new_config
|
||||||
|
|
||||||
def save_config(self):
|
def save_config(self):
|
||||||
|
@ -540,6 +534,14 @@ except Exception as e:
|
||||||
errlog.exception(f'{e}')
|
errlog.exception(f'{e}')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
if ARG_BOXES:
|
||||||
|
_new_boxes: List = []
|
||||||
|
for _box in ARG_BOXES.split():
|
||||||
|
if _box in ["cpu", "mem", "net", "proc"]:
|
||||||
|
_new_boxes.append(_box)
|
||||||
|
CONFIG.shown_boxes = " ".join(_new_boxes)
|
||||||
|
del _box, _new_boxes
|
||||||
|
|
||||||
if SYSTEM == "Linux" and not os.path.isdir("/sys/class/power_supply"):
|
if SYSTEM == "Linux" and not os.path.isdir("/sys/class/power_supply"):
|
||||||
CONFIG.show_battery = False
|
CONFIG.show_battery = False
|
||||||
|
|
||||||
|
@ -1504,14 +1506,22 @@ class Meters:
|
||||||
class Box:
|
class Box:
|
||||||
'''Box class with all needed attributes for create_box() function'''
|
'''Box class with all needed attributes for create_box() function'''
|
||||||
name: str
|
name: str
|
||||||
|
num: int = 0
|
||||||
|
boxes: List = []
|
||||||
|
view_modes: Dict[str, List] = {"full" : ["cpu", "mem", "net", "proc"], "stat" : ["cpu", "mem", "net"], "proc" : ["cpu", "proc"]}
|
||||||
|
view_mode: str
|
||||||
|
for view_mode in view_modes:
|
||||||
|
if sorted(CONFIG.shown_boxes.split(), key=str.lower) == view_modes[view_mode]:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
view_mode = "user"
|
||||||
|
view_modes["user"] = CONFIG.shown_boxes.split()
|
||||||
height_p: int
|
height_p: int
|
||||||
width_p: int
|
width_p: int
|
||||||
x: int
|
x: int
|
||||||
y: int
|
y: int
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
proc_mode: bool = (CONFIG.view_mode == "proc" and not ARG_MODE) or ARG_MODE == "proc"
|
|
||||||
stat_mode: bool = (CONFIG.view_mode == "stat" and not ARG_MODE) or ARG_MODE == "stat"
|
|
||||||
out: str
|
out: str
|
||||||
bg: str
|
bg: str
|
||||||
_b_cpu_h: int
|
_b_cpu_h: int
|
||||||
|
@ -1532,12 +1542,14 @@ class Box:
|
||||||
@classmethod
|
@classmethod
|
||||||
def calc_sizes(cls):
|
def calc_sizes(cls):
|
||||||
'''Calculate sizes of boxes'''
|
'''Calculate sizes of boxes'''
|
||||||
|
cls.boxes = CONFIG.shown_boxes.split()
|
||||||
for sub in cls.__subclasses__():
|
for sub in cls.__subclasses__():
|
||||||
sub._calc_size() # type: ignore
|
sub._calc_size() # type: ignore
|
||||||
sub.resized = True # type: ignore
|
sub.resized = True # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_update_ms(cls, now: bool = True):
|
def draw_update_ms(cls, now: bool = True):
|
||||||
|
if not "cpu" in cls.boxes: return
|
||||||
update_string: str = f'{CONFIG.update_ms}ms'
|
update_string: str = f'{CONFIG.update_ms}ms'
|
||||||
xpos: int = CpuBox.x + CpuBox.width - len(update_string) - 15
|
xpos: int = CpuBox.x + CpuBox.width - len(update_string) - 15
|
||||||
if not "+" in Key.mouse:
|
if not "+" in Key.mouse:
|
||||||
|
@ -1553,9 +1565,10 @@ class Box:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_clock(cls, force: bool = False):
|
def draw_clock(cls, force: bool = False):
|
||||||
|
if not "cpu" in cls.boxes or not cls.clock_on: return
|
||||||
out: str = ""
|
out: str = ""
|
||||||
if force: pass
|
if force: pass
|
||||||
elif not cls.clock_on or Term.resized or strftime(CONFIG.draw_clock) == cls.clock: return
|
elif Term.resized or strftime(CONFIG.draw_clock) == cls.clock: return
|
||||||
clock_string = cls.clock = strftime(CONFIG.draw_clock)
|
clock_string = cls.clock = strftime(CONFIG.draw_clock)
|
||||||
for custom in cls.clock_custom_format:
|
for custom in cls.clock_custom_format:
|
||||||
if custom in clock_string:
|
if custom in clock_string:
|
||||||
|
@ -1572,10 +1585,28 @@ class Box:
|
||||||
if CONFIG.show_battery and hasattr(psutil, "sensors_battery") and psutil.sensors_battery():
|
if CONFIG.show_battery and hasattr(psutil, "sensors_battery") and psutil.sensors_battery():
|
||||||
Draw.out("battery")
|
Draw.out("battery")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def empty_bg(cls) -> str:
|
||||||
|
return (f'{Term.clear}{Banner.draw(Term.height // 2 - 10, center=True)}'
|
||||||
|
f'{Mv.d(1)}{Mv.l(46)}{Colors.black_bg}{Colors.default}{Fx.b}[esc] Menu'
|
||||||
|
f'{Mv.r(25)}{Fx.i}Version: {VERSION}{Fx.ui}'
|
||||||
|
f'{Mv.d(1)}{Mv.l(34)}{Fx.b}All boxes hidden!'
|
||||||
|
f'{Mv.d(1)}{Mv.l(17)}{Fx.b}[1] {Fx.ub}Toggle CPU box'
|
||||||
|
f'{Mv.d(1)}{Mv.l(18)}{Fx.b}[2] {Fx.ub}Toggle MEM box'
|
||||||
|
f'{Mv.d(1)}{Mv.l(18)}{Fx.b}[3] {Fx.ub}Toggle NET box'
|
||||||
|
f'{Mv.d(1)}{Mv.l(18)}{Fx.b}[4] {Fx.ub}Toggle PROC box'
|
||||||
|
f'{Mv.d(1)}{Mv.l(19)}{Fx.b}[m] {Fx.ub}Cycle presets'
|
||||||
|
f'{Mv.d(1)}{Mv.l(17)}{Fx.b}[q] Quit {Fx.ub}{Term.bg}{Term.fg}')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw_bg(cls, now: bool = True):
|
def draw_bg(cls, now: bool = True):
|
||||||
'''Draw all boxes outlines and titles'''
|
'''Draw all boxes outlines and titles'''
|
||||||
Draw.buffer("bg", "".join(sub._draw_bg() for sub in cls.__subclasses__()), now=now, z=1000, only_save=Menu.active, once=True) # type: ignore
|
out: str = ""
|
||||||
|
if not cls.boxes:
|
||||||
|
out = cls.empty_bg()
|
||||||
|
else:
|
||||||
|
out = "".join(sub._draw_bg() for sub in cls.__subclasses__()) # type: ignore
|
||||||
|
Draw.buffer("bg", out, now=now, z=1000, only_save=Menu.active, once=True)
|
||||||
cls.draw_update_ms(now=now)
|
cls.draw_update_ms(now=now)
|
||||||
if CONFIG.draw_clock: cls.draw_clock(force=True)
|
if CONFIG.draw_clock: cls.draw_clock(force=True)
|
||||||
|
|
||||||
|
@ -1589,6 +1620,7 @@ class SubBox:
|
||||||
|
|
||||||
class CpuBox(Box, SubBox):
|
class CpuBox(Box, SubBox):
|
||||||
name = "cpu"
|
name = "cpu"
|
||||||
|
num = 1
|
||||||
x = 1
|
x = 1
|
||||||
y = 1
|
y = 1
|
||||||
height_p = 32
|
height_p = 32
|
||||||
|
@ -1612,10 +1644,16 @@ class CpuBox(Box, SubBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _calc_size(cls):
|
def _calc_size(cls):
|
||||||
|
if not "cpu" in cls.boxes:
|
||||||
|
Box._b_cpu_h = 0
|
||||||
|
cls.width = Term.width
|
||||||
|
return
|
||||||
cpu = CpuCollector
|
cpu = CpuCollector
|
||||||
height_p: int
|
height_p: int
|
||||||
if cls.proc_mode: height_p = 20
|
if cls.boxes == ["cpu"]:
|
||||||
else: height_p = cls.height_p
|
height_p = 100
|
||||||
|
else:
|
||||||
|
height_p = cls.height_p
|
||||||
cls.width = round(Term.width * cls.width_p / 100)
|
cls.width = round(Term.width * cls.width_p / 100)
|
||||||
cls.height = round(Term.height * height_p / 100)
|
cls.height = round(Term.height * height_p / 100)
|
||||||
if cls.height < 8: cls.height = 8
|
if cls.height < 8: cls.height = 8
|
||||||
|
@ -1643,6 +1681,7 @@ class CpuBox(Box, SubBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_bg(cls) -> str:
|
def _draw_bg(cls) -> str:
|
||||||
|
if not "cpu" in cls.boxes: return ""
|
||||||
if not "M" in Key.mouse:
|
if not "M" in Key.mouse:
|
||||||
Key.mouse["M"] = [[cls.x + 10 + i, cls.y] for i in range(6)]
|
Key.mouse["M"] = [[cls.x + 10 + i, cls.y] for i in range(6)]
|
||||||
return (f'{create_box(box=cls, line_color=THEME.cpu_box)}'
|
return (f'{create_box(box=cls, line_color=THEME.cpu_box)}'
|
||||||
|
@ -1692,6 +1731,7 @@ class CpuBox(Box, SubBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_fg(cls):
|
def _draw_fg(cls):
|
||||||
|
if not "cpu" in cls.boxes: return
|
||||||
cpu = CpuCollector
|
cpu = CpuCollector
|
||||||
if cpu.redraw: cls.redraw = True
|
if cpu.redraw: cls.redraw = True
|
||||||
out: str = ""
|
out: str = ""
|
||||||
|
@ -1706,7 +1746,7 @@ class CpuBox(Box, SubBox):
|
||||||
if cls.resized or cls.redraw:
|
if cls.resized or cls.redraw:
|
||||||
if not "m" in Key.mouse:
|
if not "m" in Key.mouse:
|
||||||
Key.mouse["m"] = [[cls.x + 16 + i, cls.y] for i in range(12)]
|
Key.mouse["m"] = [[cls.x + 16 + i, cls.y] for i in range(12)]
|
||||||
out_misc += f'{Mv.to(cls.y, cls.x + 16)}{THEME.cpu_box(Symbol.title_left)}{Fx.b}{THEME.hi_fg("m")}{THEME.title}ode:{ARG_MODE or CONFIG.view_mode}{Fx.ub}{THEME.cpu_box(Symbol.title_right)}'
|
out_misc += f'{Mv.to(cls.y, cls.x + 16)}{THEME.cpu_box(Symbol.title_left)}{Fx.b}{THEME.hi_fg("m")}{THEME.title}ode:{Box.view_mode}{Fx.ub}{THEME.cpu_box(Symbol.title_right)}'
|
||||||
Graphs.cpu["up"] = Graph(w - bw - 3, hh, THEME.gradient["cpu"], cpu.cpu_usage[0])
|
Graphs.cpu["up"] = Graph(w - bw - 3, hh, THEME.gradient["cpu"], cpu.cpu_usage[0])
|
||||||
Graphs.cpu["down"] = Graph(w - bw - 3, h - hh, THEME.gradient["cpu"], cpu.cpu_usage[0], invert=True)
|
Graphs.cpu["down"] = Graph(w - bw - 3, h - hh, THEME.gradient["cpu"], cpu.cpu_usage[0], invert=True)
|
||||||
Meters.cpu = Meter(cpu.cpu_usage[0][-1], bw - (21 if cpu.got_sensors else 9), "cpu")
|
Meters.cpu = Meter(cpu.cpu_usage[0][-1], bw - (21 if cpu.got_sensors else 9), "cpu")
|
||||||
|
@ -1812,6 +1852,7 @@ class CpuBox(Box, SubBox):
|
||||||
|
|
||||||
class MemBox(Box):
|
class MemBox(Box):
|
||||||
name = "mem"
|
name = "mem"
|
||||||
|
num = 2
|
||||||
height_p = 38
|
height_p = 38
|
||||||
width_p = 45
|
width_p = 45
|
||||||
x = 1
|
x = 1
|
||||||
|
@ -1833,11 +1874,23 @@ class MemBox(Box):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _calc_size(cls):
|
def _calc_size(cls):
|
||||||
|
if not "mem" in cls.boxes:
|
||||||
|
Box._b_mem_h = 0
|
||||||
|
cls.width = Term.width
|
||||||
|
return
|
||||||
width_p: int; height_p: int
|
width_p: int; height_p: int
|
||||||
if cls.stat_mode:
|
if not "proc" in cls.boxes:
|
||||||
width_p, height_p = 100, cls.height_p
|
width_p = 100
|
||||||
else:
|
else:
|
||||||
width_p, height_p = cls.width_p, cls.height_p
|
width_p = cls.width_p
|
||||||
|
|
||||||
|
if not "cpu" in cls.boxes:
|
||||||
|
height_p = 60 if "net" in cls.boxes else 98
|
||||||
|
elif not "net" in cls.boxes:
|
||||||
|
height_p = 98 - CpuBox.height_p
|
||||||
|
else:
|
||||||
|
height_p = cls.height_p
|
||||||
|
|
||||||
cls.width = round(Term.width * width_p / 100)
|
cls.width = round(Term.width * width_p / 100)
|
||||||
cls.height = round(Term.height * height_p / 100) + 1
|
cls.height = round(Term.height * height_p / 100) + 1
|
||||||
Box._b_mem_h = cls.height
|
Box._b_mem_h = cls.height
|
||||||
|
@ -1874,19 +1927,23 @@ class MemBox(Box):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_bg(cls) -> str:
|
def _draw_bg(cls) -> str:
|
||||||
if cls.proc_mode: return ""
|
if not "mem" in cls.boxes: return ""
|
||||||
out: str = ""
|
out: str = ""
|
||||||
out += f'{create_box(box=cls, line_color=THEME.mem_box)}'
|
out += f'{create_box(box=cls, line_color=THEME.mem_box)}'
|
||||||
if CONFIG.show_disks:
|
if CONFIG.show_disks:
|
||||||
out += (f'{Mv.to(cls.y, cls.divider + 2)}{THEME.mem_box(Symbol.title_left)}{Fx.b}{THEME.title("disks")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}'
|
out += (f'{Mv.to(cls.y, cls.divider + 2)}{THEME.mem_box(Symbol.title_left)}{Fx.b}{THEME.hi_fg("d")}{THEME.title("isks")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}'
|
||||||
f'{Mv.to(cls.y, cls.divider)}{THEME.mem_box(Symbol.div_up)}'
|
f'{Mv.to(cls.y, cls.divider)}{THEME.mem_box(Symbol.div_up)}'
|
||||||
f'{Mv.to(cls.y + cls.height - 1, cls.divider)}{THEME.mem_box(Symbol.div_down)}{THEME.div_line}'
|
f'{Mv.to(cls.y + cls.height - 1, cls.divider)}{THEME.mem_box(Symbol.div_down)}{THEME.div_line}'
|
||||||
f'{"".join(f"{Mv.to(cls.y + i, cls.divider)}{Symbol.v_line}" for i in range(1, cls.height - 1))}')
|
f'{"".join(f"{Mv.to(cls.y + i, cls.divider)}{Symbol.v_line}" for i in range(1, cls.height - 1))}')
|
||||||
|
Key.mouse["d"] = [[cls.divider + 3 + i, cls.y] for i in range(5)]
|
||||||
|
else:
|
||||||
|
out += f'{Mv.to(cls.y, cls.x + cls.width - 9)}{THEME.mem_box(Symbol.title_left)}{THEME.hi_fg("d")}{THEME.title("isks")}{THEME.mem_box(Symbol.title_right)}'
|
||||||
|
Key.mouse["d"] = [[cls.x + cls.width - 8 + i, cls.y] for i in range(5)]
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_fg(cls):
|
def _draw_fg(cls):
|
||||||
if cls.proc_mode: return
|
if not "mem" in cls.boxes: return
|
||||||
mem = MemCollector
|
mem = MemCollector
|
||||||
if mem.redraw: cls.redraw = True
|
if mem.redraw: cls.redraw = True
|
||||||
out: str = ""
|
out: str = ""
|
||||||
|
@ -1923,8 +1980,8 @@ class MemBox(Box):
|
||||||
if len(mem.disks) * 3 <= h + 1:
|
if len(mem.disks) * 3 <= h + 1:
|
||||||
Meters.disks_free[name] = Meter(mem.disks[name]["free_percent"], cls.disk_meter, "free")
|
Meters.disks_free[name] = Meter(mem.disks[name]["free_percent"], cls.disk_meter, "free")
|
||||||
if not "g" in Key.mouse:
|
if not "g" in Key.mouse:
|
||||||
Key.mouse["g"] = [[x + cls.mem_width - 8 + i, y-1] for i in range(5)]
|
Key.mouse["g"] = [[x + 8 + i, y-1] for i in range(5)]
|
||||||
out_misc += (f'{Mv.to(y-1, x + cls.mem_width - 9)}{THEME.mem_box(Symbol.title_left)}{Fx.b if CONFIG.mem_graphs else ""}'
|
out_misc += (f'{Mv.to(y-1, x + 7)}{THEME.mem_box(Symbol.title_left)}{Fx.b if CONFIG.mem_graphs else ""}'
|
||||||
f'{THEME.hi_fg("g")}{THEME.title("raph")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}')
|
f'{THEME.hi_fg("g")}{THEME.title("raph")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}')
|
||||||
if CONFIG.show_disks:
|
if CONFIG.show_disks:
|
||||||
if not "s" in Key.mouse:
|
if not "s" in Key.mouse:
|
||||||
|
@ -2004,6 +2061,7 @@ class MemBox(Box):
|
||||||
|
|
||||||
class NetBox(Box, SubBox):
|
class NetBox(Box, SubBox):
|
||||||
name = "net"
|
name = "net"
|
||||||
|
num = 3
|
||||||
height_p = 30
|
height_p = 30
|
||||||
width_p = 45
|
width_p = 45
|
||||||
x = 1
|
x = 1
|
||||||
|
@ -2018,11 +2076,14 @@ class NetBox(Box, SubBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _calc_size(cls):
|
def _calc_size(cls):
|
||||||
width_p: int
|
if not "net" in cls.boxes:
|
||||||
if cls.stat_mode:
|
cls.width = Term.width
|
||||||
|
return
|
||||||
|
if not "proc" in cls.boxes:
|
||||||
width_p = 100
|
width_p = 100
|
||||||
else:
|
else:
|
||||||
width_p = cls.width_p
|
width_p = cls.width_p
|
||||||
|
|
||||||
cls.width = round(Term.width * width_p / 100)
|
cls.width = round(Term.width * width_p / 100)
|
||||||
cls.height = Term.height - Box._b_cpu_h - Box._b_mem_h
|
cls.height = Term.height - Box._b_cpu_h - Box._b_mem_h
|
||||||
cls.y = Term.height - cls.height + 1
|
cls.y = Term.height - cls.height + 1
|
||||||
|
@ -2036,13 +2097,13 @@ class NetBox(Box, SubBox):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_bg(cls) -> str:
|
def _draw_bg(cls) -> str:
|
||||||
if cls.proc_mode: return ""
|
if not "net" in cls.boxes: return ""
|
||||||
return f'{create_box(box=cls, line_color=THEME.net_box)}\
|
return f'{create_box(box=cls, line_color=THEME.net_box)}\
|
||||||
{create_box(x=cls.box_x, y=cls.box_y, width=cls.box_width, height=cls.box_height, line_color=THEME.div_line, fill=False, title="Download", title2="Upload")}'
|
{create_box(x=cls.box_x, y=cls.box_y, width=cls.box_width, height=cls.box_height, line_color=THEME.div_line, fill=False, title="Download", title2="Upload")}'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_fg(cls):
|
def _draw_fg(cls):
|
||||||
if cls.proc_mode: return
|
if not "net" in cls.boxes: return
|
||||||
net = NetCollector
|
net = NetCollector
|
||||||
if net.redraw: cls.redraw = True
|
if net.redraw: cls.redraw = True
|
||||||
if not net.nic: return
|
if not net.nic: return
|
||||||
|
@ -2103,6 +2164,7 @@ class NetBox(Box, SubBox):
|
||||||
|
|
||||||
class ProcBox(Box):
|
class ProcBox(Box):
|
||||||
name = "proc"
|
name = "proc"
|
||||||
|
num = 4
|
||||||
height_p = 68
|
height_p = 68
|
||||||
width_p = 55
|
width_p = 55
|
||||||
x = 1
|
x = 1
|
||||||
|
@ -2131,11 +2193,20 @@ class ProcBox(Box):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _calc_size(cls):
|
def _calc_size(cls):
|
||||||
|
if not "proc" in cls.boxes:
|
||||||
|
cls.width = Term.width
|
||||||
|
return
|
||||||
width_p: int; height_p: int
|
width_p: int; height_p: int
|
||||||
if cls.proc_mode:
|
if not "net" in cls.boxes and not "mem" in cls.boxes:
|
||||||
width_p, height_p = 100, 80
|
width_p = 100
|
||||||
else:
|
else:
|
||||||
width_p, height_p = cls.width_p, cls.height_p
|
width_p = cls.width_p
|
||||||
|
|
||||||
|
if not "cpu" in cls.boxes:
|
||||||
|
height_p = 100
|
||||||
|
else:
|
||||||
|
height_p = cls.height_p
|
||||||
|
|
||||||
cls.width = round(Term.width * width_p / 100)
|
cls.width = round(Term.width * width_p / 100)
|
||||||
cls.height = round(Term.height * height_p / 100)
|
cls.height = round(Term.height * height_p / 100)
|
||||||
if cls.height + Box._b_cpu_h > Term.height: cls.height = Term.height - Box._b_cpu_h
|
if cls.height + Box._b_cpu_h > Term.height: cls.height = Term.height - Box._b_cpu_h
|
||||||
|
@ -2149,7 +2220,7 @@ class ProcBox(Box):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_bg(cls) -> str:
|
def _draw_bg(cls) -> str:
|
||||||
if cls.stat_mode: return ""
|
if not "proc" in cls.boxes: return ""
|
||||||
return create_box(box=cls, line_color=THEME.proc_box)
|
return create_box(box=cls, line_color=THEME.proc_box)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -2218,7 +2289,7 @@ class ProcBox(Box):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _draw_fg(cls):
|
def _draw_fg(cls):
|
||||||
if cls.stat_mode: return
|
if not "proc" in cls.boxes: return
|
||||||
proc = ProcCollector
|
proc = ProcCollector
|
||||||
if proc.proc_interrupt: return
|
if proc.proc_interrupt: return
|
||||||
if proc.redraw: cls.redraw = True
|
if proc.redraw: cls.redraw = True
|
||||||
|
@ -2276,7 +2347,7 @@ class ProcBox(Box):
|
||||||
for k in ["e", "r", "c", "t", "k", "i", "enter", "left", " ", "f", "delete"]:
|
for k in ["e", "r", "c", "t", "k", "i", "enter", "left", " ", "f", "delete"]:
|
||||||
if k in Key.mouse: del Key.mouse[k]
|
if k in Key.mouse: del Key.mouse[k]
|
||||||
if proc.detailed:
|
if proc.detailed:
|
||||||
killed = proc.details["killed"]
|
killed = proc.details.get("killed", False)
|
||||||
main = THEME.main_fg if cls.selected == 0 and not killed else THEME.inactive_fg
|
main = THEME.main_fg if cls.selected == 0 and not killed else THEME.inactive_fg
|
||||||
hi = THEME.hi_fg if cls.selected == 0 and not killed else THEME.inactive_fg
|
hi = THEME.hi_fg if cls.selected == 0 and not killed else THEME.inactive_fg
|
||||||
title = THEME.title if cls.selected == 0 and not killed else THEME.inactive_fg
|
title = THEME.title if cls.selected == 0 and not killed else THEME.inactive_fg
|
||||||
|
@ -2285,7 +2356,7 @@ class ProcBox(Box):
|
||||||
cls.current_h = cls.height - 8
|
cls.current_h = cls.height - 8
|
||||||
for i in range(7): out_misc += f'{Mv.to(dy+i, x)}{" " * w}'
|
for i in range(7): out_misc += f'{Mv.to(dy+i, x)}{" " * w}'
|
||||||
out_misc += (f'{Mv.to(dy+7, x-1)}{THEME.proc_box}{Symbol.title_right}{Symbol.h_line*w}{Symbol.title_left}'
|
out_misc += (f'{Mv.to(dy+7, x-1)}{THEME.proc_box}{Symbol.title_right}{Symbol.h_line*w}{Symbol.title_left}'
|
||||||
f'{Mv.to(dy+7, x+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{THEME.title(cls.name)}{Fx.ub}{THEME.proc_box(Symbol.title_right)}{THEME.div_line}')
|
f'{Mv.to(dy+7, x+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{THEME.hi_fg(SUBSCRIPT[cls.num])}{THEME.title(cls.name)}{Fx.ub}{THEME.proc_box(Symbol.title_right)}{THEME.div_line}')
|
||||||
for i in range(7):
|
for i in range(7):
|
||||||
out_misc += f'{Mv.to(dy + i, dgx + dgw + 1)}{Symbol.v_line}'
|
out_misc += f'{Mv.to(dy + i, dgx + dgw + 1)}{Symbol.v_line}'
|
||||||
|
|
||||||
|
@ -2322,7 +2393,7 @@ class ProcBox(Box):
|
||||||
cls.current_h = cls.height
|
cls.current_h = cls.height
|
||||||
y, h = cls.y + 1, cls.height - 2
|
y, h = cls.y + 1, cls.height - 2
|
||||||
out_misc += (f'{Mv.to(y-1, x-1)}{THEME.proc_box}{Symbol.left_up}{Symbol.h_line*w}{Symbol.right_up}'
|
out_misc += (f'{Mv.to(y-1, x-1)}{THEME.proc_box}{Symbol.left_up}{Symbol.h_line*w}{Symbol.right_up}'
|
||||||
f'{Mv.to(y-1, x+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{THEME.title(cls.name)}{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
f'{Mv.to(y-1, x+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{THEME.hi_fg(SUBSCRIPT[cls.num])}{THEME.title(cls.name)}{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
f'{Mv.to(y+7, x-1)}{THEME.proc_box(Symbol.v_line)}{Mv.r(w)}{THEME.proc_box(Symbol.v_line)}')
|
f'{Mv.to(y+7, x-1)}{THEME.proc_box(Symbol.v_line)}{Mv.r(w)}{THEME.proc_box(Symbol.v_line)}')
|
||||||
cls.select_max = cls.height - 3
|
cls.select_max = cls.height - 3
|
||||||
|
|
||||||
|
@ -2352,12 +2423,12 @@ class ProcBox(Box):
|
||||||
out_misc += (f'{Mv.to(y-1, sort_pos - 25)}{THEME.proc_box(Symbol.title_left)}{Fx.b if CONFIG.proc_per_core else ""}'
|
out_misc += (f'{Mv.to(y-1, sort_pos - 25)}{THEME.proc_box(Symbol.title_left)}{Fx.b if CONFIG.proc_per_core else ""}'
|
||||||
f'{THEME.title("per-")}{THEME.hi_fg("c")}{THEME.title("ore")}{Fx.ub}{THEME.proc_box(Symbol.title_right)}')
|
f'{THEME.title("per-")}{THEME.hi_fg("c")}{THEME.title("ore")}{Fx.ub}{THEME.proc_box(Symbol.title_right)}')
|
||||||
|
|
||||||
if not "f" in Key.mouse or cls.resized: Key.mouse["f"] = [[x+5 + i, y-1] for i in range(6 if not proc.search_filter else 2 + len(proc.search_filter[-10:]))]
|
if not "f" in Key.mouse or cls.resized: Key.mouse["f"] = [[x+6 + i, y-1] for i in range(6 if not proc.search_filter else 2 + len(proc.search_filter[-10:]))]
|
||||||
if proc.search_filter:
|
if proc.search_filter:
|
||||||
if not "delete" in Key.mouse: Key.mouse["delete"] = [[x+11 + len(proc.search_filter[-10:]) + i, y-1] for i in range(3)]
|
if not "delete" in Key.mouse: Key.mouse["delete"] = [[x+12 + len(proc.search_filter[-10:]) + i, y-1] for i in range(3)]
|
||||||
elif "delete" in Key.mouse:
|
elif "delete" in Key.mouse:
|
||||||
del Key.mouse["delete"]
|
del Key.mouse["delete"]
|
||||||
out_misc += (f'{Mv.to(y-1, x + 7)}{THEME.proc_box(Symbol.title_left)}{Fx.b if cls.filtering or proc.search_filter else ""}{THEME.hi_fg("f")}{THEME.title}' +
|
out_misc += (f'{Mv.to(y-1, x + 8)}{THEME.proc_box(Symbol.title_left)}{Fx.b if cls.filtering or proc.search_filter else ""}{THEME.hi_fg("f")}{THEME.title}' +
|
||||||
("ilter" if not proc.search_filter and not cls.filtering else f' {proc.search_filter[-(10 if w < 83 else w - 74):]}{(Fx.bl + "█" + Fx.ubl) if cls.filtering else THEME.hi_fg(" del")}') +
|
("ilter" if not proc.search_filter and not cls.filtering else f' {proc.search_filter[-(10 if w < 83 else w - 74):]}{(Fx.bl + "█" + Fx.ubl) if cls.filtering else THEME.hi_fg(" del")}') +
|
||||||
f'{THEME.proc_box(Symbol.title_right)}')
|
f'{THEME.proc_box(Symbol.title_right)}')
|
||||||
|
|
||||||
|
@ -2656,8 +2727,6 @@ class Collector:
|
||||||
cls.proc_counter = 0
|
cls.proc_counter = 0
|
||||||
cls.proc_counter += 1
|
cls.proc_counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cls.collect_run.set()
|
cls.collect_run.set()
|
||||||
|
|
||||||
|
|
||||||
|
@ -3278,7 +3347,7 @@ class ProcCollector(Collector):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _collect(cls):
|
def _collect(cls):
|
||||||
'''List all processess with pid, name, arguments, threads, username, memory percent and cpu percent'''
|
'''List all processess with pid, name, arguments, threads, username, memory percent and cpu percent'''
|
||||||
if Box.stat_mode: return
|
if not "proc" in Box.boxes: return
|
||||||
out: Dict = {}
|
out: Dict = {}
|
||||||
cls.det_cpu = 0.0
|
cls.det_cpu = 0.0
|
||||||
sorting: str = CONFIG.proc_sorting
|
sorting: str = CONFIG.proc_sorting
|
||||||
|
@ -3694,7 +3763,12 @@ class Menu:
|
||||||
"Selected (Mouse 1)" : "Show detailed information for selected process.",
|
"Selected (Mouse 1)" : "Show detailed information for selected process.",
|
||||||
"(Mouse scroll)" : "Scrolls any scrollable list/text under cursor.",
|
"(Mouse scroll)" : "Scrolls any scrollable list/text under cursor.",
|
||||||
"(Esc, shift+m)" : "Toggles main menu.",
|
"(Esc, shift+m)" : "Toggles main menu.",
|
||||||
"(m)" : "Change current view mode, order full->proc->stat.",
|
"(m)" : "Cycle view presets, order: full->proc->stat->user.",
|
||||||
|
"(1)" : "Toggle CPU box.",
|
||||||
|
"(2)" : "Toggle MEM box.",
|
||||||
|
"(3)" : "Toggle NET box.",
|
||||||
|
"(4)" : "Toggle PROC box.",
|
||||||
|
"(d)" : "Toggle disks view in MEM box.",
|
||||||
"(F2, o)" : "Shows options.",
|
"(F2, o)" : "Shows options.",
|
||||||
"(F1, h)" : "Shows this window.",
|
"(F1, h)" : "Shows this window.",
|
||||||
"(ctrl+z)" : "Sleep program and put in background.",
|
"(ctrl+z)" : "Sleep program and put in background.",
|
||||||
|
@ -3819,7 +3893,6 @@ class Menu:
|
||||||
d_quote: str
|
d_quote: str
|
||||||
inputting: bool = False
|
inputting: bool = False
|
||||||
input_val: str = ""
|
input_val: str = ""
|
||||||
global ARG_MODE
|
|
||||||
Theme.refresh()
|
Theme.refresh()
|
||||||
if not cls.background:
|
if not cls.background:
|
||||||
cls.background = f'{THEME.inactive_fg}' + Fx.uncolor(f'{Draw.saved_buffer()}') + f'{Term.fg}'
|
cls.background = f'{THEME.inactive_fg}' + Fx.uncolor(f'{Draw.saved_buffer()}') + f'{Term.fg}'
|
||||||
|
@ -3841,12 +3914,13 @@ class Menu:
|
||||||
'',
|
'',
|
||||||
'Set to False if you want terminal background',
|
'Set to False if you want terminal background',
|
||||||
'transparency.'],
|
'transparency.'],
|
||||||
"view_mode" : [
|
"shown_boxes" : [
|
||||||
'Set bpytop view mode.',
|
'Manually set which boxes to show.',
|
||||||
'',
|
'',
|
||||||
'"full" for everything shown.',
|
'Available values are "cpu mem net proc".',
|
||||||
'"proc" for cpu stats and processes.',
|
'Seperate values with whitespace.',
|
||||||
'"stat" for cpu, mem, disks and net stats shown.'],
|
'',
|
||||||
|
'Toggle between presets with mode key "m".'],
|
||||||
"update_ms" : [
|
"update_ms" : [
|
||||||
'Update time in milliseconds.',
|
'Update time in milliseconds.',
|
||||||
'',
|
'',
|
||||||
|
@ -4050,7 +4124,6 @@ class Menu:
|
||||||
option_len: int = len(option_items) * 2
|
option_len: int = len(option_items) * 2
|
||||||
sorting_i: int = CONFIG.sorting_options.index(CONFIG.proc_sorting)
|
sorting_i: int = CONFIG.sorting_options.index(CONFIG.proc_sorting)
|
||||||
loglevel_i: int = CONFIG.log_levels.index(CONFIG.log_level)
|
loglevel_i: int = CONFIG.log_levels.index(CONFIG.log_level)
|
||||||
view_mode_i: int = CONFIG.view_modes.index(CONFIG.view_mode)
|
|
||||||
cpu_sensor_i: int = CONFIG.cpu_sensors.index(CONFIG.cpu_sensor)
|
cpu_sensor_i: int = CONFIG.cpu_sensors.index(CONFIG.cpu_sensor)
|
||||||
color_i: int
|
color_i: int
|
||||||
while not cls.close:
|
while not cls.close:
|
||||||
|
@ -4096,15 +4169,13 @@ class Menu:
|
||||||
counter = f' {sorting_i + 1}/{len(CONFIG.sorting_options)}'
|
counter = f' {sorting_i + 1}/{len(CONFIG.sorting_options)}'
|
||||||
elif opt == "log_level":
|
elif opt == "log_level":
|
||||||
counter = f' {loglevel_i + 1}/{len(CONFIG.log_levels)}'
|
counter = f' {loglevel_i + 1}/{len(CONFIG.log_levels)}'
|
||||||
elif opt == "view_mode":
|
|
||||||
counter = f' {view_mode_i + 1}/{len(CONFIG.view_modes)}'
|
|
||||||
elif opt == "cpu_sensor":
|
elif opt == "cpu_sensor":
|
||||||
counter = f' {cpu_sensor_i + 1}/{len(CONFIG.cpu_sensors)}'
|
counter = f' {cpu_sensor_i + 1}/{len(CONFIG.cpu_sensors)}'
|
||||||
else:
|
else:
|
||||||
counter = ""
|
counter = ""
|
||||||
out += f'{Mv.to(y+1+cy, x+1)}{t_color}{Fx.b}{opt.replace("_", " ").capitalize() + counter:^24.24}{Fx.ub}{Mv.to(y+2+cy, x+1)}{v_color}'
|
out += f'{Mv.to(y+1+cy, x+1)}{t_color}{Fx.b}{opt.replace("_", " ").capitalize() + counter:^24.24}{Fx.ub}{Mv.to(y+2+cy, x+1)}{v_color}'
|
||||||
if opt == selected:
|
if opt == selected:
|
||||||
if isinstance(value, bool) or opt in ["color_theme", "proc_sorting", "log_level", "view_mode", "cpu_sensor"]:
|
if isinstance(value, bool) or opt in ["color_theme", "proc_sorting", "log_level", "cpu_sensor"]:
|
||||||
out += f'{t_color} {Symbol.left}{v_color}{d_quote + str(value) + d_quote:^20.20}{t_color}{Symbol.right} '
|
out += f'{t_color} {Symbol.left}{v_color}{d_quote + str(value) + d_quote:^20.20}{t_color}{Symbol.right} '
|
||||||
elif inputting:
|
elif inputting:
|
||||||
out += f'{str(input_val)[-17:] + Fx.bl + "█" + Fx.ubl + "" + Symbol.enter:^33.33}'
|
out += f'{str(input_val)[-17:] + Fx.bl + "█" + Fx.ubl + "" + Symbol.enter:^33.33}'
|
||||||
|
@ -4183,6 +4254,15 @@ class Menu:
|
||||||
else:
|
else:
|
||||||
CONFIG.tree_depth = int(input_val)
|
CONFIG.tree_depth = int(input_val)
|
||||||
ProcCollector.collapsed = {}
|
ProcCollector.collapsed = {}
|
||||||
|
elif selected == "shown_boxes":
|
||||||
|
new_boxes: List = []
|
||||||
|
for box in input_val.split():
|
||||||
|
if box in ["cpu", "mem", "net", "proc"]:
|
||||||
|
new_boxes.append(box)
|
||||||
|
CONFIG.shown_boxes = " ".join(new_boxes)
|
||||||
|
Box.view_mode = "user"
|
||||||
|
Box.view_modes["user"] = CONFIG.shown_boxes.split()
|
||||||
|
Draw.clear(saved=True)
|
||||||
elif isinstance(getattr(CONFIG, selected), str):
|
elif isinstance(getattr(CONFIG, selected), str):
|
||||||
setattr(CONFIG, selected, input_val)
|
setattr(CONFIG, selected, input_val)
|
||||||
if selected.startswith("net_"):
|
if selected.startswith("net_"):
|
||||||
|
@ -4205,7 +4285,7 @@ class Menu:
|
||||||
elif key in ["escape", "o", "M", "f2"]:
|
elif key in ["escape", "o", "M", "f2"]:
|
||||||
cls.close = True
|
cls.close = True
|
||||||
break
|
break
|
||||||
elif key == "enter" and selected in ["update_ms", "disks_filter", "custom_cpu_name", "net_download", "net_upload", "draw_clock", "tree_depth", "proc_update_mult"]:
|
elif key == "enter" and selected in ["update_ms", "disks_filter", "custom_cpu_name", "net_download", "net_upload", "draw_clock", "tree_depth", "proc_update_mult", "shown_boxes"]:
|
||||||
inputting = True
|
inputting = True
|
||||||
input_val = str(getattr(CONFIG, selected))
|
input_val = str(getattr(CONFIG, selected))
|
||||||
elif key == "left" and selected == "update_ms" and CONFIG.update_ms - 100 >= 100:
|
elif key == "left" and selected == "update_ms" and CONFIG.update_ms - 100 >= 100:
|
||||||
|
@ -4282,21 +4362,6 @@ class Menu:
|
||||||
CpuCollector.get_sensors()
|
CpuCollector.get_sensors()
|
||||||
Term.refresh(force=True)
|
Term.refresh(force=True)
|
||||||
cls.resized = False
|
cls.resized = False
|
||||||
elif key in ["left", "right"] and selected == "view_mode":
|
|
||||||
if key == "left":
|
|
||||||
view_mode_i -= 1
|
|
||||||
if view_mode_i < 0: view_mode_i = len(CONFIG.view_modes) - 1
|
|
||||||
elif key == "right":
|
|
||||||
view_mode_i += 1
|
|
||||||
if view_mode_i > len(CONFIG.view_modes) - 1: view_mode_i = 0
|
|
||||||
CONFIG.view_mode = CONFIG.view_modes[view_mode_i]
|
|
||||||
Box.proc_mode = CONFIG.view_mode == "proc"
|
|
||||||
Box.stat_mode = CONFIG.view_mode == "stat"
|
|
||||||
if ARG_MODE:
|
|
||||||
ARG_MODE = ""
|
|
||||||
Draw.clear(saved=True)
|
|
||||||
Term.refresh(force=True)
|
|
||||||
cls.resized = False
|
|
||||||
elif key == "up":
|
elif key == "up":
|
||||||
selected_int -= 1
|
selected_int -= 1
|
||||||
if selected_int < 0: selected_int = len(option_items) - 1
|
if selected_int < 0: selected_int = len(option_items) - 1
|
||||||
|
@ -4527,6 +4592,7 @@ def get_cpu_core_mapping() -> List[int]:
|
||||||
def create_box(x: int = 0, y: int = 0, width: int = 0, height: int = 0, title: str = "", title2: str = "", line_color: Color = None, title_color: Color = None, fill: bool = True, box = None) -> str:
|
def create_box(x: int = 0, y: int = 0, width: int = 0, height: int = 0, title: str = "", title2: str = "", line_color: Color = None, title_color: Color = None, fill: bool = True, box = None) -> str:
|
||||||
'''Create a box from a box object or by given arguments'''
|
'''Create a box from a box object or by given arguments'''
|
||||||
out: str = f'{Term.fg}{Term.bg}'
|
out: str = f'{Term.fg}{Term.bg}'
|
||||||
|
num: int = 0
|
||||||
if not line_color: line_color = THEME.div_line
|
if not line_color: line_color = THEME.div_line
|
||||||
if not title_color: title_color = THEME.title
|
if not title_color: title_color = THEME.title
|
||||||
|
|
||||||
|
@ -4535,8 +4601,9 @@ def create_box(x: int = 0, y: int = 0, width: int = 0, height: int = 0, title: s
|
||||||
x = box.x
|
x = box.x
|
||||||
y = box.y
|
y = box.y
|
||||||
width = box.width
|
width = box.width
|
||||||
height =box.height
|
height = box.height
|
||||||
title = box.name
|
title = box.name
|
||||||
|
num = box.num
|
||||||
hlines: Tuple[int, int] = (y, y + height - 1)
|
hlines: Tuple[int, int] = (y, y + height - 1)
|
||||||
|
|
||||||
out += f'{line_color}'
|
out += f'{line_color}'
|
||||||
|
@ -4557,7 +4624,8 @@ def create_box(x: int = 0, y: int = 0, width: int = 0, height: int = 0, title: s
|
||||||
|
|
||||||
#* Draw titles if enabled
|
#* Draw titles if enabled
|
||||||
if title:
|
if title:
|
||||||
out += f'{Mv.to(y, x + 2)}{Symbol.title_left}{title_color}{Fx.b}{title}{Fx.ub}{line_color}{Symbol.title_right}'
|
numbered: str = "" if not num else f'{THEME.hi_fg(SUBSCRIPT[num])}'
|
||||||
|
out += f'{Mv.to(y, x + 2)}{Symbol.title_left}{Fx.b}{numbered}{title_color}{title}{Fx.ub}{line_color}{Symbol.title_right}'
|
||||||
if title2:
|
if title2:
|
||||||
out += f'{Mv.to(hlines[1], x + 2)}{Symbol.title_left}{title_color}{Fx.b}{title2}{Fx.ub}{line_color}{Symbol.title_right}'
|
out += f'{Mv.to(hlines[1], x + 2)}{Symbol.title_left}{title_color}{Fx.b}{title2}{Fx.ub}{line_color}{Symbol.title_right}'
|
||||||
|
|
||||||
|
@ -4701,9 +4769,10 @@ def readfile(file: str, default: str = "") -> str:
|
||||||
def process_keys():
|
def process_keys():
|
||||||
mouse_pos: Tuple[int, int] = (0, 0)
|
mouse_pos: Tuple[int, int] = (0, 0)
|
||||||
filtered: bool = False
|
filtered: bool = False
|
||||||
global ARG_MODE
|
box_keys = {"1" : "cpu", "2" : "mem", "3" : "net", "4" : "proc"}
|
||||||
while Key.has_key():
|
while Key.has_key():
|
||||||
key = Key.get()
|
key = Key.get()
|
||||||
|
found: bool = True
|
||||||
if key in ["mouse_scroll_up", "mouse_scroll_down", "mouse_click"]:
|
if key in ["mouse_scroll_up", "mouse_scroll_down", "mouse_click"]:
|
||||||
mouse_pos = Key.get_mouse()
|
mouse_pos = Key.get_mouse()
|
||||||
if mouse_pos[0] >= ProcBox.x and ProcBox.current_y + 1 <= mouse_pos[1] < ProcBox.current_y + ProcBox.current_h - 1:
|
if mouse_pos[0] >= ProcBox.x and ProcBox.current_y + 1 <= mouse_pos[1] < ProcBox.current_y + ProcBox.current_h - 1:
|
||||||
|
@ -4732,7 +4801,6 @@ def process_keys():
|
||||||
filtered = True
|
filtered = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
if key == "_null":
|
if key == "_null":
|
||||||
continue
|
continue
|
||||||
elif key == "q":
|
elif key == "q":
|
||||||
|
@ -4743,99 +4811,125 @@ def process_keys():
|
||||||
elif key == "-" and CONFIG.update_ms - 100 >= 100:
|
elif key == "-" and CONFIG.update_ms - 100 >= 100:
|
||||||
CONFIG.update_ms -= 100
|
CONFIG.update_ms -= 100
|
||||||
Box.draw_update_ms()
|
Box.draw_update_ms()
|
||||||
elif key in ["b", "n"]:
|
|
||||||
NetCollector.switch(key)
|
|
||||||
elif key in ["M", "escape"]:
|
elif key in ["M", "escape"]:
|
||||||
Menu.main()
|
Menu.main()
|
||||||
elif key in ["o", "f2"]:
|
elif key in ["o", "f2"]:
|
||||||
Menu.options()
|
Menu.options()
|
||||||
elif key in ["h", "f1"]:
|
elif key in ["h", "f1"]:
|
||||||
Menu.help()
|
Menu.help()
|
||||||
elif key == "z":
|
|
||||||
NetCollector.reset = not NetCollector.reset
|
|
||||||
Collector.collect(NetCollector, redraw=True)
|
|
||||||
elif key == "y":
|
|
||||||
CONFIG.net_sync = not CONFIG.net_sync
|
|
||||||
Collector.collect(NetCollector, redraw=True)
|
|
||||||
elif key == "a":
|
|
||||||
NetCollector.auto_min = not NetCollector.auto_min
|
|
||||||
NetCollector.net_min = {"download" : -1, "upload" : -1}
|
|
||||||
Collector.collect(NetCollector, redraw=True)
|
|
||||||
elif key in ["left", "right"]:
|
|
||||||
ProcCollector.sorting(key)
|
|
||||||
elif key == " " and CONFIG.proc_tree and ProcBox.selected > 0:
|
|
||||||
if ProcBox.selected_pid in ProcCollector.collapsed:
|
|
||||||
ProcCollector.collapsed[ProcBox.selected_pid] = not ProcCollector.collapsed[ProcBox.selected_pid]
|
|
||||||
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "e":
|
|
||||||
CONFIG.proc_tree = not CONFIG.proc_tree
|
|
||||||
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "r":
|
|
||||||
CONFIG.proc_reversed = not CONFIG.proc_reversed
|
|
||||||
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "c":
|
|
||||||
CONFIG.proc_per_core = not CONFIG.proc_per_core
|
|
||||||
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "g":
|
|
||||||
CONFIG.mem_graphs = not CONFIG.mem_graphs
|
|
||||||
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "s":
|
|
||||||
Collector.collect_idle.wait()
|
|
||||||
CONFIG.swap_disk = not CONFIG.swap_disk
|
|
||||||
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
|
||||||
elif key == "f":
|
|
||||||
ProcBox.filtering = True
|
|
||||||
if not ProcCollector.search_filter: ProcBox.start = 0
|
|
||||||
Collector.collect(ProcCollector, redraw=True, only_draw=True)
|
|
||||||
elif key == "m":
|
elif key == "m":
|
||||||
if ARG_MODE:
|
if list(Box.view_modes).index(Box.view_mode) + 1 > len(list(Box.view_modes)) - 1:
|
||||||
ARG_MODE = ""
|
Box.view_mode = list(Box.view_modes)[0]
|
||||||
elif CONFIG.view_modes.index(CONFIG.view_mode) + 1 > len(CONFIG.view_modes) - 1:
|
|
||||||
CONFIG.view_mode = CONFIG.view_modes[0]
|
|
||||||
else:
|
else:
|
||||||
CONFIG.view_mode = CONFIG.view_modes[(CONFIG.view_modes.index(CONFIG.view_mode) + 1)]
|
Box.view_mode = list(Box.view_modes)[(list(Box.view_modes).index(Box.view_mode) + 1)]
|
||||||
Box.proc_mode = CONFIG.view_mode == "proc"
|
CONFIG.shown_boxes = " ".join(Box.view_modes[Box.view_mode])
|
||||||
Box.stat_mode = CONFIG.view_mode == "stat"
|
|
||||||
Draw.clear(saved=True)
|
Draw.clear(saved=True)
|
||||||
Term.refresh(force=True)
|
Term.refresh(force=True)
|
||||||
elif key.lower() in ["t", "k", "i"] and (ProcBox.selected > 0 or ProcCollector.detailed):
|
elif key in box_keys:
|
||||||
pid: int = ProcBox.selected_pid if ProcBox.selected > 0 else ProcCollector.detailed_pid # type: ignore
|
boxes = CONFIG.shown_boxes.split()
|
||||||
if psutil.pid_exists(pid):
|
if box_keys[key] in boxes:
|
||||||
if key.lower() == "t": sig = signal.SIGTERM
|
boxes.remove(box_keys[key])
|
||||||
elif key.lower() == "k": sig = signal.SIGKILL
|
|
||||||
elif key.lower() == "i": sig = signal.SIGINT
|
|
||||||
try:
|
|
||||||
os.kill(pid, sig)
|
|
||||||
except Exception as e:
|
|
||||||
errlog.error(f'Exception when sending signal {sig} to pid {pid}')
|
|
||||||
errlog.exception(f'{e}')
|
|
||||||
elif key == "delete" and ProcCollector.search_filter:
|
|
||||||
ProcCollector.search_filter = ""
|
|
||||||
Collector.collect(ProcCollector, proc_interrupt=True, redraw=True)
|
|
||||||
elif key == "enter":
|
|
||||||
if ProcBox.selected > 0 and ProcCollector.detailed_pid != ProcBox.selected_pid and psutil.pid_exists(ProcBox.selected_pid):
|
|
||||||
ProcCollector.detailed = True
|
|
||||||
ProcBox.last_selection = ProcBox.selected
|
|
||||||
ProcBox.selected = 0
|
|
||||||
ProcCollector.detailed_pid = ProcBox.selected_pid
|
|
||||||
ProcBox.resized = True
|
|
||||||
elif ProcCollector.detailed:
|
|
||||||
ProcBox.selected = ProcBox.last_selection
|
|
||||||
ProcBox.last_selection = 0
|
|
||||||
ProcCollector.detailed = False
|
|
||||||
ProcCollector.detailed_pid = None
|
|
||||||
ProcBox.resized = True
|
|
||||||
else:
|
else:
|
||||||
continue
|
boxes.append(box_keys[key])
|
||||||
ProcCollector.details = {}
|
CONFIG.shown_boxes = " ".join(boxes)
|
||||||
ProcCollector.details_cpu = []
|
Box.view_mode = "user"
|
||||||
ProcCollector.details_mem = []
|
Box.view_modes["user"] = CONFIG.shown_boxes.split()
|
||||||
Graphs.detailed_cpu = NotImplemented
|
Draw.clear(saved=True)
|
||||||
Graphs.detailed_mem = NotImplemented
|
Term.refresh(force=True)
|
||||||
Collector.collect(ProcCollector, proc_interrupt=True, redraw=True)
|
else:
|
||||||
|
found = False
|
||||||
|
|
||||||
|
if found: continue
|
||||||
|
|
||||||
|
if "proc" in Box.boxes:
|
||||||
|
if key in ["left", "right"]:
|
||||||
|
ProcCollector.sorting(key)
|
||||||
|
elif key == " " and CONFIG.proc_tree and ProcBox.selected > 0:
|
||||||
|
if ProcBox.selected_pid in ProcCollector.collapsed:
|
||||||
|
ProcCollector.collapsed[ProcBox.selected_pid] = not ProcCollector.collapsed[ProcBox.selected_pid]
|
||||||
|
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "e":
|
||||||
|
CONFIG.proc_tree = not CONFIG.proc_tree
|
||||||
|
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "r":
|
||||||
|
CONFIG.proc_reversed = not CONFIG.proc_reversed
|
||||||
|
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "c":
|
||||||
|
CONFIG.proc_per_core = not CONFIG.proc_per_core
|
||||||
|
Collector.collect(ProcCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "f":
|
||||||
|
ProcBox.filtering = True
|
||||||
|
if not ProcCollector.search_filter: ProcBox.start = 0
|
||||||
|
Collector.collect(ProcCollector, redraw=True, only_draw=True)
|
||||||
|
elif key.lower() in ["t", "k", "i"] and (ProcBox.selected > 0 or ProcCollector.detailed):
|
||||||
|
pid: int = ProcBox.selected_pid if ProcBox.selected > 0 else ProcCollector.detailed_pid # type: ignore
|
||||||
|
if psutil.pid_exists(pid):
|
||||||
|
if key.lower() == "t": sig = signal.SIGTERM
|
||||||
|
elif key.lower() == "k": sig = signal.SIGKILL
|
||||||
|
elif key.lower() == "i": sig = signal.SIGINT
|
||||||
|
try:
|
||||||
|
os.kill(pid, sig)
|
||||||
|
except Exception as e:
|
||||||
|
errlog.error(f'Exception when sending signal {sig} to pid {pid}')
|
||||||
|
errlog.exception(f'{e}')
|
||||||
|
elif key == "delete" and ProcCollector.search_filter:
|
||||||
|
ProcCollector.search_filter = ""
|
||||||
|
Collector.collect(ProcCollector, proc_interrupt=True, redraw=True)
|
||||||
|
elif key == "enter":
|
||||||
|
if ProcBox.selected > 0 and ProcCollector.detailed_pid != ProcBox.selected_pid and psutil.pid_exists(ProcBox.selected_pid):
|
||||||
|
ProcCollector.detailed = True
|
||||||
|
ProcBox.last_selection = ProcBox.selected
|
||||||
|
ProcBox.selected = 0
|
||||||
|
ProcCollector.detailed_pid = ProcBox.selected_pid
|
||||||
|
ProcBox.resized = True
|
||||||
|
Collector.proc_counter = 1
|
||||||
|
elif ProcCollector.detailed:
|
||||||
|
ProcBox.selected = ProcBox.last_selection
|
||||||
|
ProcBox.last_selection = 0
|
||||||
|
ProcCollector.detailed = False
|
||||||
|
ProcCollector.detailed_pid = None
|
||||||
|
ProcBox.resized = True
|
||||||
|
Collector.proc_counter = 1
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
ProcCollector.details = {}
|
||||||
|
ProcCollector.details_cpu = []
|
||||||
|
ProcCollector.details_mem = []
|
||||||
|
Graphs.detailed_cpu = NotImplemented
|
||||||
|
Graphs.detailed_mem = NotImplemented
|
||||||
|
Collector.collect(ProcCollector, proc_interrupt=True, redraw=True)
|
||||||
|
elif key in ["up", "down", "mouse_scroll_up", "mouse_scroll_down", "page_up", "page_down", "home", "end", "mouse_click", "mouse_unselect"]:
|
||||||
|
ProcBox.selector(key, mouse_pos)
|
||||||
|
|
||||||
|
if "net" in Box.boxes:
|
||||||
|
if key in ["b", "n"]:
|
||||||
|
NetCollector.switch(key)
|
||||||
|
elif key == "z":
|
||||||
|
NetCollector.reset = not NetCollector.reset
|
||||||
|
Collector.collect(NetCollector, redraw=True)
|
||||||
|
elif key == "y":
|
||||||
|
CONFIG.net_sync = not CONFIG.net_sync
|
||||||
|
Collector.collect(NetCollector, redraw=True)
|
||||||
|
elif key == "a":
|
||||||
|
NetCollector.auto_min = not NetCollector.auto_min
|
||||||
|
NetCollector.net_min = {"download" : -1, "upload" : -1}
|
||||||
|
Collector.collect(NetCollector, redraw=True)
|
||||||
|
|
||||||
|
if "mem" in Box.boxes:
|
||||||
|
if key == "g":
|
||||||
|
CONFIG.mem_graphs = not CONFIG.mem_graphs
|
||||||
|
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "s":
|
||||||
|
Collector.collect_idle.wait()
|
||||||
|
CONFIG.swap_disk = not CONFIG.swap_disk
|
||||||
|
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "d":
|
||||||
|
Collector.collect_idle.wait()
|
||||||
|
CONFIG.show_disks = not CONFIG.show_disks
|
||||||
|
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
elif key in ["up", "down", "mouse_scroll_up", "mouse_scroll_down", "page_up", "page_down", "home", "end", "mouse_click", "mouse_unselect"]:
|
|
||||||
ProcBox.selector(key, mouse_pos)
|
|
||||||
|
|
||||||
|
|
||||||
#? Pre main -------------------------------------------------------------------------------------->
|
#? Pre main -------------------------------------------------------------------------------------->
|
||||||
|
|
Loading…
Reference in New Issue