From d6af79fcd1dcbfda8d30a17a183064dd0a9be9a2 Mon Sep 17 00:00:00 2001 From: aristocratos Date: Sat, 2 May 2020 00:14:20 +0200 Subject: [PATCH] added disks read/write stats --- bashtop | 523 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 281 insertions(+), 242 deletions(-) diff --git a/bashtop b/bashtop index 5853aa1..89d7867 100755 --- a/bashtop +++ b/bashtop @@ -138,7 +138,7 @@ menu_quit_selected=( "║═╬╗║ ║ ║ ║ " "╚═╝╚╚═╝ ╩ ╩ ") -declare -A cpu mem swap proc net box theme +declare -A cpu mem swap proc net box theme disks declare -a cpu_usage cpu_graph_a cpu_graph_b color_meter color_temp_graph color_cpu color_cpu_graph cpu_history color_mem_graph color_swap_graph declare -a mem_history swap_history net_history_download net_history_upload mem_graph swap_graph proc_array download_graph upload_graph trace_array declare resized=1 size_error clock tty_width tty_height hex="16#" cpu_p_box swap_on=1 draw_out esc_character boxes_out last_screen clock_out update_string @@ -148,9 +148,9 @@ declare -a save_array=(${options_array[*]/net_totals_reset/}) declare -a sorting=( "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive" ) declare -a pid_history detail_graph detail_history detail_mem_history declare time_left timestamp_start timestamp_end timestamp_input_start timestamp_input_end time_string mem_out proc_misc prev_screen pause_screen filter input_to_filter -declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out curled git_version +declare no_epoch proc_det proc_misc2 sleeping=0 detail_mem_graph proc_det2 proc_out curled git_version has_iostat declare esc_character tab backspace sleepy late_update skip_process_draw winches quitting theme_int -declare -a disks_free disks_total disks_name disks_free_percent saved_key themes +declare -a disks_free disks_total disks_name disks_free_percent disks_io saved_key themes printf -v esc_character "\u1b" printf -v tab "\u09" printf -v backspace "\u7F" @@ -216,6 +216,9 @@ init_() { #? Collect needed information and set options before startig main loop #* Check if "curl" command is available, if not, disable update check and theme downloads if command -v curl >/dev/null 2>&1; then curled=1; else unset curled; fi + #* Check if "iostat" command is available, if not, disable disk io stat collection + if command -v iostat >/dev/null 2>&1; then has_iostat=1; else unset has_iostat; fi + #* Get number of cores and cpu threads get_cpu_info @@ -224,7 +227,7 @@ init_() { #? Collect needed information and set options before startig main loop if [[ -e /usr/include/asm-generic/param.h ]]; then param_var="$(rgb_start[0]+rgb_start[1]+rgb_start[2])); then + if [[ -z ${rgb_mid[*]} ]] && ((rgb_end[0]+rgb_end[1]+rgb_end[2]>rgb_start[0]+rgb_start[1]+rgb_start[2])); then rgb_mid=( $((rgb_end[0]/2)) $((rgb_end[1]/2)) $((rgb_end[2]/2)) ) elif [[ -z ${rgb_mid[*]} ]]; then rgb_mid=( $((rgb_start[0]/2)) $((rgb_start[1]/2)) $((rgb_start[2]/2)) ) fi - - for((i=0;i<=100;i++,y=0)); do + + for((i=0;i<=100;i++,y=0)); do if [[ -n ${rgb_end[*]} ]]; then for this_color in "red" "green" "blue"; do if ((i==50)); then rgb_start[y]=${rgb[$this_color]}; fi - + if ((middle==1 & rgb[$this_color]255)); then rgb[$this_color]=255; fi - + y+=1 if ((i==49 & y==3 & middle==1)); then middle=0; fi done @@ -428,7 +431,7 @@ quit_() { #? Clean exit if [[ $config_file != "/dev/null" ]]; then save_config "${save_array[@]}" fi - + exit 0 } @@ -436,7 +439,7 @@ sleep_() { #? Restore terminal options, stop and send to background if caught SI tput rmcup stty echo tput cnorm - + kill -s SIGSTOP $$ } @@ -458,7 +461,7 @@ traperr() { #? Function for reporting error line numbers len=$((${#trace_array[@]})) if ((len-->=1)); then - while ((len>=${#trace_array[@]}-2)); do + while ((len>=${#trace_array[@]}-2)); do if [[ $err == "${trace_array[$((len--))]}" ]]; then ((++match)) ; fi done if ((match==2 & len != -2)); then return @@ -468,7 +471,7 @@ traperr() { #? Function for reporting error line numbers if ((len>100)); then unset 'trace_array[@]'; fi trace_array+=("$err") echo "$(printf "%(%X)T") ERROR: On line $err $trap_muted" >> "${config_dir}/error.log" - + } resized() { #? Get new terminal size if terminal is resized @@ -476,7 +479,7 @@ resized() { #? Get new terminal size if terminal is resized unset winches while ((++winches<5)); do read tty_height tty_width < <(stty size) - if (($tty_width<80 | $tty_height<24)); then + if (($tty_width<80 | $tty_height<24)); then size_error_msg winches=0 else @@ -496,18 +499,18 @@ size_error_msg() { #? Shows error message if terminal size is below 80x25 print -rs -m $((tty_height/2-1)) 2 -fg ${theme[title]} -c -l 11 "Current size: " -bg "#00" -fg dd2020 -d 1 -c "${tty_width}x${tty_height}" -rs print -d 1 -fg ${theme[title]} -c -l 15 "Need to be atleast:" -bg "#00" -fg 30dd50 -d 1 -c "80x24" -rs while [[ $(stty size) == "$tty_height $tty_width" ]]; do sleep 0.2; if [[ -n $quitting ]]; then quit_; fi ; done - + } draw_banner() { #? Draw banner, usage: draw_banner [output variable] local y letter b_color x_color xpos ypos=$1 banner_out if [[ -n $2 ]]; then local -n banner_out=$2; fi xpos=$(( (tty_width/2)-(banner_width/2) )) - + for banner_line in "${banner[@]}"; do print -v banner_out -rs -move $((ypos+++y)) $xpos -t "${banner_line}" done - + if [[ -z $2 ]]; then echo -en "${banner_out}"; fi } @@ -581,7 +584,7 @@ set_font() { #? Take a string and generate a string of unicode characters of giv string_out="${string_out} \e[1D${letter}" fi done - + echo -en "${string_out}" } @@ -589,14 +592,14 @@ sort_array_int() { #? Copy and sort an array of integers from largest to smalles #* Return if given array has no values if [[ -z ${!1} ]]; then return; fi local start_n search_n tmp_array - + #* Create pointers to arrays local -n in_arr="$1" local -n out_arr="$2" #* Create local copy of array local array=("${in_arr[@]}") - + #* Start sorting for ((start_n=0;start_n<=${#array[@]}-1;++start_n)); do for ((search_n=start_n+1;search_n<=${#array[@]}-1;++search_n)); do @@ -607,9 +610,9 @@ sort_array_int() { #? Copy and sort an array of integers from largest to smalles fi done done - + #* Write the sorted array to output array - out_arr=("${array[@]}") + out_arr=("${array[@]}") } subscript() { #? Convert an integer to a string of subscript numbers @@ -621,7 +624,7 @@ subscript() { #? Convert an integer to a string of subscript numbers } spaces() { #? Prints back spaces, usage: spaces "number of spaces" - printf "%${1}s" "" + printf "%${1}s" "" } is_int() { #? Check if value(s) is integer @@ -647,20 +650,21 @@ is_hex() { #? Check if value(s) is hexadecimal floating_humanizer() { #? Convert integer to floating point and scale up in steps of 1024 to highest positive unit #? Usage: floating_humanizer <-b,-bit|-B,-Byte> [-ps,-per-second] [-s,-start "1024 multiplier start"] [-v,-variable-output] - local value selector per_second unit_mult decimals out_var ext_var + local value selector per_second unit_mult decimals out_var ext_var short sep=" " local -a unit until (($#==0)); do case "$1" in -b|-bit) unit=(bit Kib Mib Gib Tib Pib); unit_mult=8;; -B|-Byte) unit=(Byte KiB MiB GiB TiB PiB); unit_mult=1;; -ps|-per-second) per_second=1;; + -short) short=1; sep="";; -s|-start) selector="$2"; shift;; -v|-variable-output) local -n out_var="$2"; ext_var=1; shift;; *) if is_int "$1"; then value=$1; break; fi;; esac shift done - + if [[ -z $value || $value -lt 0 || -z $unit_mult ]]; then return; fi if ((per_second==1 & unit_mult==1)); then per_second="/s" @@ -674,7 +678,7 @@ floating_humanizer() { #? Convert integer to floating point and scale up in ste ((++selector)) done - if ((${#value}<5 & ${#value}>=2 & selector>0)); then + if [[ -z $short ]] && ((${#value}<5 & ${#value}>=2 & selector>0)); then decimals=$((5-${#value})) value="${value::-2}.${value:(-${decimals})}" elif ((${#value}>=2)); then @@ -682,7 +686,7 @@ floating_humanizer() { #? Convert integer to floating point and scale up in ste fi fi - out_var="${value} ${unit[$selector]}${per_second}" + out_var="${value}${sep}${unit[$selector]::${short:-${#unit[$selector]}}}${per_second}" if [[ -z $ext_var ]]; then echo -n "${out_var}"; fi } @@ -736,7 +740,7 @@ get_value() { #? Get a value from a file, variable or array by searching for a n while IFS='' read -r input_line; do ((++current_line)) if [[ -n $line_nr && $current_line -eq $line_nr || -z $line_nr && -n $key && ${input_line/${key}/} != "$input_line" ]]; then - if [[ -n $all ]]; then + if [[ -n $all ]]; then found="${input_line}" break @@ -744,7 +748,7 @@ get_value() { #? Get a value from a file, variable or array by searching for a n found="${input_line/${key}/}" break - else + else line_array=(${input_line/${key}/${key// /}}) fi @@ -754,7 +758,7 @@ get_value() { #? Get a value from a file, variable or array by searching for a n if ((match_key<0 & line_pos+match_key>=0)) || ((match_key>=0 & line_pos+match_key<${#line_array[@]})); then found="${line_array[$((line_pos+match_key))]}" break 2 - else + else return 1 fi @@ -797,7 +801,7 @@ get_value() { #? Get a value from a file, variable or array by searching for a n fi done - + if [[ -z $ext_var ]]; then echo "${found}"; fi if [[ -n $ext_arr ]]; then array_out=(${found}); fi } @@ -814,7 +818,7 @@ get_themes() { } cur_pos() { #? Get cursor postion, argument "line" prints current line, argument "col" prints current column, no argument prints both in format "line column" - local line col + local line col IFS=';' read -sdR -p $'\E[6n' line col if [[ -z $1 || $1 == "line" ]]; then echo -n "${line#*[}${1:-" "}"; fi if [[ -z $1 || $1 == "col" ]]; then echo -n "$col"; fi @@ -824,7 +828,7 @@ create_box() { #? Draw a box with an optional title at given location local width height col line title ltype hpos vpos i hlines vlines color line_color c_rev=0 box_out ext_var fill until (($#==0)); do case $1 in - -f|-full) col=1; line=1; width=$((tty_width)); height=$((tty_height));; #? Use full terminal size for box + -f|-full) col=1; line=1; width=$((tty_width)); height=$((tty_height));; #? Use full terminal size for box -c|-col) if is_int "$2"; then col=$2; shift; fi;; #? Column position to start box -l|-line) if is_int "$2"; then line=$2; shift; fi;; #? Line position to start box -w|-width) if is_int "$2"; then width=$2; shift; fi;; #? Width of box @@ -880,13 +884,13 @@ create_box() { #? Draw a box with an optional title at given location print -v box_out -rs -m $((line+1)) $((col+1)) - if [[ -z $ext_var ]]; then echo -en "${box_out}"; fi - - + if [[ -z $ext_var ]]; then echo -en "${box_out}"; fi + + } create_meter() { #? Create a horizontal percentage meter, usage; create_meter - #? Optional arguments: [-p, -place ] [-w, -width ] [-f, -fill-empty] + #? Optional arguments: [-p, -place ] [-w, -width ] [-f, -fill-empty] #? [-c, -color "array-name"] [-i, -invert-color] [-v, -variable "variable-name"] if [[ -z $1 ]]; then return; fi local val width colors color block="■" i fill_empty col line var ext_var out meter_var print_var invert bg_color=${theme[inactive_fg]} @@ -926,7 +930,7 @@ create_meter() { #? Create a horizontal percentage meter, usage; create_meter < for((i=1;i<=width;i++)); do if [[ -n $invert ]]; then print -v meter_var -l 2; fi - if ((val>=i*100/width)); then + if ((val>=i*100/width)); then print -v meter_var -fg ${colors[$((i*100/width))]} -t "${block}" elif ((fill_empty==1)); then if [[ -n $invert ]]; then print -v meter_var -l $((width-i)); fi @@ -936,7 +940,7 @@ create_meter() { #? Create a horizontal percentage meter, usage; create_meter < else print -v meter_var -r $((1+width-i)); break; fi fi done - if [[ -z $ext_var ]]; then echo -en "${meter_var}"; fi + if [[ -z $ext_var ]]; then echo -en "${meter_var}"; fi } create_graph() { #? Create a graph from an array of percentage values, usage; create_graph @@ -953,7 +957,7 @@ create_graph() { #? Create a graph from an array of percentage values, usage; case $1 in -d|-dimensions) if is_int "${@:2:4}"; then line=$2; col=$3; height=$4; width=$5; shift 4; fi;; #? Graph dimensions -c|-color) local -n colors=$2; shift;; #? Name of an array containing colors from index 0-100 - -o|-output-array) local -n output_array=$2; ext_var=1; shift;; #? Output meter to an array + -o|-output-array) local -n output_array=$2; ext_var=1; shift;; #? Output meter to an array -add-value) if is_int "$3"; then local -n output_array=$2; add=$3; break; else return; fi;; #? Add a value to existing graph -add-last) local -n output_array=$2; local -n add_array=$3; add=${add_array[-1]}; break;; #? Add last value from array to existing graph -i|-invert) invert=1;; #? Invert graph, drawing from top to bottom @@ -964,7 +968,7 @@ create_graph() { #? Create a graph from an array of percentage values, usage; shift done - if [[ -z $no_guide ]]; then + if [[ -z $no_guide ]]; then ((--height)) else if [[ -n $invert ]]; then ((line--)); fi @@ -983,7 +987,7 @@ create_graph() { #? Create a graph from an array of percentage values, usage; if [[ -n $output_array ]]; then graph_array=("${output_array[@]}") if [[ -z ${graph_array[0]} ]]; then return; fi - else + else return fi height=$((${#graph_array[@]}-1)) @@ -1009,31 +1013,31 @@ create_graph() { #? Create a graph from an array of percentage values, usage; for((i=height;i>=0;i--)); do g_index+=($i) done - + else for((i=0;i<=height;i++)); do g_index+=($i) done fi - + if [[ -n $no_guide ]]; then unset normal_vals elif [[ -n $invert ]]; then g_char=(" ⡇" " ⡤" "⠤") fi #* Set up graph array print side numbers and lines - print -v graph_array[0] -rs + print -v graph_array[0] -rs print -v graph_array[0] -m $((line+g_index[0])) ${col} ${normal_vals:+-jr 3 -fg ee -b -t "${side_num[0]}" -rs -fg ${theme[main_fg]} -t "${g_char[0]}"} -fg ${colors[100]} for((i=1;i @@ -1157,10 +1161,10 @@ create_mini_graph() { #? Create a one line high graph from an array of percenta if [[ -n $output_var ]]; then graph_var="${output_var}" if [[ -z ${graph_var} ]]; then return; fi - else + else return fi - + declare -a input_array input_array[0]=${add} @@ -1185,29 +1189,29 @@ create_mini_graph() { #? Create a one line high graph from an array of percenta fi fi - + #* If no color array was given, create a simple greyscale array if [[ -z $colors && -z $no_color ]]; then for ((i=0,ic=50;i<=100;i++,ic=ic+2)); do colors[i]="${ic} ${ic} ${ic}" done fi - + #* Create the graph local value_width x=0 y a cur_value virt_height=$((height*10)) offset=0 org_value if [[ -n $add ]]; then value_width=1 - elif ((${#input_array[@]}<=width)); then - value_width=${#input_array[@]}; + elif ((${#input_array[@]}<=width)); then + value_width=${#input_array[@]}; else value_width=${width} offset=$((${#input_array[@]}-width)) fi #* Print spaces to right-justify graph if number of values is less than graph width - if [[ -z $add && -z $no_color ]] && ((value_width ] [-l, -left ] [-r, -right ] [-u, -up ] [-d, -down ] [-c, -center] [-sc, -save] [-rc, -restore] #? [-jl, -justify-left ] [-jr, -justify-right ] [-jc, -justify-center ] [-rp, -repeat ] #? Text: [-v, -variable "variable-name"] [-stdin] [-t, -text "string"] ["string"] - + #* Return if no arguments is given if [[ -z $1 ]]; then return; fi #* Just echo and return if only one argument and not a valid option if [[ $# -eq 1 && ${1::1} != "-" ]]; then echo -en "$1"; return; fi - + local effect color add_command text text2 esc center clear fgc bgc fg_bg_div tmp tmp_len bold italic custom_font val var out ext_var hex="16#" local justify_left justify_right justify_center repeat r_tmp trans - - + + #* Loop function until we are out of arguments until (($#==0)); do @@ -1269,7 +1273,7 @@ print() { #? Print text, set true-color foreground/background color, add effects elif [[ ${#val} == 6 ]] && is_hex "$val"; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:2:2}));$((${hex}${val:4:2}))m"; shift elif [[ ${#val} == 2 ]] && is_hex "$val"; then fgc="\e[38;2;$((${hex}${val:0:2}));$((${hex}${val:0:2}));$((${hex}${val:0:2}))m"; shift fi - ;; + ;; -bg|-background) #? Set text background color, accepts either 6 digit hexadecimal "#RRGGBB", 2 digit hex (greyscale) or decimal RGB "<0-255> <0-255> <0-255>" val=${2//#/} if is_int "${@:2:3}"; then bgc="\e[48;2;$2;$3;$4m"; shift 3 @@ -1289,7 +1293,7 @@ print() { #? Print text, set true-color foreground/background color, add effects +ul|+underline) effect="${effect}${effect:+;}24";; #? Disable underlined text -bl|-blink) effect="${effect}${effect:+;}5";; #? Enable blinking text +bl|+blink) effect="${effect}${effect:+;}25";; #? Disable blinking text - -f|-font) if [[ $2 =~ ^(sans-serif|script|fraktur|monospace|double-struck)$ ]]; then custom_font="$2"; shift; fi;; #? Set custom font + -f|-font) if [[ $2 =~ ^(sans-serif|script|fraktur|monospace|double-struck)$ ]]; then custom_font="$2"; shift; fi;; #? Set custom font -m|-move) if is_int "${@:2:2}"; then add_command="${add_command}\e[${2};${3}f"; shift 2; fi;; #? Move to postion "LINE" "COLUMN" -l|-left) if is_int "$2"; then add_command="${add_command}\e[${2}D"; shift; fi;; #? Move left x columns -r|-right) if is_int "$2"; then add_command="${add_command}\e[${2}C"; shift; fi;; #? Move right x columns @@ -1302,7 +1306,7 @@ print() { #? Print text, set true-color foreground/background color, add effects -sc|-save) add_command="\e[s${add_command}";; #? Save cursor position -rc|-restore) add_command="${add_command}\e[u";; #? Restore cursor position -trans) trans=1;; #? Make whitespace transparent - -v|-variable) local -n var=$2; ext_var=1; shift;; #? Send output to a variable, appending if not unset + -v|-variable) local -n var=$2; ext_var=1; shift;; #? Send output to a variable, appending if not unset *) text="$1"; shift; break;; #? Assumes text string if no argument is found esac shift @@ -1360,7 +1364,7 @@ collect_cpu() { #? Collects cpu stats from /proc/stat and compares with previous while ((thread0)); then get_value -v 'swap[free]' -sv "mem_info" -k "SwapFree:" -i swap[free_percent]=$((swap[free]*100/swap[total])) - + swap[used]=$((swap[total]-swap[free])) swap[used_percent]=$((swap[used]*100/swap[total])) - + available+=("swap") else unset swap_on @@ -1535,15 +1539,16 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" done #* Get disk information from "df" command - local df_array df_line line_array - unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' + local df_array df_line line_array dev_path dev_name iostat_var disk_read disk_write disk_io_string + local -a device_array iostat_array + unset 'disks_free[@]' 'disks_used[@]' 'disks_used_percent[@]' 'disks_total[@]' 'disks_name[@]' 'disks_free_percent[@]' 'disks_io[@]' readarray -t df_array < <(df -x squashfs -x tmpfs -x devtmpfs -x overlay) for df_line in "${df_array[@]:1}"; do line_array=(${df_line}) if [[ ${line_array[5]} == "/" ]]; then disks_name+=("root") else disks_name+=("${line_array[5]##*/}"); fi - + #* Filter disks showed if $disks_filter is set if [[ -n $disks_filter ]]; then unset found @@ -1558,6 +1563,32 @@ collect_mem() { #? Collect memory information from "/proc/meminfo" disks_used_percent+=("${line_array[4]%'%'}") disks_free+=("$(floating_humanizer -s 1 -B ${line_array[3]})") disks_free_percent+=("$((100-${line_array[4]%'%'}))") + + #* Get read/write stats for disk if "iostat" is available + if [[ -n $has_iostat ]]; then + dev_name="${line_array[0]##*/}" + dev_path="${line_array[0]%${dev_name}}" + if [[ ${dev_name::2} == "md" ]]; then dev_name="${dev_name::3}"; fi + unset iostat_var disk_io_string 'iostat_array[@]' + read -r iostat_var < <(iostat -dkz --dec=0 "${dev_path}${dev_name}" | tail -n +4) + iostat_array=(${iostat_var}) + if [[ -n ${iostat_array[-2]} ]]; then + + disk_read=$((iostat_array[-2]-${disks[${dev_name}_read]:-${iostat_array[-2]}})) + disk_write=$((iostat_array[-1]-${disks[${dev_name}_write]:-${iostat_array[-1]}})) + + if ((box[m_width2]>25)); then + if ((disk_read>0)); then disk_io_string="▲$(floating_humanizer -s 1 -short -B ${disk_read}) "; fi + if ((disk_write>0)); then disk_io_string+="▼$(floating_humanizer -s 1 -short -B ${disk_write})"; fi + elif ((disk_read+disk_write>0)); then + disk_io_string+="▼▲$(floating_humanizer -s 1 -short -B $((disk_read+disk_write)))" + fi + + disks[${dev_name}_read]="${iostat_array[-2]}" + disks[${dev_name}_write]="${iostat_array[-1]}" + fi + disks_io+=("${disk_io_string:-0}") + fi else unset 'disks_name[-1]' disks_name=("${disks_name[@]}") @@ -1607,7 +1638,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu fi readarray ${options} proc_array < <(ps ax -o pid:${proc[pid_len]}=Pid:,comm:${format_cmd}=Program:${format_args},nlwp:3=Tr:,euser:6=User:,pmem=Mem%,pcpu:10=Cpu% --sort ${proc[reverse]:--}${sort}) - + proc_array[0]="${proc_array[0]/ Tr:/ Threads:}" proc_array[0]="${proc_array[0]/ ${selected}/${symbol}${selected}}" @@ -1627,7 +1658,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu #* Timestamp the values in milliseconds to accurately calculate cpu usage get_ms proc[new_timestamp] - + for readline in "${proc_array[@]:1}"; do ((++count)) @@ -1658,20 +1689,20 @@ collect_processes() { #? Collect process information and calculate accurate cpu utime=${statfile[13]} stime=${statfile[14]} - + proc[new_${pid}_ticks]=$((utime+stime)) - + if [[ -n ${proc[old_${pid}_ticks]} ]]; then time_elapsed=$((proc[new_timestamp]-proc[old_timestamp])) - + #* Calculate current cpu usage for process, * 1000 (for conversion from ms to seconds) * 1000 (for conversion to floating point) cpu_percent[count]=$(( ( ( ${proc[new_${pid}_ticks]}-${proc[old_${pid}_ticks]} ) * 1000 * 1000 ) / ( cpu[hz]*time_elapsed*cpu[threads] ) )) if ((cpu_percent[count]<0)); then cpu_percent[count]=0 elif ((cpu_percent[count]>1000)); then cpu_percent[count]=1000; fi - + if ((${#cpu_percent[count]}<=3)); then printf -v cpu_percent_string "%01d%s" "${cpu_percent[count]::-1}" ".${cpu_percent[count]:(-1)}" else @@ -1694,9 +1725,9 @@ collect_processes() { #? Collect process information and calculate accurate cpu local get_mem local -a det_array read -r proc[detailed_name] box[details_width]*2)); then detail_history=( "${detail_history[@]:${box[details_width]}}" "$((cpu_int+4))") @@ -1756,7 +1787,7 @@ collect_processes() { #? Collect process information and calculate accurate cpu else create_mini_graph -nc -add-value "pid_${pid}_graph" "$((cpu_int+4))" fi - + pid_count=$((${pid_count}-1)) elif [[ ${pid_count} == "0" ]]; then unset "pid_${pid}_graph" @@ -1770,10 +1801,10 @@ collect_processes() { #? Collect process information and calculate accurate cpu fi proc[old_${pid}_ticks]=${proc[new_${pid}_ticks]} - + fi - if ((breaking==1)); then + if ((breaking==1)); then if [[ ${proc[detailed]} == "1" && -z ${proc[detailed_cpu]} ]] && ps ${proc[detailed_pid]} >/dev/null 2>&1; then readarray ${options} -O ${#proc_array[@]} proc_array < <(ps -o pid:${proc[pid_len]}=Pid:,comm:${format_cmd}=Program:${format_args},nlwp:3=Tr:,euser:6=User:,pmem=Mem%,pcpu:10=Cpu% --no-headers -p ${proc[detailed_pid]} || true) else @@ -1820,7 +1851,7 @@ collect_net() { #? Collect information from "/proc/net/dev" local operations operation direction index unit_selector speed speed_B total local -a net_dev history_sorted history_last - if [[ $1 == "init" ]]; then + if [[ $1 == "init" ]]; then for direction in "download" "upload"; do net[${direction}_max]=0 net[${direction}_new_low]=0 @@ -1847,7 +1878,7 @@ collect_net() { #? Collect information from "/proc/net/dev" elif ((net[reset]==0)) && [[ -n ${net[total_offset_${direction}]} ]]; then unset "net[total_offset_${direction}]"; fi floating_humanizer -Byte -v net[total_${direction}] $((${net[new_${direction}]}-${net[total_offset_${direction}]:-0})) - + #* Calculate current speeds: ("New value" - "Old value") * 1000(for ms to seconds) / ("new_timestamp" - "old_timestamp") net[speed_${direction}]=$(( (${net[new_${direction}]}-${net[old_${direction}]})*1000/(net[new_timestamp]-net[old_timestamp]) )) @@ -1894,7 +1925,7 @@ collect_net() { #? Collect information from "/proc/net/dev" if ((${net[${direction}_graph_max]}<10<<10)); then net[${direction}_graph_max]=$((10<<10)); fi net[${direction}_redraw]=1 net[${direction}_new_low]=0 - fi + fi fi net[old_${direction}]=${net[new_${direction}]} @@ -1906,11 +1937,11 @@ collect_net() { #? Collect information from "/proc/net/dev" calc_sizes() { #? Calculate width and height of all boxes local pos calc_size calc_total percent threads=${cpu[threads]} - + #* Calculate heights for pos in ${box[boxes]/processes/}; do - if [[ $pos = "cpu" ]]; then percent=32; - elif [[ $pos = "mem" ]]; then percent=40; + if [[ $pos = "cpu" ]]; then percent=32; + elif [[ $pos = "mem" ]]; then percent=40; else percent=28; fi #* Multiplying with 10 to convert to floating point @@ -1920,7 +1951,7 @@ calc_sizes() { #? Calculate width and height of all boxes if ((${calc_size:(-2):1}==0)); then calc_size=$((calc_size+10)); fi if ((${calc_size:(-2)}<50)); then calc_size=$((${calc_size::-2})) - else + else calc_size=$((${calc_size::-2}+1)) fi @@ -1940,14 +1971,14 @@ calc_sizes() { #? Calculate width and height of all boxes unset calc_total for pos in net processes; do if [[ $pos = "net" ]]; then percent=45; else percent=55; fi - + #* Multiplying with 10 to convert to floating point calc_size=$(( (tty_width*10)*(percent*10)/100 )) #* Round down if last 2 digits of value is below "50" and round up if above if ((${calc_size:(-2)}<50)); then calc_size=$((${calc_size::-2})) - else + else calc_size=$((${calc_size::-2}+1)) fi @@ -1976,7 +2007,7 @@ calc_sizes() { #? Calculate width and height of all boxes box[processes_line]=$((box[processes_line]+box[details_height])) box[processes_height]=$((box[processes_height]-box[details_height])) fi - + #* Calculate number of columns and placement of cpu meter box local cpu_line=$((box[cpu_line]+1)) cpu_width=$((box[cpu_width]-2)) cpu_height=$((box[cpu_height]-2)) box_cols if ((threads>(cpu_height-3)*3 && tty_width>=200)); then box[p_width]=$((24*4)); box[p_height]=$((threads/4+4)); box_cols=4 @@ -1988,8 +2019,8 @@ calc_sizes() { #? Calculate width and height of all boxes if [[ $check_temp == true ]]; then box[p_width]=$(( box[p_width]+13*box_cols)) fi - - if ((box[p_height]>cpu_height)); then box[p_height]=$cpu_height; fi + + if ((box[p_height]>cpu_height)); then box[p_height]=$cpu_height; fi box[p_col]="$((cpu_width-box[p_width]+2))" box[p_line]="$((cpu_line+(cpu_height/2)-(box[p_height]/2)+1))" @@ -2009,7 +2040,7 @@ calc_sizes() { #? Calculate width and height of all boxes else box[n_height]=$net_height; fi box[n_col]="$((net_width-box[n_width]+2))" box[n_line]="$((net_line+(net_height/2)-(box[n_height]/2)+1))" - + } @@ -2053,16 +2084,16 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages #* Get variables from previous calculations local col=$((box[cpu_col]+1)) line=$((box[cpu_line]+1)) width=$((box[cpu_width]-2)) height=$((box[cpu_height]-2)) local p_width=${box[p_width]} p_height=${box[p_height]} p_col=${box[p_col]} p_line=${box[p_line]} - + #* If resized recreate cpu meter/graph box, cpu graph and core graphs if ((resized>0)); then local graph_a_size graph_b_size graph_a_size=$((height/2)); graph_b_size=${graph_a_size} - + if ((graph_a_size*224+temp_width)); then + if ((i==0 & p_width>24+temp_width)); then name="CPU Total "; meter_width=$((p_width-17-temp_width)) fi - + #* Create cpu usage meter if ((i==0)); then @@ -2123,7 +2154,7 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages core_name="cpu_core_graph_$i" meter="${!core_name}" fi - + if ((p_width>84+temp_width & i>=(p_height-2)*3-2)); then pt_line=$((p_line+i-y*4)); pt_col=$((p_col+72+temp_width*3)) elif ((p_width>54+temp_width & i>=(p_height-2)*2-1)); then pt_line=$((p_line+i-y*3)); pt_col=$((p_col+48+temp_width*2)) elif ((p_width>24+temp_width & i>=p_height-2)); then pt_line=$((p_line+i-y*2)); pt_col=$((p_col+24+temp_width)) @@ -2135,7 +2166,7 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages print -v cpu_out_var -fg ${theme[inactive_fg]} " ⡀⡀⡀⡀⡀" -l 7 -t " ${!temp_name}" -fg $temp_color -jr 4 -t ${cpu[temp_${i}]} -fg $p_normal_color -t ${cpu[temp_unit]} fi - if (( i>(p_height-2)*( p_width/(24+temp_width) )-( p_width/(24+temp_width) )-1 )); then break; fi + if (( i>(p_height-2)*( p_width/(24+temp_width) )-( p_width/(24+temp_width) )-1 )); then break; fi done #* Print load average and uptime @@ -2151,7 +2182,7 @@ draw_cpu() { #? Draw cpu and core graphs and print percentages #* Print current CPU frequency right of the title in the meter box if [[ -n ${cpu[freq_string]} ]]; then print -v cpu_out_var -m $((p_line-1)) $((p_col+p_width-5-${#cpu[freq_string]})) -fg ${theme[div_line]} -t "┤" -fg ${theme[title]} -b -t "${cpu[freq_string]}" -rs -fg ${theme[div_line]} -t "├"; fi - + #* Print created text, graph and meters to output variable draw_out+="${cpu_graph_a[*]}${cpu_graph_b[*]}${cpu_out_var}" @@ -2176,9 +2207,9 @@ draw_mem() { #? Draw mem, swap and disk statistics local y_pos=$m_line v_height=8 list value meter inv_meter for type in ${types[@]}; do local -n type_name="$type" - if [[ $type == "mem" ]]; then + if [[ $type == "mem" ]]; then m_title="memory" - else + else m_title="$type" if ((height>14)); then ((y_pos++)); fi fi @@ -2192,10 +2223,10 @@ draw_mem() { #? Draw mem, swap and disk statistics value_text="${value::$((m_width-12))}" if ((height<14)); then value_text="${value_text::5}"; fi - + #* Print name of value and value amount in humanized base 2 bytes print -v mem_out -m $y_pos $m_col -rs -fg $normal_color -jl 9 -t "${value_text^}:" -m $((y_pos++)) $((mem_line-10)) -jr 9 -trans -t " ${type_name[${value}_string]::$((m_width-11))}" - + #* Create meter for value and calculate size and placement depending on terminal size if ((height>v_height++ | tty_width>100)); then if ((height<=v_height & tty_width<150)); then @@ -2208,7 +2239,7 @@ draw_mem() { #? Draw mem, swap and disk statistics meter_mod_pos=10 fi create_meter -v ${type}_${value}_meter -w $((m_width-7-meter_mod_w)) -f -c color_${value}_graph ${type_name[${value}_percent]} - + meter="${type}_${value}_meter" print -v mem_out -m $((y_pos++)) $((m_col+meter_mod_pos)) -t "${!meter}" -rs -fg $normal_color @@ -2219,7 +2250,7 @@ draw_mem() { #? Draw mem, swap and disk statistics #* Create text and meters for disks and adapt sizes based on available height - local disk_num disk_name disk_value v_height2 + local disk_num disk_name disk_value v_height2 just_val name_len y_pos=$m_line m_col=$((m_col+m_width)) m_width=${box[m_width2]} @@ -2229,8 +2260,16 @@ draw_mem() { #? Draw mem, swap and disk statistics for disk_name in "${disks_name[@]}"; do if ((y_pos>m_line+height-2)); then break; fi - #* Print folder disk is mounted on and total size in humanized base 2 bytes - print -v mem_out -m $((y_pos++)) $m_col -rs -fg ${theme[title]} -b -jl 9 -t "${disks_name[disk_num]::10}" -jr $((m_width-11)) -t "${disks_total[disk_num]::$((m_width-11))}" + #* Print folder disk is mounted on, total size in humanized base 2 bytes and io stats if enabled + print -v mem_out -m $((y_pos++)) $m_col -rs -fg ${theme[title]} -b -t "${disks_name[disk_num]::10}" + name_len=${#disks_name[disk_num]}; if ((name_len>10)); then name_len=10; fi + if [[ -n $has_iostat && ${disks_io[disk_num]} != "0" ]] && ((m_width-11-name_len>6)); then + print -v mem_out -jc $((m_width-name_len-10)) -rs -fg ${theme[main_fg]} -t "${disks_io[disk_num]::$((m_width-10-name_len))}" + just_val=8 + else + just_val=$((m_width-name_len-2)) + fi + print -v mem_out -jr ${just_val} -fg ${theme[title]} -b -t "${disks_total[disk_num]::$((m_width-11))}" for value in "used" "free"; do if ((height0)); then - unset proc_det2 + unset proc_det2 create_graph -o detail_graph -d $((d_line+1)) $((d_col+1)) ${detail_graph_height} ${detail_graph_width} -c color_cpu_graph -n detail_history if ((tty_width>120)); then create_mini_graph -o detail_mem_graph -w $((right_width/3-3)) -nc detail_mem_history; fi det_no_add=1 - + for detail_location in "${d_line}" "$((d_line+d_height))"; do print -v proc_det2 -m ${detail_location} $((d_col+1)) -rs -fg ${box[processes_color]} -rp $((d_width-2)) -t "─" done @@ -2327,33 +2366,33 @@ draw_processes() { #? Draw processes and values to screen if ((tty_width>128)); then print -v proc_det2 -m -r 1 -t "┤" -fg ${theme[title]} -b -t "${proc[detailed_pid]}" -rs -fg ${box[processes_color]} -t "├"; fi - + if ((${#proc[detailed_cmd]}>(right_width-6)*2)); then ((det_y--)); dets=2 elif ((${#proc[detailed_cmd]}>right_width-6)); then dets=1; fi - + print -v proc_det2 -fg ${theme[title]} -b for i in C M D; do print -v proc_det2 -m $((d_line+5+cmd_y++)) $right_col -t "$i" done - - + + print -v proc_det2 -m $((d_line+det_y++)) $((right_col+1)) -jc $((right_width-4)) -rs -fg ${theme[main_fg]} -t "${proc[detailed_cmd]::$((right_width-6))}" if ((dets>0)); then print -v proc_det2 -m $((d_line+det_y++)) $((right_col+2)) -jl $((right_width-6)) -t "${proc[detailed_cmd]:$((right_width-6)):$((right_width-6))}"; fi if ((dets>1)); then print -v proc_det2 -m $((d_line+det_y)) $((right_col+2)) -jl $((right_width-6)) -t "${proc[detailed_cmd]:$(( (right_width-6)*2 )):$((right_width-6))}"; fi - + fi - - + + if ((proc[selected]>0)); then enter_fg="${theme[inactive_fg]}"; enter_a_fg="${theme[inactive_fg]}"; else enter_fg="${theme[title]}"; enter_a_fg="${theme[hi_fg]}"; fi if [[ -n ${proc[detailed_killed]} ]]; then misc_fg="${theme[title]}"; misc_a_fg="${theme[hi_fg]}" else misc_fg=$enter_fg; misc_a_fg=$enter_a_fg; fi print -v proc_det -m ${d_line} $((d_col+d_width-11)) -fg ${box[processes_color]} -t "┤" -fg $enter_fg -b -t "close " -fg $enter_a_fg -t "↲" -rs -fg ${box[processes_color]} -t "├" if ((tty_width<129)); then det_mod="-8"; fi - + print -v proc_det -m ${d_line} $((d_col+detail_graph_width+4+det_mod)) -t "┤" -fg $misc_a_fg -b -t "t" -fg $misc_fg -t "erminate" -rs -fg ${box[processes_color]} -t "├" print -v proc_det -r 1 -t "┤" -fg $misc_a_fg -b -t "k" -fg $misc_fg -t "ill" -rs -fg ${box[processes_color]} -t "├" if ((tty_width>104)); then print -v proc_det -r 1 -t "┤" -fg $misc_a_fg -b -t "i" -fg $misc_fg -t "nterrupt" -rs -fg ${box[processes_color]} -t "├"; fi - + proc_det="${proc_det2}${proc_det}" proc_out="${proc_det}" @@ -2361,25 +2400,25 @@ draw_processes() { #? Draw processes and values to screen elif ((resized==0)); then unset proc_det create_box -v proc_out -col ${box[${this_box}_col]} -line ${box[${this_box}_line]} -width ${box[${this_box}_width]} -height ${box[${this_box}_height]} -fill -lc "${box[${this_box}_color]}" -title ${this_box} - fi + fi fi if [[ ${proc[detailed]} -eq 1 ]]; then local det_status status_color det_columns=3 if ((tty_width>140)); then ((det_columns++)); fi if ((tty_width>150)); then ((det_columns++)); fi - if [[ -z $det_no_add && $1 != "now" && -z ${proc[detailed_killed]} ]]; then + if [[ -z $det_no_add && $1 != "now" && -z ${proc[detailed_killed]} ]]; then create_graph -add-last detail_graph detail_history if ((tty_width>120)); then create_mini_graph -w $((right_width/3-3)) -nc -add-last detail_mem_graph detail_mem_history; fi fi - + print -v proc_out -fg ${theme[title]} -b cmd_y=0 for i in C P U; do print -v proc_out -m $((d_line+3+cmd_y++)) $((d_col+1)) -t "$i" done print -v proc_out -m $((d_line+1)) $((d_col+1)) -fg ${theme[title]} -t "${proc[detailed_cpu]}%" - + if [[ -n ${proc[detailed_killed]} ]]; then det_status="stopped"; status_color="${theme[inactive_fg]}" else det_status="running"; status_color="${theme[proc_misc]}"; fi print -v proc_out -m $((d_line+1)) ${right_col} -fg ${theme[title]} -b -jc $((right_width/det_columns-1)) -t "Status:" -jc $((right_width/det_columns)) -t "Elapsed:" -jc $((right_width/det_columns)) -t "Parent:" @@ -2389,7 +2428,7 @@ draw_processes() { #? Draw processes and values to screen if ((det_columns>=4)); then print -v proc_out -jc $((right_width/det_columns-1)) -t "${proc[detailed_user]::$((right_width/det_columns-2))}"; fi if ((det_columns>=5)); then print -v proc_out -jc $((right_width/det_columns-1)) -t "${proc[detailed_threads]}"; fi - print -v proc_out -m $((d_line+4)) ${right_col} -fg ${theme[title]} -b -jr $((right_width/3+2)) -t "Memory: ${proc[detailed_mem]}%" -t " " + print -v proc_out -m $((d_line+4)) ${right_col} -fg ${theme[title]} -b -jr $((right_width/3+2)) -t "Memory: ${proc[detailed_mem]}%" -t " " if ((tty_width>120)); then print -v proc_out -rs -fg ${theme[inactive_fg]} -rp $((right_width/3-3)) "⡀" -l $((right_width/3-3)) -fg ${theme[proc_misc]} -t "${detail_mem_graph}" -t " "; fi print -v proc_out -fg ${theme[title]} -b -t "${proc[detailed_mem_string]}" fi @@ -2409,9 +2448,9 @@ draw_processes() { #? Draw processes and values to screen pid_g="$(( pid_g-( pid_add_g*(proc[selected]-1) ) ))" pid_b="$(( pid_b-( pid_add_b*(proc[selected]-1) ) ))" fi - + current_num=1 - + print -v proc_out -rs -m $((line+y++)) $((col+1)) -fg ${theme[title]} -b -t "${proc_array[0]::$((width-3))} " -rs @@ -2421,17 +2460,17 @@ draw_processes() { #? Draw processes and values to screen if ((current_num==proc[selected])); then print -v proc_out -bg ${theme[selected_bg]} -fg ${theme[selected_fg]} -b; proc[selected_pid]="$pid" else print -v proc_out -rs -fg $((fg_r-fg_step_r)) $((fg_b-fg_step_b)) $((fg_b-fg_step_b)); fi - + print -v proc_out -m $((line+y)) $((col+1)) -t "${out_line::$((width-3))} " - + if ((current_num==proc[selected])); then print -v proc_out -rs -bg ${theme[selected_bg]}; fi - + print -v proc_out -m $((line+y)) $((col+width-12)) -fg ${theme[inactive_fg]} -t "⡀⡀⡀⡀⡀" if [[ -n ${!pid_graph} ]]; then print -v proc_out -m $((line+y)) $((col+width-12)) -fg $((pid_r-pid_step_r)) $((pid_g-pid_step_g)) $((pid_b-pid_step_b)) -t "${!pid_graph}" fi - + ((y++)) ((current_num++)) if ((y>height-2)); then break; fi @@ -2443,10 +2482,10 @@ draw_processes() { #? Draw processes and values to screen fg_step_r=$((fg_step_r+fg_add_r)); fg_step_g=$((fg_step_g+fg_add_g)); fg_step_b=$((fg_step_b+fg_add_b)) pid_step_r=$((pid_step_r+pid_add_r)); pid_step_g=$((pid_step_g+pid_add_g)); pid_step_b=$((pid_step_b+pid_add_b)) fi - + done print -v proc_out -rs - while ((y<=height-2)); do + while ((y<=height-2)); do print -v proc_out -m $((line+y++)) $((col+1)) -rp $((width-2)) -t " " done @@ -2467,7 +2506,7 @@ draw_processes() { #? Draw processes and values to screen fi print -v proc_misc -m $line $((col+width-${#proc_sorting}-8-reverse_pos)) -rs ${reverse_string}\ -fg ${box[processes_color]} -t "┤" -fg ${theme[hi_fg]} -b -t "‹" -fg ${theme[title]} -t " ${proc_sorting} " -fg ${theme[hi_fg]} -t "›" -rs -fg ${box[processes_color]} -t "├" - + if [[ -z $filter && -z $input_to_filter ]]; then print -v proc_misc -m $line $((col+14)) -fg ${box[processes_color]} -t "┤" -fg ${theme[hi_fg]} -b -t "f" -fg ${theme[title]} -t "ilter" -rs -fg ${box[processes_color]} -t "├" elif [[ -n $input_to_filter ]]; then @@ -2482,8 +2521,8 @@ draw_processes() { #? Draw processes and values to screen print -v proc_misc -m $line $((col+14)) -fg ${box[processes_color]} -t "┤" -fg ${theme[hi_fg]} -b -t "f" -fg ${theme[title]} -t " ${filter_string} " -fg ${theme[hi_fg]} -t "c" -rs -fg ${box[processes_color]} -t "├" fi - - + + proc_out+="${proc_misc}" fi @@ -2523,7 +2562,7 @@ draw_net() { #? Draw net information and graphs to screen #* Get variables from previous calculations local col=$((box[net_col]+1)) line=$((box[net_line]+1)) width=$((box[net_width]-2)) height=$((box[net_height]-2)) local n_width=${box[n_width]} n_height=${box[n_height]} n_col=${box[n_col]} n_line=${box[n_line]} main_fg="${theme[main_fg]}" - + #* If resized recreate net meter box and net graphs if ((resized>0)); then local graph_a_size graph_b_size @@ -2535,11 +2574,11 @@ draw_net() { #? Draw net information and graphs to screen create_graph -o download_graph -d $line $col $graph_a_size $((width-n_width-2)) -c color_download_graph -n -max "${net[download_graph_max]}" net_history_download create_graph -o upload_graph -d $((line+graph_a_size)) $col $graph_b_size $((width-n_width-2)) -c color_upload_graph -i -n -max "${net[upload_graph_max]}" net_history_upload - net[download_redraw]=0 + net[download_redraw]=0 net[upload_redraw]=0 ((resized++)) fi - + #* Update graphs if graph resolution update is needed or just resized, otherwise just add new values if ((net[download_redraw]==1 | resized>0)); then create_graph -o download_graph -d $line $col ${net[graph_a_size]} $((width-n_width-2)) -c color_download_graph -n -max "${net[download_graph_max]}" net_history_download @@ -2558,12 +2597,12 @@ draw_net() { #? Draw net information and graphs to screen print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▼ Byte:" -jr 12 -t "${net[speed_download_byteps]}" if ((height>4)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▼ Bit:" -jr 12 -t "${net[speed_download_bitps]}"; fi if ((height>6)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▼ Total:" -jr 12 -t "${net[total_download]}"; fi - + if ((height>8)); then ((ypos++)); fi print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▲ Byte:" -jr 12 -t "${net[speed_upload_byteps]}" if ((height>7)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▲ Bit:" -jr 12 -t "${net[speed_upload_bitps]}"; fi if ((height>5)); then print -v net_out -fg ${main_fg} -m $((ypos++)) $n_col -jl 10 -t "▲ Total:" -jr 12 -t "${net[total_upload]}"; fi - + #* Print graphs and text to output variable draw_out+="${download_graph[*]}${upload_graph[*]}${net_out}" @@ -2598,11 +2637,11 @@ pause_() { #? Pause input and draw a darkened version of main ui prev_screen+="${proc_out}" unset skip_process_draw proc_out fi - + unset pause_screen print -v pause_screen -rs -b -fg ${theme[inactive_fg]} pause_screen+="${theme[main_bg]}m$(sed -E 's/\\e\[[0-9;\-]*m//g' <<< "${prev_screen}")\e[0m" #\e[1;38;5;236 - + if [[ -z $ext_var ]]; then echo -en "${pause_screen}" else pause_out="${pause_screen}"; fi @@ -2619,7 +2658,7 @@ unpause_() { #? Unpause menu_() { #? Shows the main menu overlay local menu i count keypress selected_int=0 selected up local_rez d_banner=1 menu_out bannerd skipped menu_pause out_out wait_string trans local -a menus=("options" "help" "quit") color - + until false; do #* Put program to sleep if caught ctrl-z @@ -2663,17 +2702,17 @@ menu_() { #? Shows the main menu overlay unset out_out out_out="${menu_pause}${menu_out}" echo -e "${out_out}" - - + + get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) if ((time_left>1000)); then wait_string=1; time_left=$((time_left-1000)) elif ((time_left>1)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 else wait_string="0.001"; time_left=0; fi - + get_key -v keypress -w ${wait_string} if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi - if ((resized>0)); then + if ((resized>0)); then calc_sizes; draw_bg quiet; time_left=0; unset menu_out unset bannerd fi @@ -2691,13 +2730,13 @@ menu_() { #? Shows the main menu overlay m|M|escape|backspace) break ;; q|Q) quit_ ;; esac - + if ((time_left==0)); then get_ms timestamp_start; collect_and_draw; fi if ((resized>=5)); then resized=0; fi - done + done unpause_ - + } help_() { #? Shows the help overlay @@ -2742,7 +2781,7 @@ help_() { #? Shows the help overlay ) if [[ -n $pause_screen ]]; then from_menu=1; fi - + until [[ -n $help_key ]]; do #* Put program to sleep if caught ctrl-z @@ -2763,14 +2802,14 @@ help_() { #? Shows the help overlay draw_banner "$((tty_height/2-11))" help_out print -d 1 create_box -v help_out -w 72 -h $((height+3)) -l $((line++)) -c $((col++)) -fill -lc ${theme[div_line]} -title "help" - + if [[ -n $pages ]]; then print -v help_out -m $((line-1)) $((col+72-17)) -rs -fg ${theme[div_line]} -t "┤" -fg ${theme[hi_fg]} -b -t "‹" -fg ${theme[title]} -t " page ${page}/${pages} " -fg ${theme[hi_fg]} -t "›" -rs -fg ${theme[div_line]} -t "├" fi ((++col)) print -v help_out -m $line $col -fg ${theme[title]} -b -jl 20 -t "Key:" -jl 48 -t "Description:" -m $((line+y++)) $col - + for((i=(page-1)*height;i1000)); then wait_string=1; time_left=$((time_left-1000)) elif ((time_left>0)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 else wait_string="0.001"; time_left=0; fi - + get_key -v help_key -w "${wait_string}" if [[ -n $pages ]]; then @@ -2797,7 +2836,7 @@ help_() { #? Shows the help overlay fi if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi - if ((resized>0)); then + if ((resized>0)); then sleep 0.5 calc_sizes; draw_bg quiet; redraw=1 d_banner=1 @@ -2902,8 +2941,8 @@ options_() { #? Shows the options overlay #* Put program to sleep if caught ctrl-z if ((sleepy==1)); then sleep_; fi - - + + if [[ $background_update == true || -n $redraw_misc ]]; then draw_clock if [[ -z $inputting ]]; then pause_ options_pause; fi @@ -2924,8 +2963,8 @@ options_() { #? Shows the options overlay print -v options_misc -m $((line)) $((col+29-17)) -rs -fg ${theme[div_line]} -t "┤" -fg ${theme[hi_fg]} -b -t "p" -fg ${theme[title]} -t " page ${page}/${pages} " -fg ${theme[hi_fg]} -t "n" -rs -fg ${theme[div_line]} -t "├" fi fi - - + + if [[ -n $keypress || -z $options_out ]]; then unset options_out desc_height lr inp valid selected="${options_array[selected_int]}" @@ -2937,13 +2976,13 @@ options_() { #? Shows the options overlay for((i=(page-1)*height,ypos=1;i500)); then wait_string=0.5 elif ((time_left>0)); then printf -v wait_string ".%03d" "${time_left}" else wait_string="0.001"; time_left=0; fi - + get_key -v keypress -w ${wait_string} - + if [[ -n $inputting ]]; then case "$keypress" in escape) unset inputting inputting_value ;; @@ -3020,12 +3059,12 @@ options_() { #? Shows the options overlay esac if (( selected_int<(page-1)*height | selected_int>=page*height )); then page=$(( (selected_int/height)+1 )); redraw_misc=1; fi fi - + if [[ ${selected} == "color_theme" && ${keypress} =~ left|right && ${#themes} -lt 2 ]]; then unset valid; fi if [[ -n $valid ]]; then case "${selected} ${keypress}" in - "update_ms right") + "update_ms right") if ((update_ms<86399900)); then update_ms=$((update_ms+100)) updated_ms=1 @@ -3039,7 +3078,7 @@ options_() { #? Shows the options overlay ;; "update_ms enter") if [[ -z $inputting ]]; then inputting=1; inputting_value="${update_ms}" - else + else if ((inputting_value<86400000)); then update_ms="${inputting_value:-0}"; updated_ms=1; fi unset inputting inputting_value fi @@ -3127,7 +3166,7 @@ options_() { #? Shows the options overlay if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi - if ((resized>0)); then + if ((resized>0)); then calc_sizes; draw_bg quiet redraw_misc=1 unset options_out bannerd menu_out @@ -3152,7 +3191,7 @@ options_() { #? Shows the options overlay killer_() { #? Kill process with selected signal local kill_op="$1" kill_pid="$2" killer_out killer_box col line program keypress selected selected_int=0 sig confirmed=0 option killer_pause status msg local -a options=("yes" "no") - + if ! program="$(ps -o comm --no-header -p ${kill_pid})"; then return; fi case $kill_op in @@ -3160,7 +3199,7 @@ killer_() { #? Kill process with selected signal k|K) kill_op="kill"; sig="SIGKILL" ;; i|I) kill_op="interrupt"; sig="SIGINT" ;; esac - + until false; do #* Put program to sleep if caught ctrl-z @@ -3176,7 +3215,7 @@ killer_() { #? Kill process with selected signal if [[ -z $killer_box ]]; then col=$((tty_width/2-15)); line=$((tty_height/2-4)); y=1 unset redraw killer_box - create_box -v killer_box -w 40 -h 9 -l $line -c $((col++)) -fill -lc "${theme[proc_box]}" -title "${kill_op}" + create_box -v killer_box -w 40 -h 9 -l $line -c $((col++)) -fill -lc "${theme[proc_box]}" -title "${kill_op}" fi if ((confirmed==0)); then @@ -3194,20 +3233,20 @@ killer_() { #? Kill process with selected signal if [[ -n $msg ]]; then print -v killer_out -m $((line+5)) $col -fg ${theme[main_fg]} -jc 38 -t "${msg}" -m $((line+7)) $col; fi print -v killer_out -fg ${theme[selected_fg]} -bg ${theme[selected_bg]} -b -r 15 -t "[ Ok ]" -rs fi - + echo -en "${killer_pause}${killer_box}${killer_out}" unset killer_out draw_out - - + + get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) if ((time_left>1000)); then wait_string=1; time_left=$((time_left-1000)) elif ((time_left>1)); then printf -v wait_string ".%03d" "${time_left}"; time_left=0 else wait_string="0.001"; time_left=0; fi - + get_key -v keypress -w ${wait_string} if [[ $(stty size) != "$tty_height $tty_width" ]]; then resized; fi - if ((resized>0)); then + if ((resized>0)); then calc_sizes; draw_bg quiet; time_left=0; unset killer_out killer_box fi @@ -3222,16 +3261,16 @@ killer_() { #? Kill process with selected signal ;; q|Q) quit_ ;; esac - - + + if ((confirmed<0)); then unpause_ break elif ((confirmed>0)) && [[ -z $status ]]; then - if kill -${sig} ${kill_pid} >/dev/null 2>&1; then + if kill -${sig} ${kill_pid} >/dev/null 2>&1; then status="success" - else + else if ! ps -p ${kill_pid} >/dev/null 2>&1; then msg="Process not running." elif [[ $UID != 0 ]]; then @@ -3241,14 +3280,14 @@ killer_() { #? Kill process with selected signal fi status="failed"; fi fi - + if ((time_left==0)); then get_ms timestamp_start; unset draw_out; collect_and_draw; fi if ((resized>=5)); then resized=0; fi - done - - + done + + } get_key() { #? Get one key from standard input and translate key code to readable format @@ -3264,18 +3303,18 @@ get_key() { #? Get one key from standard input and translate key code to readabl esac shift done - + if [[ -z $save && -n ${saved_key[0]} ]]; then key="${saved_key[0]}"; unset 'saved_key[0]'; saved_key=("${saved_key[@]}") else unset key IFS= read -rsd '' -t ${wait_time:-0.001} -n 1 key >/dev/null 2>&1 ||true - if [[ -z ${key:+s} ]]; then + if [[ -z ${key:+s} ]]; then key_out="" if [[ -z $save ]]; then return 0 else return 1; fi fi - + #* Read 3 more characters if a leading escape character is detected if [[ $key == "${enter_key}" ]]; then key="enter" elif [[ $key == "${backspace}" ]]; then key="backspace" @@ -3314,7 +3353,7 @@ get_key() { #? Get one key from standard input and translate key code to readabl fi read -rst 0.0001 -n 1000 2>/dev/null ||true - + if [[ -n $save && -n $key ]]; then saved_key+=("${key}"); return 0; fi if [[ -n $ext_out ]]; then key_out="${key}" @@ -3336,7 +3375,7 @@ process_input() { #? Process keypresses for main ui "escape") unset input_to_filter filter ;; *) if [[ ${#keypress} -eq 1 ]]; then filter+="${keypress//[\\\$\"\']/}"; else unset filter_change; fi ;; esac - + else case "$keypress" in left) #* Move left in processes sorting column @@ -3484,7 +3523,7 @@ collect_and_draw() { #? Run all collect and draw functions local task_int=0 for task in processes cpu mem net; do ((++task_int)) - if [[ -n $pause_screen && -n ${saved_key[0]} ]]; then + if [[ -n $pause_screen && -n ${saved_key[0]} ]]; then return elif [[ -z $pause_screen ]]; then while [[ -n ${saved_key[0]} ]]; do @@ -3510,7 +3549,7 @@ main_loop() { #? main loop... #* Put program to sleep if caught ctrl-z if ((sleepy==1)); then sleep_; fi - + #* Timestamp for accurate timer get_ms timestamp_start @@ -3527,11 +3566,11 @@ main_loop() { #? main loop... #* Reset resized variable if resized and all functions have finished redrawing if ((resized>=5)); then resized=0 elif ((resized>0)); then unset draw_out proc_out clock_out; return; fi - + #* Echo everyting out to screen in one command to get a smooth transition between updates echo -en "${draw_out}${proc_out}${clock_out}" unset draw_out - + #* Compare timestamps to get exact time needed to wait until next loop get_ms timestamp_end time_left=$((timestamp_start+update_ms-timestamp_end)) @@ -3546,14 +3585,14 @@ main_loop() { #? main loop... if [[ -z $input_to_filter ]] && ((time_left>=500)); then wait_string="0.5" time_left=$((time_left-500)) - + #* If waiting for input and time left is greater than "50 ms", wait 50ms and loop elif [[ -n $input_to_filter ]] && ((time_left>=50)); then wait_string="0.05" time_left=$((time_left-50)) #* Else format wait string with padded zeroes if needed and break loop - else + else printf -v wait_string ".%03d" "${time_left}" time_left=0 fi @@ -3562,10 +3601,10 @@ main_loop() { #? main loop... while [[ -n ${saved_key[0]} ]]; do process_input late_update=0 - done + done process_input "${wait_string}" - #* Draw clock if set + #* Draw clock if set draw_clock now done @@ -3575,7 +3614,7 @@ main_loop() { #? main loop... update_ms=$((update_ms+100)) draw_update_string fi - + if ((skip_process_draw==1)); then unset skip_process_draw; fi } @@ -3583,7 +3622,7 @@ main_loop() { #? main loop... #* Read config file or create if non existant config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/bashtop" -if [[ -d "${config_dir}" && -w "${config_dir}" ]] || mkdir -p "${config_dir}"; then +if [[ -d "${config_dir}" && -w "${config_dir}" ]] || mkdir -p "${config_dir}"; then theme_dir="${config_dir}/themes" if [[ ! -d "${theme_dir}" ]]; then mkdir -p "${theme_dir}"; fi config_file="${config_dir}/bashtop.cfg" @@ -3609,7 +3648,7 @@ fi #* Set up traps for ctrl-c, soft kill, window resize, ctrl-z and resume from ctrl-z trap 'quitting=1; time_left=0' SIGINT SIGQUIT SIGTERM trap 'resized=1; time_left=0' SIGWINCH -trap 'sleepy=1; time_left=0' SIGTSTP +trap 'sleepy=1; time_left=0' SIGTSTP trap 'resume_' SIGCONT