mirror of
https://github.com/aristocratos/btop.git
synced 2024-05-21 04:43:36 +12:00
Merge pull request #2 from kz6fittycent/testing
Desktop UI now working in snap
This commit is contained in:
commit
0cd636a3a4
|
@ -1,3 +1,7 @@
|
|||
[*.{cpp,h,sh,md,cfg,sample}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -7,6 +7,10 @@ assignees: aristocratos
|
|||
|
||||
---
|
||||
|
||||
**Read the README.md and search for similar issues before posting a bug report!**
|
||||
|
||||
Any bug that can be solved by just reading the [prerequisites](https://github.com/aristocratos/btop#prerequisites) section of the README will likely be ignored.
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
[A clear and concise description of what the bug is.]
|
||||
|
@ -24,7 +28,7 @@ assignees: aristocratos
|
|||
[If applicable, add screenshots to help explain your problem.]
|
||||
|
||||
**Info (please complete the following information):**
|
||||
- btop++ version: `bpytop -v`
|
||||
- btop++ version: `btop -v`
|
||||
- Binary: [self compiled or static binary from release]
|
||||
- (If compiled) Compiler and version:
|
||||
- Architecture: [x86_64, aarch64, etc.] `uname -m`
|
||||
|
@ -38,16 +42,18 @@ assignees: aristocratos
|
|||
|
||||
contents of `~/.config/btop/btop.log`
|
||||
|
||||
(try running btop with `--debug` flag if error.log is empty)
|
||||
(try running btop with `--debug` flag if btop.log is empty)
|
||||
|
||||
**GDB Backtrace**
|
||||
|
||||
If btop++ is crashing at start the following steps could be helpful:
|
||||
|
||||
1. run `gdb btop`
|
||||
(Extra helpful if compiled with `make OPTFLAGS="-O0 -g"`)
|
||||
|
||||
2. `r` to run, wait for crash and press enter
|
||||
1. run (linux): `gdb btop` (macos): `lldb btop`
|
||||
|
||||
3. `bt` to get backtrace
|
||||
2. `r` to run, wait for crash and press enter if prompted, CTRL+L to clear screen if needed.
|
||||
|
||||
3. (gdb): `thread apply all bt` (lldb): `bt all` to get backtrace for all threads
|
||||
|
||||
4. Copy and paste the backtrace here:
|
||||
|
|
113
.github/workflows/continuous-build-linux.yml
vendored
Normal file
113
.github/workflows/continuous-build-linux.yml
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
name: Continuous Build Linux
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags-ignore:
|
||||
- '*.*'
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '!src/osx/**'
|
||||
- '!src/freebsd/**'
|
||||
- 'include/**'
|
||||
- 'Makefile'
|
||||
- '.github/workflows/continuous-build.yml'
|
||||
|
||||
jobs:
|
||||
static-build:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
toolchain:
|
||||
- aarch64-linux-musl
|
||||
- aarch64_be-linux-musl
|
||||
- arm-linux-musleabi
|
||||
- arm-linux-musleabihf
|
||||
- armeb-linux-musleabi
|
||||
- armeb-linux-musleabihf
|
||||
- armel-linux-musleabi
|
||||
- armel-linux-musleabihf
|
||||
- armv5l-linux-musleabi
|
||||
- armv5l-linux-musleabihf
|
||||
- armv6-linux-musleabi
|
||||
- armv6-linux-musleabihf
|
||||
- armv7l-linux-musleabihf
|
||||
- armv7m-linux-musleabi
|
||||
- armv7r-linux-musleabihf
|
||||
- i486-linux-musl
|
||||
- i686-linux-musl
|
||||
- m68k-linux-musl
|
||||
- mips-linux-musl
|
||||
- mips-linux-musln32sf
|
||||
- mips-linux-muslsf
|
||||
- mips64-linux-musl
|
||||
- mips64-linux-musln32
|
||||
- mips64-linux-musln32sf
|
||||
- mips64el-linux-musl
|
||||
- mips64el-linux-musln32
|
||||
- mips64el-linux-musln32sf
|
||||
- mipsel-linux-musl
|
||||
- mipsel-linux-musln32
|
||||
- mipsel-linux-musln32sf
|
||||
- mipsel-linux-muslsf
|
||||
- powerpc-linux-musl
|
||||
- powerpc-linux-muslsf
|
||||
- powerpc64-linux-musl
|
||||
- powerpc64le-linux-musl
|
||||
- powerpcle-linux-musl
|
||||
- powerpcle-linux-muslsf
|
||||
- riscv32-linux-musl
|
||||
- riscv64-linux-musl
|
||||
- s390x-linux-musl
|
||||
- x86_64-linux-musl
|
||||
- x86_64-linux-muslx32
|
||||
|
||||
# - or1k-linux-musl
|
||||
# - sh2-linux-musl
|
||||
# - sh2-linux-muslfdpic
|
||||
# - sh2eb-linux-musl
|
||||
# - sh2eb-linux-muslfdpic
|
||||
# - sh4-linux-musl
|
||||
# - sh4eb-linux-musl
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container: muslcc/x86_64:${{ matrix.toolchain }}
|
||||
|
||||
steps:
|
||||
- name: Install build tools
|
||||
run: apk add --no-cache coreutils git make tar zstd
|
||||
|
||||
- name: Fix - Unsafe repository stop
|
||||
run: git config --global --add safe.directory /__w/btop/btop
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Fix - Stopping at filesystem boundary
|
||||
run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).]
|
||||
|
||||
- name: Build
|
||||
run: make STATIC=true STRIP=true
|
||||
|
||||
- name: Make executable
|
||||
run: chmod +x bin/*
|
||||
|
||||
- name: Set up directories
|
||||
run: |
|
||||
mkdir .artifacts
|
||||
mkdir .package
|
||||
|
||||
- name: Create binary atrifacts
|
||||
run: |
|
||||
TOOLCHAIN=${{ matrix.toolchain }}
|
||||
GIT_HASH=$(git rev-parse --short "${{ github.sha }}")
|
||||
FILENAME=btop-${TOOLCHAIN/linux-musl/}-$GIT_HASH
|
||||
cp bin/btop .artifacts/$FILENAME
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: btop-${{ matrix.toolchain }}
|
||||
path: '.artifacts/**'
|
34
.github/workflows/continuous-build-macos.yml
vendored
Normal file
34
.github/workflows/continuous-build-macos.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
name: Continuous Build MacOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags-ignore:
|
||||
- '*.*'
|
||||
paths:
|
||||
- 'src/**'
|
||||
- '!src/linux/**'
|
||||
- '!src/freebsd/**'
|
||||
- 'include/**'
|
||||
- 'Makefile'
|
||||
- '.github/workflows/*'
|
||||
|
||||
jobs:
|
||||
build-osx:
|
||||
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Compile
|
||||
run: |
|
||||
make CXX=g++-11 ARCH=x86_64 STATIC=true STRIP=true
|
||||
GIT_HASH=$(git rev-parse --short "$GITHUB_SHA")
|
||||
mv bin/btop bin/btop-x86_64-BigSur-$GIT_HASH
|
||||
ls -alh bin
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: btop-x86_64-macos-BigSur
|
||||
path: 'bin/*'
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -49,4 +49,8 @@ stage/
|
|||
build
|
||||
bin
|
||||
btop
|
||||
.*/
|
||||
.*/
|
||||
|
||||
|
||||
#do not ignore .github directory
|
||||
!.github
|
288
CHANGELOG.md
288
CHANGELOG.md
|
@ -1,3 +1,291 @@
|
|||
## v1.2.8
|
||||
|
||||
* Added: Support for ZFS pool io stats monitoring, by @simplepad
|
||||
|
||||
* Added: Filtering of kernel processes, by @0xJoeMama
|
||||
|
||||
* Added: New theme everforest-dark-hard, by @iambeingtracked
|
||||
|
||||
* Added: New theme tomorrow-night, by @appuchias
|
||||
|
||||
* Changed: Disable battery monitoring if it fails instead of exiting
|
||||
|
||||
## v1.2.7
|
||||
|
||||
* Fixed: Disk IO stats for individual partitions instead of whole disk (Linux)
|
||||
|
||||
* Added: Case insensitive process filtering, by @abrasumente233
|
||||
|
||||
* Added: Include ZFS ARC in cached/available memory on Linux, by @mattico
|
||||
|
||||
* Added: Desktop entry and icons, by @yonatan8070
|
||||
|
||||
* Fixed: Net sync scale bug
|
||||
|
||||
* Added: tokyo-night & tokyo-storm themes, by @Schievel1
|
||||
|
||||
## v1.2.6
|
||||
|
||||
* Fixed: Wrong memory unit when shorten and size is less than 10, by @mohi001
|
||||
|
||||
* Fixed: Use cpu cores avarage temp if missing cpu package temp for FreeBSD
|
||||
|
||||
* Changed: Enter symbol to a more common variant
|
||||
|
||||
## v1.2.5
|
||||
|
||||
* Fixed: Fallback to less accurate UTF8 char count if conversion to wstring fails
|
||||
|
||||
* Fixed: Small ui fixes for mem and disks
|
||||
|
||||
* Added: New theme HotPurpleTrafficLight, by @pallebone
|
||||
|
||||
* Fixed: title_left symbol between auto and zero in the net box is not displayed, by @mrdotx
|
||||
|
||||
* Fixed: Mouse mappings for net box
|
||||
|
||||
## v1.2.4
|
||||
|
||||
* Optimization: Proc::draw()
|
||||
|
||||
* Fixed: Ignore duplicate disks with same mountpoint
|
||||
|
||||
* Changed: Restrict command line for processes to 1000 characters to fix utf8 conversion errors
|
||||
|
||||
* Added: add "g" and "G" to vim keys, by @mohi001
|
||||
|
||||
## v1.2.3
|
||||
|
||||
* Changed: floating_humanizer() now show fractions when shortened and value is < 10
|
||||
|
||||
* Fixed: Process tree not redrawing properly
|
||||
|
||||
* Fixed: string to wstring conversion crash when string is too big
|
||||
|
||||
## v1.2.2
|
||||
|
||||
* Changed: Reverted uncolor() back to using regex to fix delay in opening menu when compiled with musl
|
||||
|
||||
* Added: Toggle for showing free disk space for privileged or normal users
|
||||
|
||||
* Added: Clarification on signal screen that number can be manually entered
|
||||
|
||||
## v1.2.1
|
||||
|
||||
* Added: Arrow only after use of "f" when filtering processes, by @NavigationHazard
|
||||
|
||||
* Fixed: Fx::uncolor not removing all escapes
|
||||
|
||||
* Fixed: Text alignment for popup boxes
|
||||
|
||||
* Fixed: Terminal resize warning getting stuck
|
||||
|
||||
* Removed: Unnecessary counter for atomic_lock
|
||||
|
||||
* Added: Percentage progress to Makefile
|
||||
|
||||
* Fixed: Alignment of columns in proc box when wide UTF8 characters are used
|
||||
|
||||
* Fixed: Battery meter draw fix
|
||||
|
||||
## v1.2.0
|
||||
|
||||
* Added: Support for FreeBSD, by @joske and @aristocratos
|
||||
|
||||
* Fixed (again): Account for system rolling over net speeds in Net::collect()
|
||||
|
||||
* Added: Theme gruvbox_material_dark, by @marcoradocchia
|
||||
|
||||
* Added: Option for base 10 bytes/bits
|
||||
|
||||
## v1.1.5
|
||||
|
||||
* Fixed: Account for system rolling over net speeds in Net::collect()
|
||||
|
||||
## v1.1.4
|
||||
|
||||
* Fixed: Create dependency files in build directory when compiling, by @stwnt
|
||||
|
||||
* Fixed: fix CPU temp fallback on macOS, by @joske
|
||||
|
||||
* Changed: From rng::sort() to rng::stable_sort() for more stability
|
||||
|
||||
* Fixed: in_avail() can always be zero, by @pg83
|
||||
|
||||
## v1.1.3
|
||||
|
||||
* Added: New theme ayu, by @AlphaNecron
|
||||
|
||||
* Added: New theme gruvbox_dark_v2, by @pietryszak
|
||||
|
||||
* Fixed: Macos cpu coretemp for Intel, by @joske
|
||||
|
||||
* Added: New theme OneDark, by @vtmx
|
||||
|
||||
* Fixed: Fixed network graph scale int rollover
|
||||
|
||||
* Fixed: Suspected possibility of very rare stall in Input::clear()
|
||||
|
||||
## v1.1.2
|
||||
|
||||
* Fixed: SISEGV on macos Mojave, by @mgradowski
|
||||
|
||||
* Fixed: Small optimizations and fixes to Mem::collect() and Input::get()
|
||||
|
||||
* Fixed: Wrong unit for net_upload and net_download in config menu
|
||||
|
||||
* Fixed: UTF-8 detection on macos
|
||||
|
||||
* Fixed: coretemp iteration due to missing tempX_input, by @KFilipek
|
||||
|
||||
* Fixed: coretemp ordering
|
||||
|
||||
## v1.1.1
|
||||
|
||||
* Added: Partial static build (libgcc, libstdc++) for macos
|
||||
|
||||
* Changed: Continuous build macos switched to OSX 11.6 (Big Sur) and partial static build
|
||||
|
||||
* Changed: Release binaries for macos switched to OSX 12 (Monterey) and partial static build
|
||||
|
||||
## v1.1.0
|
||||
|
||||
* Added: Support for OSX, by @joske and @aristocratos
|
||||
|
||||
## v1.0.24
|
||||
|
||||
* Changed: Collection ordering
|
||||
|
||||
* Fixed: Restore all escape seq mouse modes on exit
|
||||
|
||||
* Fixed: SIGINT not cleaning up on exit
|
||||
|
||||
## v1.0.23
|
||||
|
||||
* Fixed: Config parser missing first value when not including version header
|
||||
|
||||
* Fixed: Vim keys menu lists selection
|
||||
|
||||
* Fixed: Stall when clearing input queue on exit and queue is >1
|
||||
|
||||
* Fixed: Inconsistent behaviour of "q" key in the menus
|
||||
|
||||
## v1.0.22
|
||||
|
||||
* Fixed: Bad values for disks and network on 32-bit
|
||||
|
||||
## v1.0.21
|
||||
|
||||
* Fixed: Removed extra spaces in cpu name
|
||||
|
||||
* Added: / as alternative bind for filter
|
||||
|
||||
* Fixed: Security issue when running with SUID bit set
|
||||
|
||||
## v1.0.20
|
||||
|
||||
* Added: Improved cpu sensor detection for Ryzen Mobile, by @adnanpri
|
||||
|
||||
* Changed: Updated makefile
|
||||
|
||||
* Changed: Regex for Fx::uncolor() changed to string search and replace
|
||||
|
||||
* Changed: Removed all use of regex with dedicated string functions
|
||||
|
||||
## v1.0.19
|
||||
|
||||
* Fixed: Makefile now tests compiler flag compatibility
|
||||
|
||||
## v1.0.18
|
||||
|
||||
* Fixed: Makefile g++ -dumpmachine failure to get platform on some distros
|
||||
|
||||
## v1.0.17
|
||||
|
||||
* Changed: Reverted mutexes back to custom atomic bool based locks
|
||||
|
||||
* Added: Static binaries switched to building with musl + more platforms, by @jan-guenter
|
||||
|
||||
* Fixed: Improved battery detection, by @jan-guenter
|
||||
|
||||
* Added: Displayed battery selectable in options menu
|
||||
|
||||
* Fixed: Battery error if non existent battery named is entered
|
||||
|
||||
## v1.0.16
|
||||
|
||||
* Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep
|
||||
|
||||
* Fixed: Swapped from atomic bool spinlocks to mutexes to fix rare deadlock
|
||||
|
||||
* Added: Continuous Build workflow for OSX branch, by @ShrirajHegde
|
||||
|
||||
* Changed: Reverted thread mutex lock to atomic bool with wait and timeout
|
||||
|
||||
* Changed: Removed unnecessary async threads in Runner thread
|
||||
|
||||
* Added: Try to restart secondary thread in case of stall and additional error checks for ifstream in Proc::collect()
|
||||
|
||||
* Fixed: change [k]ill to [K]ill when enabling vim keys, by @jlopezcur
|
||||
|
||||
## v1.0.15
|
||||
|
||||
* Fixed: Extra "root" partition when running in snap
|
||||
|
||||
* Changed: Limit atomic_wait() to 1000ms to fix rare stall
|
||||
|
||||
* Fixed: Removed unneeded lock in Runner::run()
|
||||
|
||||
* Added: Toggle in options for enabling directional vim keys "h,j,k,l"
|
||||
|
||||
## v1.0.14
|
||||
|
||||
* Changed: Total system memory is checked at every update instead of once at start
|
||||
|
||||
* Added: Continuous Build workflow, by @ShrirajHegde
|
||||
|
||||
* Fixed: Uid -> User fallback to getpwuid() if failure for non static builds
|
||||
|
||||
* Fixed: snap root disk and changed to compiler flags instead of env variables for detection
|
||||
|
||||
* Added: Development branch for OSX, by @joske
|
||||
|
||||
## v1.0.13
|
||||
|
||||
* Changed: Graph empty symbol is now regular whitespace
|
||||
|
||||
## v1.0.12
|
||||
|
||||
* Fixed: Exception handling for faulty net download/upload speed
|
||||
|
||||
* Fixed: Cpu percent formatting if over 10'000
|
||||
|
||||
## v1.0.11
|
||||
|
||||
* Changed: atomic_wait to use while loop instead of wait() because of rare stall when a signal handler is triggered while waiting
|
||||
|
||||
* Fixed: Get real / mountpoint when running inside snap
|
||||
|
||||
* Fixed: UTF8 set LANG and LC_ALL to empty before UTF8 search and fixed empty error msg on exit before signal handler init
|
||||
|
||||
* Changed: Init will continue with a warning if UTF-8 locale are detected and it fails to set the locale
|
||||
|
||||
## v1.0.10
|
||||
|
||||
* Added: Wait for terminal size properties to be available at start
|
||||
|
||||
* Changed: Stop second thread before updating terminal size variables
|
||||
|
||||
* Changed: Moved check for valid terminal dimensions to before platform init
|
||||
|
||||
* Added: Check for empty percentage deques
|
||||
|
||||
* Changed: Cpu temp values check for existing values
|
||||
|
||||
* Fixed: Cpu percent cutting off above 1000 percent and added scaling with "k" prefix above 10'000
|
||||
|
||||
* Fixed: Crash when rapidly resizing terminal at start
|
||||
|
||||
## v1.0.9
|
||||
|
||||
* Added: ifstream check and try-catch for stod() in Tools::system_uptime()
|
||||
|
|
BIN
Img/icon.png
Normal file
BIN
Img/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
111
Img/icon.svg
Normal file
111
Img/icon.svg
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="90"
|
||||
height="90"
|
||||
version="1.1"
|
||||
id="svg70"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs26">
|
||||
<pattern
|
||||
xlink:href="#gray-stripes"
|
||||
id="pattern1888" />
|
||||
<pattern
|
||||
xlink:href="#red-stripes"
|
||||
id="pattern1870" />
|
||||
<pattern
|
||||
id="red-stripes"
|
||||
width="341"
|
||||
height="90"
|
||||
patternUnits="userSpaceOnUse">
|
||||
<rect
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#f00"
|
||||
id="rect2" />
|
||||
<rect
|
||||
y="16"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#d70000"
|
||||
id="rect4" />
|
||||
<rect
|
||||
y="32"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#af0000"
|
||||
id="rect6" />
|
||||
<rect
|
||||
y="48"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#870000"
|
||||
id="rect8" />
|
||||
<rect
|
||||
y="64"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#5f0000"
|
||||
id="rect10" />
|
||||
</pattern>
|
||||
<pattern
|
||||
id="gray-stripes"
|
||||
width="341"
|
||||
height="90"
|
||||
patternUnits="userSpaceOnUse">
|
||||
<rect
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#585858"
|
||||
id="rect13" />
|
||||
<rect
|
||||
y="16"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#4e4e4e"
|
||||
id="rect15" />
|
||||
<rect
|
||||
y="32"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#444"
|
||||
id="rect17" />
|
||||
<rect
|
||||
y="48"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#3a3a3a"
|
||||
id="rect19" />
|
||||
<rect
|
||||
y="64"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#303030"
|
||||
id="rect21" />
|
||||
<rect
|
||||
y="80"
|
||||
width="341"
|
||||
height="10"
|
||||
fill="#262626"
|
||||
id="rect23" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<g
|
||||
id="g2074"
|
||||
transform="translate(18)">
|
||||
<path
|
||||
d="M 2,7 V 90 H 47 V 74 h 7 V 55 H 47 V 42 h 7 V 23 H 47 V 7 Z M 19,26 H 37 V 39 H 19 Z m 0,32 H 37 V 71 H 19 Z"
|
||||
id="path28"
|
||||
style="fill:#080808" />
|
||||
<path
|
||||
d="M 2,7 V 90 H 47 V 74 h 7 V 55 H 47 V 42 h 7 V 23 H 47 V 7 Z m 1,1 h 43 v 16 h 7 v 17 h -7 v 15 h 7 V 73 H 46 V 89 H 3 Z M 18,25 H 38 V 40 H 18 Z m 1,1 V 39 H 37 V 26 Z M 18,57 H 38 V 72 H 18 Z m 1,1 V 71 H 37 V 58 Z M 4,9 V 88 H 45 V 72 h 7 V 57 H 45 V 40 h 7 V 25 H 45 V 9 Z m 1,1 h 39 v 16 h 7 v 13 h -7 v 19 h 7 V 71 H 44 V 87 H 5 Z M 16,23 H 40 V 42 H 16 Z m 1,1 V 41 H 39 V 24 Z M 16,55 H 40 V 74 H 16 Z m 1,1 V 73 H 39 V 56 Z"
|
||||
id="path42"
|
||||
style="fill:url(#pattern1888)" />
|
||||
<path
|
||||
d="M 0,0 V 80 H 42 V 64 h 7 V 48 H 42 V 32 h 7 V 16 H 42 V 0 Z M 14,16 H 35 V 32 H 14 Z m 0,32 H 35 V 64 H 14 Z"
|
||||
id="path56"
|
||||
style="fill:url(#pattern1870)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Img/logo.png
BIN
Img/logo.png
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 1,012 B |
44
Img/logo.svg
Normal file
44
Img/logo.svg
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="341" height="90" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<pattern id="red-stripes" width="341" height="90" patternUnits="userSpaceOnUse">
|
||||
<rect width="341" height="16" fill="#f00"/>
|
||||
<rect y="16" width="341" height="16" fill="#d70000"/>
|
||||
<rect y="32" width="341" height="16" fill="#af0000"/>
|
||||
<rect y="48" width="341" height="16" fill="#870000"/>
|
||||
<rect y="64" width="341" height="16" fill="#5f0000"/>
|
||||
</pattern>
|
||||
<pattern id="gray-stripes" width="341" height="90" patternUnits="userSpaceOnUse">
|
||||
<rect width="341" height="16" fill="#585858"/>
|
||||
<rect y="16" width="341" height="16" fill="#4e4e4e"/>
|
||||
<rect y="32" width="341" height="16" fill="#444"/>
|
||||
<rect y="48" width="341" height="16" fill="#3a3a3a"/>
|
||||
<rect y="64" width="341" height="16" fill="#303030"/>
|
||||
<rect y="80" width="341" height="10" fill="#262626"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g fill="#080808">
|
||||
<path d="m2,7v83h45v-16h7v-19h-7v-13h7v-19h-7v-16h-45zm17,19h18v13h-18v-13zm0,32h18v13h-18v-13z"/>
|
||||
<path d="m58,7v19h21v64h17v-64h21v-19h-59z"/>
|
||||
<path d="m128,7v16h-7v51h7v16h45v-16h7v-51h-7v-16h-45zm10,19h25v45h-25v-45z"/>
|
||||
<path d="m184,7v83h17v-32h28v-16h7v-19h-7v-16h-45zm17,19h18v13h-18v-13z"/>
|
||||
<path d="m261,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17z"/>
|
||||
<path d="m310,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17z"/>
|
||||
</g>
|
||||
<g fill="url(#gray-stripes)">
|
||||
<path d="m2,7v83h45v-16h7v-19h-7v-13h7v-19h-7v-16h-45zm1,1h43v16h7v17h-7v15h7v17h-7v16h-43v-81zm15,17h20v15h-20v-15zm1,1v13h18v-13h-18zm-1,31h20v15h-20v-15zm1,1v13h18v-13h-18zm-15-49v79h41v-16h7v-15h-7v-17h7v-15h-7v-16h-41zm1,1h39v16h7v13h-7v19h7v13h-7v16h-39v-77zm11,13h24v19h-24v-19zm1,1v17h22v-17h-22zm-1,31h24v19h-24v-19zm1,1v17h22v-17h-22z"/>
|
||||
<path d="m58,7v19h21v64h17v-64h21v-19h-59zm1,1h57v17h-21v64h-15v-64h-21v-17zm1,1v15h21v64h13v-64h21v-15h-55zm1,1h53v13h-21v64h-11v-64h-21v-13z"/>
|
||||
<path d="m128,7v16h-7v51h7v16h45v-16h7v-51h-7v-16h-45zm1,1h43v16h7v49h-7v16h-43v-16h-7v-49h7v-16zm9,18v45h25v-45h-25zm-1-1h27v47h-27v-47zm-7-16v16h-7v47h7v16h41v-16h7v-47h-7v-16h-41zm1,1h39v16h7v45h-7v16h-39v-16h-7v-45h7v-16zm5,14v49h29v-49h-29zm-1-1h31v51h-31v-51z"/>
|
||||
<path d="m184,7v83h17v-32h28v-16h7v-19h-7v-16h-45zm1,1h43v16h7v17h-7v16h-28v32h-15v-81zm16,18v13h18v-13h-18zm-1-1h20v15h-20v-15zm-14-16v79h13v-32h28v-16h7v-15h-7v-16h-41zm1,1h39v16h7v13h-7v16h-28v32h-11v-77zm12,14v17h22v-17h-22zm-1-1h24v19h-24v-19z"/>
|
||||
<path d="m261,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17zm1,1h15v16h14v17h-14v16h-15v-16h-14v-17h14v-16zm1,1v16h-14v15h14v16h13v-16h14v-15h-14v-16h-13zm1,1h11v16h14v13h-14v16h-11v-16h-14v-13h14v-16z"/>
|
||||
<path d="m310,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17zm1,1h15v16h14v17h-14v16h-15v-16h-14v-17h14v-16zm1,1v16h-14v15h14v16h13v-16h14v-15h-14v-16h-13zm1,1h11v16h14v13h-14v16h-11v-16h-14v-13h14v-16z"/>
|
||||
</g>
|
||||
<g fill="url(#red-stripes)">
|
||||
<path d="m0,0v80h42v-16h7v-16h-7v-16h7v-16h-7v-16h-42zm14,16h21v16h-21v-16zm0,32h21v16h-21v-16z"/>
|
||||
<path d="m56,0v16h21v64h14v-64h21v-16h-56z"/>
|
||||
<path d="m126,0v16h-7v48h7v16h42v-16h7v-48h-7v-16h-42zm7,16h28v48h-28v-48z"/>
|
||||
<path d="m182,0v80h14v-32h28v-16h7v-16h-7v-16h-42zm14,16h21v16h-21v-16z"/>
|
||||
<path d="m259,16v16h-14v16h14v16h14v-16h14v-16h-14v-16h-14z"/>
|
||||
<path d="m308,16v16h-14v16h14v16h14v-16h14v-16h-14v-16h-14z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
149
Makefile
149
Makefile
|
@ -1,12 +1,18 @@
|
|||
#* Btop++ makefile v1.2
|
||||
#* Btop++ makefile v1.5
|
||||
|
||||
BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.2\033[0m
|
||||
BANNER = \n \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m████████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗ \033[38;5;196m██████\033[38;5;240m╗\n \033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗╚══\033[38;5;160m██\033[38;5;239m╔══╝\033[38;5;160m██\033[38;5;239m╔═══\033[38;5;160m██\033[38;5;239m╗\033[38;5;160m██\033[38;5;239m╔══\033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗ \033[38;5;160m██\033[38;5;239m╗\n \033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║ \033[38;5;124m██\033[38;5;238m║\033[38;5;124m██████\033[38;5;238m╔╝ \033[38;5;124m██████\033[38;5;238m╗\033[38;5;124m██████\033[38;5;238m╗\n \033[38;5;88m██\033[38;5;237m╔══\033[38;5;88m██\033[38;5;237m╗ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║ \033[38;5;88m██\033[38;5;237m║\033[38;5;88m██\033[38;5;237m╔═══╝ ╚═\033[38;5;88m██\033[38;5;237m╔═╝╚═\033[38;5;88m██\033[38;5;237m╔═╝\n \033[38;5;52m██████\033[38;5;236m╔╝ \033[38;5;52m██\033[38;5;236m║ ╚\033[38;5;52m██████\033[38;5;236m╔╝\033[38;5;52m██\033[38;5;236m║ ╚═╝ ╚═╝\n \033[38;5;235m╚═════╝ ╚═╝ ╚═════╝ ╚═╝ \033[1;3;38;5;240mMakefile v1.5\033[0m
|
||||
|
||||
override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown")
|
||||
override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0")
|
||||
override DATESTAMP := $(shell date '+%Y-%m-%d %H:%M:%S' || echo "5 minutes ago")
|
||||
ifeq ($(shell command -v gdate >/dev/null; echo $$?),0)
|
||||
DATE_CMD := gdate
|
||||
else
|
||||
DATE_CMD := date
|
||||
endif
|
||||
|
||||
ifneq ($(QUIET),true)
|
||||
override PRE := info
|
||||
override PRE := info info-quiet
|
||||
override QUIET := false
|
||||
else
|
||||
override PRE := info-quiet
|
||||
|
@ -14,33 +20,56 @@ endif
|
|||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
#? NOTICE! Manually set PLATFORM and ARCH if not compiling for host system
|
||||
#? Detect PLATFORM and ARCH from uname/gcc if not set
|
||||
PLATFORM ?= $(shell uname -s || echo unknown)
|
||||
ARCH ?= $(shell uname -m || echo unknown)
|
||||
ifneq ($(filter unknown Darwin, $(PLATFORM)),)
|
||||
override PLATFORM := $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }')
|
||||
ifeq ($(PLATFORM),apple)
|
||||
override PLATFORM := macos
|
||||
endif
|
||||
endif
|
||||
ifeq ($(shell uname -v | grep ARM64 >/dev/null 2>&1; echo $$?),0)
|
||||
ARCH ?= arm64
|
||||
else
|
||||
ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1)
|
||||
endif
|
||||
|
||||
#? Only enable fcf-protection if on x86_64
|
||||
ifeq ($(ARCH),x86_64)
|
||||
override ADDFLAGS += -fcf-protection
|
||||
override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
#? Any flags added to TESTFLAGS must not contain whitespace for the testing to work
|
||||
override TESTFLAGS := -fexceptions -fstack-clash-protection -fcf-protection
|
||||
ifneq ($(PLATFORM) $(ARCH),macos arm64)
|
||||
override TESTFLAGS += -fstack-protector
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC),true)
|
||||
override ADDFLAGS += -static -static-libgcc -static-libstdc++
|
||||
endif
|
||||
|
||||
#? Make sure PLATFORM Darwin is OSX and not Darwin
|
||||
ifeq ($(PLATFORM),Darwin)
|
||||
ifeq ($(shell sw_vers >/dev/null 2>&1; echo $$?),0)
|
||||
PLATFORM := OSX
|
||||
override ADDFLAGS += -static-libgcc -static-libstdc++
|
||||
ifneq ($(PLATFORM),macos)
|
||||
override ADDFLAGS += -DSTATIC_BUILD -static -Wl,--fatal-warnings
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(STRIP),true)
|
||||
override ADDFLAGS += -s
|
||||
endif
|
||||
|
||||
#? Compiler and Linker
|
||||
CXX ?= g++
|
||||
ifeq ($(shell command -v g++-11 >/dev/null; echo $$?),0)
|
||||
CXX := g++-11
|
||||
else ifeq ($(shell command -v g++11 >/dev/null; echo $$?),0)
|
||||
CXX := g++11
|
||||
else ifeq ($(shell command -v g++ >/dev/null; echo $$?),0)
|
||||
CXX := g++
|
||||
endif
|
||||
override CXX_VERSION := $(shell $(CXX) -dumpfullversion -dumpversion || echo 0)
|
||||
|
||||
#? Try to make sure we are using GCC/G++ version 11 or later if not instructed to use g++-10
|
||||
ifeq ($(CXX),g++)
|
||||
V_MAJOR := $(shell echo $(CXX_VERSION) | cut -f1 -d".")
|
||||
ifeq ($(shell g++ --version | grep clang >/dev/null 2>&1; echo $$?),0)
|
||||
V_MAJOR := 0
|
||||
else
|
||||
V_MAJOR := $(shell echo $(CXX_VERSION) | cut -f1 -d".")
|
||||
endif
|
||||
ifneq ($(shell test $(V_MAJOR) -ge 11; echo $$?),0)
|
||||
ifeq ($(shell command -v g++-11 >/dev/null; echo $$?),0)
|
||||
override CXX := g++-11
|
||||
|
@ -50,21 +79,27 @@ ifeq ($(CXX),g++)
|
|||
endif
|
||||
|
||||
#? Pull in platform specific source files and get thread count
|
||||
ifeq ($(PLATFORM),Linux)
|
||||
ifeq ($(PLATFORM_LC),linux)
|
||||
PLATFORM_DIR := linux
|
||||
THREADS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)
|
||||
else ifeq ($(PLATFORM),FreeBSD)
|
||||
SU_GROUP := root
|
||||
else ifeq ($(PLATFORM_LC),freebsd)
|
||||
PLATFORM_DIR := freebsd
|
||||
THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1)
|
||||
else ifeq ($(PLATFORM),OSX)
|
||||
SU_GROUP := wheel
|
||||
override ADDFLAGS += -lstdc++ -lm -lkvm -ldevstat -Wl,-rpath=/usr/local/lib/gcc11
|
||||
export MAKE = gmake
|
||||
else ifeq ($(PLATFORM_LC),macos)
|
||||
PLATFORM_DIR := osx
|
||||
THREADS := $(shell sysctl -n hw.ncpu || echo 1)
|
||||
override ADDFLAGS += -framework IOKit -framework CoreFoundation -Wno-format-truncation
|
||||
SU_GROUP := wheel
|
||||
else
|
||||
$(error $(shell printf "\033[1;91mERROR: \033[97mUnsupported platform ($(PLATFORM))\033[0m"))
|
||||
endif
|
||||
|
||||
#? Use all CPU cores (will only be set if using Make 4.3+)
|
||||
MAKEFLAGS := --jobs=$(THREADS)
|
||||
MAKEFLAGS := --jobs=$(THREADS)
|
||||
ifeq ($(THREADS),1)
|
||||
override THREADS := auto
|
||||
endif
|
||||
|
@ -78,23 +113,47 @@ SRCEXT := cpp
|
|||
DEPEXT := d
|
||||
OBJEXT := o
|
||||
|
||||
#? Filter out unsupported compiler flags
|
||||
override GOODFLAGS := $(foreach flag,$(TESTFLAGS),$(strip $(shell echo "int main() {}" | $(CXX) -o /dev/null $(flag) -x c++ - >/dev/null 2>&1 && echo $(flag) || true)))
|
||||
|
||||
#? Flags, Libraries and Includes
|
||||
override REQFLAGS := -std=c++20
|
||||
WARNFLAGS := -Wall -Wextra -pedantic
|
||||
OPTFLAGS ?= -O2 -ftree-loop-vectorize -flto=$(THREADS)
|
||||
LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector -fstack-clash-protection $(ADDFLAGS)
|
||||
OPTFLAGS := -O2 -ftree-loop-vectorize -flto=$(THREADS)
|
||||
LDCXXFLAGS := -pthread -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS $(GOODFLAGS) $(ADDFLAGS)
|
||||
override CXXFLAGS += $(REQFLAGS) $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
|
||||
override LDFLAGS += $(LDCXXFLAGS) $(OPTFLAGS) $(WARNFLAGS)
|
||||
INC := -I$(INCDIR) -I$(SRCDIR)
|
||||
SU_USER := root
|
||||
SU_GROUP := root
|
||||
|
||||
SOURCES := $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT))
|
||||
ifdef DEBUG
|
||||
override OPTFLAGS := -O0 -g
|
||||
endif
|
||||
|
||||
SOURCES += $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT))
|
||||
SOURCES := $(sort $(shell find $(SRCDIR) -maxdepth 1 -type f -name *.$(SRCEXT)))
|
||||
|
||||
SOURCES += $(sort $(shell find $(SRCDIR)/$(PLATFORM_DIR) -type f -name *.$(SRCEXT)))
|
||||
|
||||
#? Setup percentage progress
|
||||
SOURCE_COUNT := $(words $(SOURCES))
|
||||
|
||||
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
|
||||
|
||||
ifeq ($(shell find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o >/dev/null 2>&1; echo $$?),0)
|
||||
ifneq ($(wildcard $(BUILDDIR)/.*),)
|
||||
SKIPPED_SOURCES := $(foreach fname,$(SOURCES),$(shell find $(BUILDDIR) -type f -newer $(fname) -name *.o | grep "$(basename $(notdir $(fname))).o" 2>/dev/null))
|
||||
override SOURCE_COUNT := $(shell expr $(SOURCE_COUNT) - $(words $(SKIPPED_SOURCES)))
|
||||
ifeq ($(SOURCE_COUNT),0)
|
||||
override SOURCE_COUNT = $(words $(SOURCES))
|
||||
endif
|
||||
endif
|
||||
PROGRESS = expr $$(find $(BUILDDIR) -type f -newermt "$(DATESTAMP)" -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2
|
||||
else
|
||||
PROGRESS = expr $$(find $(BUILDDIR) -type f -name *.o | wc -l || echo 1) '*' 90 / $(SOURCE_COUNT) | cut -c1-2
|
||||
endif
|
||||
|
||||
P := %%
|
||||
|
||||
#? Default Make
|
||||
all: $(PRE) directories btop
|
||||
|
||||
|
@ -111,10 +170,8 @@ info:
|
|||
@printf "\033[1;95mCXXFLAGS \033[1;92m+| \033[0;37m\$$(\033[92mREQFLAGS\033[37m) \$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n"
|
||||
@printf "\033[1;95mLDFLAGS \033[1;92m+| \033[0;37m\$$(\033[93mLDCXXFLAGS\033[37m) \$$(\033[94mOPTFLAGS\033[37m) \$$(\033[91mWARNFLAGS\033[37m)\n"
|
||||
|
||||
@printf "\n\033[1;92mBuilding btop++ \033[93m(\033[97mv$(BTOP_VERSION)\033[93m)\033[0m\n"
|
||||
|
||||
info-quiet:
|
||||
|
||||
@sleep 0.1 2>/dev/null || true
|
||||
@printf "\n\033[1;92mBuilding btop++ \033[91m(\033[97mv$(BTOP_VERSION)\033[91m) \033[93m$(PLATFORM) \033[96m$(ARCH)\033[0m\n"
|
||||
|
||||
help:
|
||||
|
@ -128,6 +185,7 @@ help:
|
|||
@printf " install Install btop++ to \$$PREFIX ($(PREFIX))\n"
|
||||
@printf " setuid Set installed binary owner/group to \$$SU_USER/\$$SU_GROUP ($(SU_USER)/$(SU_GROUP)) and set SUID bit\n"
|
||||
@printf " uninstall Uninstall btop++ from \$$PREFIX\n"
|
||||
@printf " info Display information about Environment,compiler and linker flags\n"
|
||||
|
||||
#? Make the Directories
|
||||
directories:
|
||||
|
@ -154,6 +212,16 @@ install:
|
|||
@cp -p README.md $(DESTDIR)$(PREFIX)/share/btop
|
||||
@printf "\033[1;92mInstalling themes to: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop/themes\033[0m\n"
|
||||
@cp -pr themes $(DESTDIR)$(PREFIX)/share/btop
|
||||
@printf "\033[1;92mInstalling desktop entry to: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\n"
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/share/applications/
|
||||
@cp -p btop.desktop $(DESTDIR)$(PREFIX)/share/applications/btop.desktop
|
||||
@printf "\033[1;92mInstalling PNG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\n"
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps
|
||||
@cp -p Img/icon.png $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png
|
||||
@printf "\033[1;92mInstalling SVG icon to: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\n"
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps
|
||||
@cp -p Img/icon.svg $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg
|
||||
|
||||
|
||||
#? Set SUID bit for btop as $SU_USER in $SU_GROUP
|
||||
setuid:
|
||||
|
@ -168,6 +236,12 @@ uninstall:
|
|||
@rm -rf $(DESTDIR)$(PREFIX)/bin/btop
|
||||
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/btop\033[0m\n"
|
||||
@rm -rf $(DESTDIR)$(PREFIX)/share/btop
|
||||
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/applications/btop.desktop\033[0m\n"
|
||||
@rm -rf $(DESTDIR)$(PREFIX)/share/applications/btop.desktop
|
||||
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png\033[0m\n"
|
||||
@rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/48x48/apps/btop.png
|
||||
@printf "\033[1;91mRemoving: \033[1;97m$(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg\033[0m\n"
|
||||
@rm -rf $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/btop.svg
|
||||
|
||||
#? Pull in dependency info for *existing* .o files
|
||||
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
|
||||
|
@ -175,26 +249,21 @@ uninstall:
|
|||
#? Link
|
||||
.ONESHELL:
|
||||
btop: $(OBJECTS)
|
||||
@sleep 0.1 2>/dev/null || true
|
||||
@sleep 0.2 2>/dev/null || true
|
||||
@TSTAMP=$$(date +%s 2>/dev/null || echo "0")
|
||||
@$(QUIET) || printf "\n\033[1;92mLinking and optimizing binary\033[37m...\033[0m\n"
|
||||
@$(CXX) -o $(TARGETDIR)/btop $^ $(LDFLAGS) || exit 1
|
||||
@printf "\033[1;92m-> \033[1;37m$(TARGETDIR)/btop \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
|
||||
printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n"
|
||||
@printf "\033[1;92m100$(P) -> \033[1;37m$(TARGETDIR)/btop \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $(TARGETDIR)/btop | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
|
||||
@printf "\n\033[1;92mBuild complete in \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $(TIMESTAMP) 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo "unknown")\033[92m)\033[0m\n"
|
||||
|
||||
#? Compile
|
||||
.ONESHELL:
|
||||
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
|
||||
@sleep 0.1 2>/dev/null || true
|
||||
@sleep 0.3 2>/dev/null || true
|
||||
@TSTAMP=$$(date +%s 2>/dev/null || echo "0")
|
||||
@$(QUIET) || printf "\033[1;97mCompiling $<\033[0m\n"
|
||||
@$(CXX) $(CXXFLAGS) $(INC) -c -o $@ $< || exit 1
|
||||
@$(CXX) $(CXXFLAGS) $(INC) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT) >/dev/null || exit 1
|
||||
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
|
||||
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
|
||||
@printf "\033[1;92m-> \033[1;37m$@ \033[100D\033[35C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$(date -d @$$(expr $$(date +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
|
||||
@$(CXX) $(CXXFLAGS) $(INC) -MMD -c -o $@ $< || exit 1
|
||||
@printf "\033[1;92m$$($(PROGRESS))$(P)\033[10D\033[5C-> \033[1;37m$@ \033[100D\033[38C\033[1;93m(\033[1;97m$$(du -ah $@ | cut -f1)iB\033[1;93m) \033[92m(\033[97m$$($(DATE_CMD) -d @$$(expr $$($(DATE_CMD) +%s 2>/dev/null || echo "0") - $${TSTAMP} 2>/dev/null) -u +%Mm:%Ss 2>/dev/null | sed 's/^00m://' || echo '')\033[92m)\033[0m\n"
|
||||
|
||||
#? Non-File Targets
|
||||
.PHONY: all msg help pre
|
||||
|
|
327
README.md
327
README.md
|
@ -5,17 +5,20 @@
|
|||
</a>
|
||||
|
||||
![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux)
|
||||
![OSX](https://img.shields.io/badge/-OSX-black?logo=apple)
|
||||
![FreeBSD](https://img.shields.io/badge/-FreeBSD-red?logo=freebsd)
|
||||
![Usage](https://img.shields.io/badge/Usage-System%20resource%20monitor-yellow)
|
||||
![c++20](https://img.shields.io/badge/cpp-c%2B%2B20-green)
|
||||
![btop_version](https://img.shields.io/github/v/tag/aristocratos/btop?label=version)
|
||||
![latest_release](https://img.shields.io/github/v/tag/aristocratos/btop?label=release)
|
||||
[![Donate](https://img.shields.io/badge/-Donate-yellow?logo=paypal)](https://paypal.me/aristocratos)
|
||||
[![Sponsor](https://img.shields.io/badge/-Sponsor-red?logo=github)](https://github.com/sponsors/aristocratos)
|
||||
[![Coffee](https://img.shields.io/badge/-Buy%20me%20a%20Coffee-grey?logo=Ko-fi)](https://ko-fi.com/aristocratos)
|
||||
[![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop)
|
||||
[![Continuous Build Linux](https://github.com/aristocratos/btop/actions/workflows/continuous-build-linux.yml/badge.svg)](https://github.com/aristocratos/btop/actions/workflows/continuous-build-linux.yml)
|
||||
[![Continuous Build MacOS](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml/badge.svg)](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml)
|
||||
|
||||
## Index
|
||||
|
||||
|
||||
|
||||
* [News](#news)
|
||||
* [Documents](#documents)
|
||||
* [Description](#description)
|
||||
|
@ -25,15 +28,67 @@
|
|||
* [Prerequisites](#prerequisites) (Read this if you are having issues!)
|
||||
* [Screenshots](#screenshots)
|
||||
* [Keybindings](#help-menu)
|
||||
* [Installation](#installation)
|
||||
* [Manual compilation](#compilation)
|
||||
* [Install the snap](#install-the-snap)
|
||||
* [Installation Linux/OSX](#installation)
|
||||
* [Compilation Linux](#compilation-linux)
|
||||
* [Compilation OSX](#compilation-osx)
|
||||
* [Compilation FreeBSD](#compilation-freebsd)
|
||||
* [Installing the snap](#installing-the-snap)
|
||||
* [Configurability](#configurability)
|
||||
* [License](#license)
|
||||
|
||||
## News
|
||||
|
||||
### Under development
|
||||
##### 16 January 2022
|
||||
|
||||
Release v1.2.0 with FreeBSD support. No release binaries for FreeBSD provided as of yet.
|
||||
|
||||
Again a big thanks to [@joske](https://github.com/joske) for his porting efforts!
|
||||
|
||||
Since compatibility with Linux, MacOS and FreeBSD are done, the focus going forward will be on new features like GPU monitoring.
|
||||
|
||||
##### 13 November 2021
|
||||
|
||||
Release v1.1.0 with OSX support. Binaries in [continuous-build-macos](https://github.com/aristocratos/btop/actions/workflows/continuous-build-macos.yml) are only x86 for now.
|
||||
Macos binaries + installer are included for both x86 and ARM64 (Apple Silicon) in the releases.
|
||||
|
||||
Big thank you to [@joske](https://github.com/joske) who wrote the vast majority of the implementation!
|
||||
|
||||
<details>
|
||||
<summary>More...</summary>
|
||||
|
||||
##### 30 October 2021
|
||||
|
||||
Work on the OSX and FreeBSD branches, both initiated and mostly worked on by [@joske](https://github.com/joske), will likely be completed in the coming weeks.
|
||||
The OSX branch has some memory leaks that needs to be sorted out and both have some issues with the processes cpu usage calculation and other smaller issues that needs fixing.
|
||||
|
||||
If you want to help out, test for bugs/fix bugs or just try out the branches:
|
||||
|
||||
**OSX**
|
||||
```bash
|
||||
# Install and use Homebrew or MacPorts package managers for easy dependency installation
|
||||
brew install coreutils make gcc@11
|
||||
git clone https://github.com/aristocratos/btop.git
|
||||
cd btop
|
||||
git checkout OSX
|
||||
gmake
|
||||
```
|
||||
|
||||
**FreeBSD**
|
||||
```bash
|
||||
sudo pkg install gmake gcc11 coreutils git
|
||||
git clone https://github.com/aristocratos/btop.git
|
||||
cd btop
|
||||
git checkout freebsd
|
||||
gmake
|
||||
```
|
||||
|
||||
Note that GNU make (`gmake`) is recommended but not required for OSX but it is required on FreeBSD.
|
||||
|
||||
|
||||
##### 6 October 2021
|
||||
|
||||
OsX development have been started by [@joske](https://github.com/joske), big thanks :)
|
||||
See branch [OSX](https://github.com/aristocratos/btop/tree/OSX) for current progress.
|
||||
|
||||
##### 18 September 2021
|
||||
|
||||
|
@ -59,6 +114,8 @@ Windows support is not in the plans as of now, but if anyone else wants to take
|
|||
This project is gonna take some time until it has complete feature parity with bpytop, since all system information gathering will have to be written from scratch without any external libraries.
|
||||
And will need some help in the form of code contributions to get complete support for BSD and OSX.
|
||||
|
||||
</details>
|
||||
|
||||
## Documents
|
||||
|
||||
**[CHANGELOG.md](CHANGELOG.md)**
|
||||
|
@ -114,7 +171,7 @@ Any support is greatly appreciated!
|
|||
|
||||
For best experience, a terminal with support for:
|
||||
|
||||
* 24-bit truecolor ([See list of terminals with truecolor support](https://gist.github.com/XVilka/8346728))
|
||||
* 24-bit truecolor ([See list of terminals with truecolor support](https://github.com//termstandard/colors))
|
||||
* 256-color terminals are supported through 24-bit to 256-color conversion when setting "truecolor" to False in the options or with "-lc/--low-color" arguments.
|
||||
* 16 color TTY mode will be activated if a real tty device is detected. Can be forced with "-t/--tty_on" arguments.
|
||||
* Wide characters (Are sometimes problematic in web-based terminals)
|
||||
|
@ -167,9 +224,11 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
## Installation
|
||||
|
||||
**Binary release (statically compiled, for kernel 3.2.0 and newer)**
|
||||
**Binaries for Linux are statically compiled with musl and works on kernel 2.6.39 and newer**
|
||||
|
||||
1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder**
|
||||
1. **Download btop-(VERSION)-(ARCH)-(PLATFORM).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder**
|
||||
|
||||
**Notice! Use x86_64 for 64-bit x86 systems, i486 and i686 are 32-bit!**
|
||||
|
||||
2. **Install (from created folder)**
|
||||
|
||||
|
@ -207,17 +266,37 @@ Also needs a UTF8 locale and a font that covers:
|
|||
make help
|
||||
```
|
||||
|
||||
## Compilation
|
||||
**Binary release (from native os repo)**
|
||||
|
||||
* **openSUSE**
|
||||
* **Tumbleweed:**
|
||||
```bash
|
||||
sudo zypper in btop
|
||||
```
|
||||
* For all other versions, see [openSUSE Software: btop](https://software.opensuse.org/package/btop)
|
||||
|
||||
|
||||
**Binary release on Homebrew (macOS (x86_64 & ARM64) / Linux (x86_64))**
|
||||
|
||||
* **[Homebrew](https://formulae.brew.sh/formula/btop)**
|
||||
```bash
|
||||
brew install btop
|
||||
```
|
||||
|
||||
## Compilation Linux
|
||||
|
||||
Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary).
|
||||
|
||||
The makefile also needs GNU coreutils and `sed` (should already be installed on any modern distribution).
|
||||
|
||||
For a `cmake` based build alternative see the [fork](https://github.com/jan-guenter/btop/tree/main) by @jan-guenter
|
||||
|
||||
1. **Install dependencies (example for Ubuntu 21.04 Hirsute)**
|
||||
|
||||
Use gcc-10 g++-10 if gcc-11 isn't available
|
||||
|
||||
``` bash
|
||||
sudo apt install coreutils sed git build-essential gcc-11 g++-11
|
||||
# use gcc-10 g++-10 if gcc-11 isn't available
|
||||
```
|
||||
|
||||
2. **Clone repository**
|
||||
|
@ -231,13 +310,20 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
Append `STATIC=true` to `make` command for static compilation.
|
||||
|
||||
Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users if compiling statically with glibc.
|
||||
|
||||
Append `QUIET=true` for less verbose output.
|
||||
|
||||
Notice! Manually set `$ARCH` variable if cross-compiling
|
||||
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
|
||||
|
||||
Append `ARCH=<architecture>` to manually set the target architecture.
|
||||
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
|
||||
|
||||
Use `ADDFLAGS` variable for appending flags to both compiler and linker.
|
||||
|
||||
For example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
|
||||
For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
|
||||
|
||||
If `g++` is linked to an older version of gcc on your system specify the correct version by appending `CXX=g++-10` or `CXX=g++-11`.
|
||||
|
||||
``` bash
|
||||
make
|
||||
|
@ -245,9 +331,11 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
4. **Install**
|
||||
|
||||
Append `PREFIX=/target/dir` to set target, default: `/usr/local`
|
||||
|
||||
Notice! Only use "sudo" when installing to a NON user owned directory.
|
||||
|
||||
``` bash
|
||||
# use "make install PREFIX=/target/dir" to set target, default: /usr/local
|
||||
# only use "sudo" when installing to a NON user owned directory
|
||||
sudo make install
|
||||
```
|
||||
|
||||
|
@ -255,9 +343,11 @@ Also needs a UTF8 locale and a font that covers:
|
|||
|
||||
No need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems.
|
||||
|
||||
Run after make install and use same PREFIX if any was used at install.
|
||||
|
||||
Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `root`
|
||||
|
||||
``` bash
|
||||
# run after make install and use same PREFIX if any was used at install
|
||||
# set SU_USER and SU_GROUP to select user and group, default is root:root
|
||||
sudo make setuid
|
||||
```
|
||||
|
||||
|
@ -285,7 +375,177 @@ Also needs a UTF8 locale and a font that covers:
|
|||
make help
|
||||
```
|
||||
|
||||
## Install the snap
|
||||
## Compilation OSX
|
||||
|
||||
Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary).
|
||||
|
||||
The makefile also needs GNU coreutils and `sed`.
|
||||
|
||||
Install and use Homebrew or MacPorts package managers for easy dependency installation
|
||||
|
||||
1. **Install dependencies (example for Homebrew)**
|
||||
|
||||
``` bash
|
||||
brew install coreutils make gcc@11
|
||||
```
|
||||
|
||||
2. **Clone repository**
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/aristocratos/btop.git
|
||||
cd btop
|
||||
```
|
||||
|
||||
3. **Compile**
|
||||
|
||||
Append `STATIC=true` to `make` command for static compilation (only libgcc and libstdc++ will be static!).
|
||||
|
||||
Append `QUIET=true` for less verbose output.
|
||||
|
||||
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
|
||||
|
||||
Append `ARCH=<architecture>` to manually set the target architecture.
|
||||
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
|
||||
|
||||
Use `ADDFLAGS` variable for appending flags to both compiler and linker.
|
||||
|
||||
For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
|
||||
|
||||
``` bash
|
||||
gmake
|
||||
```
|
||||
|
||||
4. **Install**
|
||||
|
||||
Append `PREFIX=/target/dir` to set target, default: `/usr/local`
|
||||
|
||||
Notice! Only use "sudo" when installing to a NON user owned directory.
|
||||
|
||||
``` bash
|
||||
sudo gmake install
|
||||
```
|
||||
|
||||
5. **(Recommended) Set suid bit to make btop always run as root (or other user)**
|
||||
|
||||
No need for `sudo` to see information for non user owned processes and to enable signal sending to any process.
|
||||
|
||||
Run after make install and use same PREFIX if any was used at install.
|
||||
|
||||
Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `wheel`
|
||||
|
||||
``` bash
|
||||
sudo gmake setuid
|
||||
```
|
||||
|
||||
* **Uninstall**
|
||||
|
||||
``` bash
|
||||
sudo gmake uninstall
|
||||
```
|
||||
|
||||
* **Remove any object files from source dir**
|
||||
|
||||
```bash
|
||||
gmake clean
|
||||
```
|
||||
|
||||
* **Remove all object files, binaries and created directories in source dir**
|
||||
|
||||
```bash
|
||||
gmake distclean
|
||||
```
|
||||
|
||||
* **Show help**
|
||||
|
||||
```bash
|
||||
gmake help
|
||||
```
|
||||
|
||||
## Compilation FreeBSD
|
||||
|
||||
Needs GCC 10 or higher, (GCC 11 or above strongly recommended for better CPU efficiency in the compiled binary).
|
||||
|
||||
Note that GNU make (`gmake`) is required to compile on FreeBSD.
|
||||
|
||||
1. **Install dependencies**
|
||||
|
||||
``` bash
|
||||
sudo pkg install gmake gcc11 coreutils git
|
||||
```
|
||||
|
||||
2. **Clone repository**
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/aristocratos/btop.git
|
||||
cd btop
|
||||
```
|
||||
|
||||
3. **Compile**
|
||||
|
||||
Append `STATIC=true` to `make` command for static compilation.
|
||||
|
||||
Append `QUIET=true` for less verbose output.
|
||||
|
||||
Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag).
|
||||
|
||||
Append `ARCH=<architecture>` to manually set the target architecture.
|
||||
If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system.
|
||||
|
||||
Use `ADDFLAGS` variable for appending flags to both compiler and linker.
|
||||
|
||||
For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system.
|
||||
|
||||
``` bash
|
||||
gmake
|
||||
```
|
||||
|
||||
4. **Install**
|
||||
|
||||
Append `PREFIX=/target/dir` to set target, default: `/usr/local`
|
||||
|
||||
Notice! Only use "sudo" when installing to a NON user owned directory.
|
||||
|
||||
``` bash
|
||||
sudo gmake install
|
||||
```
|
||||
|
||||
5. **(Recommended) Set suid bit to make btop always run as root (or other user)**
|
||||
|
||||
No need for `sudo` to see information for non user owned processes and to enable signal sending to any process.
|
||||
|
||||
Run after make install and use same PREFIX if any was used at install.
|
||||
|
||||
Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `wheel`
|
||||
|
||||
``` bash
|
||||
sudo gmake setuid
|
||||
```
|
||||
|
||||
* **Uninstall**
|
||||
|
||||
``` bash
|
||||
sudo gmake uninstall
|
||||
```
|
||||
|
||||
* **Remove any object files from source dir**
|
||||
|
||||
```bash
|
||||
gmake clean
|
||||
```
|
||||
|
||||
* **Remove all object files, binaries and created directories in source dir**
|
||||
|
||||
```bash
|
||||
gmake distclean
|
||||
```
|
||||
|
||||
* **Show help**
|
||||
|
||||
```bash
|
||||
gmake help
|
||||
```
|
||||
|
||||
## Installing the snap
|
||||
[![btop](https://snapcraft.io/btop/badge.svg)](https://snapcraft.io/btop)
|
||||
|
||||
* **Install the snap**
|
||||
|
@ -297,7 +557,7 @@ Also needs a UTF8 locale and a font that covers:
|
|||
```
|
||||
sudo snap install btop --edge
|
||||
```
|
||||
|
||||
|
||||
* **Connect the interface**
|
||||
|
||||
```bash
|
||||
|
@ -310,17 +570,17 @@ Also needs a UTF8 locale and a font that covers:
|
|||
All options changeable from within UI.
|
||||
Config and log files stored in `$XDG_CONFIG_HOME/btop` or `$HOME/.config/btop` folder
|
||||
|
||||
#### btop.cfg: (auto generated if not found)
|
||||
#### btop.conf: (auto generated if not found)
|
||||
|
||||
```bash
|
||||
#? Config file for btop v. 0.1.0
|
||||
#? Config file for btop v. 1.2.2
|
||||
|
||||
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
|
||||
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
|
||||
color_theme = "Default"
|
||||
|
||||
#* If the theme set background should be shown, set to False if you want terminal background transparency.
|
||||
theme_background = False
|
||||
theme_background = True
|
||||
|
||||
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
|
||||
truecolor = True
|
||||
|
@ -330,11 +590,15 @@ truecolor = True
|
|||
force_tty = False
|
||||
|
||||
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
|
||||
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positons, G=graph symbol to use for box.
|
||||
#* Use withespace " " as seprator between different presets.
|
||||
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
|
||||
#* Use withespace " " as separator between different presets.
|
||||
#* Example: "cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty"
|
||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"
|
||||
|
||||
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
|
||||
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
|
||||
vim_keys = False
|
||||
|
||||
#* Rounded corners on boxes, is ignored if TTY mode is ON.
|
||||
rounded_corners = True
|
||||
|
||||
|
@ -358,10 +622,10 @@ graph_symbol_net = "default"
|
|||
graph_symbol_proc = "default"
|
||||
|
||||
#* Manually set which boxes to show. Available values are "cpu mem net proc", separate values with whitespace.
|
||||
shown_boxes = "cpu mem net proc"
|
||||
shown_boxes = "proc cpu mem net"
|
||||
|
||||
#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs.
|
||||
update_ms = 2000
|
||||
update_ms = 1500
|
||||
|
||||
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu responsive",
|
||||
#* "cpu lazy" sorts top process over time (easier to follow), "cpu responsive" updates top process directly.
|
||||
|
@ -429,6 +693,9 @@ cpu_core_map = ""
|
|||
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine".
|
||||
temp_scale = "celsius"
|
||||
|
||||
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
|
||||
base_10_sizes = False
|
||||
|
||||
#* Show CPU frequency.
|
||||
show_cpu_freq = True
|
||||
|
||||
|
@ -467,6 +734,9 @@ only_physical = True
|
|||
#* Read disks list from /etc/fstab. This also disables only_physical.
|
||||
use_fstab = False
|
||||
|
||||
#* Set to true to show available disk space for privileged users.
|
||||
disk_free_priv = False
|
||||
|
||||
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
|
||||
show_io_stat = True
|
||||
|
||||
|
@ -497,6 +767,9 @@ net_iface = "br0"
|
|||
#* Show battery stats in top right if battery is present.
|
||||
show_battery = True
|
||||
|
||||
#* Which battery to use if multiple are present. "Auto" for auto detection.
|
||||
selected_battery = "Auto"
|
||||
|
||||
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
|
||||
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
|
||||
log_level = "DEBUG"
|
||||
|
|
13
btop.desktop
Normal file
13
btop.desktop
Normal file
|
@ -0,0 +1,13 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Version=1.0
|
||||
Name=btop++
|
||||
GenericName=System Monitor
|
||||
GenericName[it]=Monitor di sistema
|
||||
Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes
|
||||
Comment[it]=Monitoraggio delle risorse: mostra utilizzo e statistiche per CPU, dischi, rete e processi
|
||||
Icon=btop
|
||||
Exec=btop
|
||||
Terminal=true
|
||||
Categories=System;Monitor;ConsoleOnly;
|
||||
Keywords=system;process;task
|
|
@ -36,7 +36,7 @@
|
|||
// see https://semver.org/
|
||||
#define ROBIN_HOOD_VERSION_MAJOR 3 // for incompatible API changes
|
||||
#define ROBIN_HOOD_VERSION_MINOR 11 // for adding functionality in a backwards-compatible manner
|
||||
#define ROBIN_HOOD_VERSION_PATCH 3 // for backwards-compatible bug fixes
|
||||
#define ROBIN_HOOD_VERSION_PATCH 5 // for backwards-compatible bug fixes
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
@ -1820,6 +1820,12 @@ public:
|
|||
InsertionState::key_found != idxAndState.second);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
iterator emplace_hint(const_iterator position, Args&&... args) {
|
||||
(void)position;
|
||||
return emplace(std::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::pair<iterator, bool> try_emplace(const key_type& key, Args&&... args) {
|
||||
return try_emplace_impl(key, std::forward<Args>(args)...);
|
||||
|
@ -1831,16 +1837,15 @@ public:
|
|||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::pair<iterator, bool> try_emplace(const_iterator hint, const key_type& key,
|
||||
Args&&... args) {
|
||||
iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args) {
|
||||
(void)hint;
|
||||
return try_emplace_impl(key, std::forward<Args>(args)...);
|
||||
return try_emplace_impl(key, std::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
std::pair<iterator, bool> try_emplace(const_iterator hint, key_type&& key, Args&&... args) {
|
||||
iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args) {
|
||||
(void)hint;
|
||||
return try_emplace_impl(std::move(key), std::forward<Args>(args)...);
|
||||
return try_emplace_impl(std::move(key), std::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
template <typename Mapped>
|
||||
|
@ -1854,16 +1859,15 @@ public:
|
|||
}
|
||||
|
||||
template <typename Mapped>
|
||||
std::pair<iterator, bool> insert_or_assign(const_iterator hint, const key_type& key,
|
||||
Mapped&& obj) {
|
||||
iterator insert_or_assign(const_iterator hint, const key_type& key, Mapped&& obj) {
|
||||
(void)hint;
|
||||
return insertOrAssignImpl(key, std::forward<Mapped>(obj));
|
||||
return insertOrAssignImpl(key, std::forward<Mapped>(obj)).first;
|
||||
}
|
||||
|
||||
template <typename Mapped>
|
||||
std::pair<iterator, bool> insert_or_assign(const_iterator hint, key_type&& key, Mapped&& obj) {
|
||||
iterator insert_or_assign(const_iterator hint, key_type&& key, Mapped&& obj) {
|
||||
(void)hint;
|
||||
return insertOrAssignImpl(std::move(key), std::forward<Mapped>(obj));
|
||||
return insertOrAssignImpl(std::move(key), std::forward<Mapped>(obj)).first;
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& keyval) {
|
||||
|
@ -1871,10 +1875,20 @@ public:
|
|||
return emplace(keyval);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& keyval) {
|
||||
(void)hint;
|
||||
return emplace(keyval).first;
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(value_type&& keyval) {
|
||||
return emplace(std::move(keyval));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& keyval) {
|
||||
(void)hint;
|
||||
return emplace(std::move(keyval)).first;
|
||||
}
|
||||
|
||||
// Returns 1 if key is found, 0 otherwise.
|
||||
size_t count(const key_type& key) const { // NOLINT(modernize-use-nodiscard)
|
||||
ROBIN_HOOD_TRACE(this)
|
||||
|
@ -2308,13 +2322,14 @@ private:
|
|||
|
||||
auto const numElementsWithBuffer = calcNumElementsWithBuffer(max_elements);
|
||||
|
||||
// calloc also zeroes everything
|
||||
// malloc & zero mInfo. Faster than calloc everything.
|
||||
auto const numBytesTotal = calcNumBytesTotal(numElementsWithBuffer);
|
||||
ROBIN_HOOD_LOG("std::calloc " << numBytesTotal << " = calcNumBytesTotal("
|
||||
<< numElementsWithBuffer << ")")
|
||||
mKeyVals = reinterpret_cast<Node*>(
|
||||
detail::assertNotNull<std::bad_alloc>(std::calloc(1, numBytesTotal)));
|
||||
detail::assertNotNull<std::bad_alloc>(std::malloc(numBytesTotal)));
|
||||
mInfo = reinterpret_cast<uint8_t*>(mKeyVals + numElementsWithBuffer);
|
||||
std::memset(mInfo, 0, numBytesTotal - numElementsWithBuffer * sizeof(Node));
|
||||
|
||||
// set sentinel
|
||||
mInfo[numElementsWithBuffer] = 1;
|
||||
|
|
1491
include/widechar_width.hpp
Normal file
1491
include/widechar_width.hpp
Normal file
File diff suppressed because it is too large
Load diff
11
snap/gui/btop.desktop
Normal file
11
snap/gui/btop.desktop
Normal file
|
@ -0,0 +1,11 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Version=1.0
|
||||
Name=btop++
|
||||
GenericName=System Monitor
|
||||
Comment=Resource monitor that shows usage and stats for processor, memory, disks, network and processes
|
||||
Icon=${SNAP}/meta/gui/icon.svg
|
||||
Exec=btop
|
||||
Terminal=true
|
||||
Categories=System;Monitor;ConsoleOnly;
|
||||
Keywords=system;process;task
|
111
snap/gui/icon.svg
Normal file
111
snap/gui/icon.svg
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="90"
|
||||
height="90"
|
||||
version="1.1"
|
||||
id="svg70"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs26">
|
||||
<pattern
|
||||
xlink:href="#gray-stripes"
|
||||
id="pattern1888" />
|
||||
<pattern
|
||||
xlink:href="#red-stripes"
|
||||
id="pattern1870" />
|
||||
<pattern
|
||||
id="red-stripes"
|
||||
width="341"
|
||||
height="90"
|
||||
patternUnits="userSpaceOnUse">
|
||||
<rect
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#f00"
|
||||
id="rect2" />
|
||||
<rect
|
||||
y="16"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#d70000"
|
||||
id="rect4" />
|
||||
<rect
|
||||
y="32"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#af0000"
|
||||
id="rect6" />
|
||||
<rect
|
||||
y="48"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#870000"
|
||||
id="rect8" />
|
||||
<rect
|
||||
y="64"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#5f0000"
|
||||
id="rect10" />
|
||||
</pattern>
|
||||
<pattern
|
||||
id="gray-stripes"
|
||||
width="341"
|
||||
height="90"
|
||||
patternUnits="userSpaceOnUse">
|
||||
<rect
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#585858"
|
||||
id="rect13" />
|
||||
<rect
|
||||
y="16"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#4e4e4e"
|
||||
id="rect15" />
|
||||
<rect
|
||||
y="32"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#444"
|
||||
id="rect17" />
|
||||
<rect
|
||||
y="48"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#3a3a3a"
|
||||
id="rect19" />
|
||||
<rect
|
||||
y="64"
|
||||
width="341"
|
||||
height="16"
|
||||
fill="#303030"
|
||||
id="rect21" />
|
||||
<rect
|
||||
y="80"
|
||||
width="341"
|
||||
height="10"
|
||||
fill="#262626"
|
||||
id="rect23" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<g
|
||||
id="g2074"
|
||||
transform="translate(18)">
|
||||
<path
|
||||
d="M 2,7 V 90 H 47 V 74 h 7 V 55 H 47 V 42 h 7 V 23 H 47 V 7 Z M 19,26 H 37 V 39 H 19 Z m 0,32 H 37 V 71 H 19 Z"
|
||||
id="path28"
|
||||
style="fill:#080808" />
|
||||
<path
|
||||
d="M 2,7 V 90 H 47 V 74 h 7 V 55 H 47 V 42 h 7 V 23 H 47 V 7 Z m 1,1 h 43 v 16 h 7 v 17 h -7 v 15 h 7 V 73 H 46 V 89 H 3 Z M 18,25 H 38 V 40 H 18 Z m 1,1 V 39 H 37 V 26 Z M 18,57 H 38 V 72 H 18 Z m 1,1 V 71 H 37 V 58 Z M 4,9 V 88 H 45 V 72 h 7 V 57 H 45 V 40 h 7 V 25 H 45 V 9 Z m 1,1 h 39 v 16 h 7 v 13 h -7 v 19 h 7 V 71 H 44 V 87 H 5 Z M 16,23 H 40 V 42 H 16 Z m 1,1 V 41 H 39 V 24 Z M 16,55 H 40 V 74 H 16 Z m 1,1 V 73 H 39 V 56 Z"
|
||||
id="path42"
|
||||
style="fill:url(#pattern1888)" />
|
||||
<path
|
||||
d="M 0,0 V 80 H 42 V 64 h 7 V 48 H 42 V 32 h 7 V 16 H 42 V 0 Z M 14,16 H 35 V 32 H 14 Z m 0,32 H 35 V 64 H 14 Z"
|
||||
id="path56"
|
||||
style="fill:url(#pattern1870)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -4,7 +4,6 @@ summary: Resource monitor that shows usage and stats
|
|||
description: |
|
||||
Resource monitor that shows usage and stats for processor, memory, disks, network and processes.
|
||||
C++ version and continuation of bashtop and bpytop.
|
||||
|
||||
license: Apache-2.0
|
||||
|
||||
base: core20
|
||||
|
@ -26,6 +25,8 @@ package-repositories:
|
|||
apps:
|
||||
btop:
|
||||
command: usr/local/bin/btop
|
||||
extensions:
|
||||
- gnome-3-38
|
||||
environment:
|
||||
LC_ALL: C.UTF-8
|
||||
LANG: C.UTF-8
|
||||
|
@ -38,6 +39,11 @@ apps:
|
|||
- network-observe
|
||||
- home
|
||||
- removable-media
|
||||
- desktop
|
||||
- desktop-legacy
|
||||
- x11
|
||||
- wayland
|
||||
- unity7
|
||||
|
||||
parts:
|
||||
btop:
|
||||
|
|
493
src/btop.cpp
493
src/btop.cpp
|
@ -17,10 +17,12 @@ tab-size = 4
|
|||
*/
|
||||
|
||||
#include <csignal>
|
||||
#include <clocale>
|
||||
#include <pthread.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <bitset>
|
||||
#include <numeric>
|
||||
#include <ranges>
|
||||
#include <unistd.h>
|
||||
|
@ -30,6 +32,11 @@ tab-size = 4
|
|||
#include <tuple>
|
||||
#include <regex>
|
||||
#include <chrono>
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include <btop_shared.hpp>
|
||||
#include <btop_tools.hpp>
|
||||
|
@ -40,7 +47,7 @@ tab-size = 4
|
|||
#include <btop_menu.hpp>
|
||||
|
||||
using std::string, std::string_view, std::vector, std::atomic, std::endl, std::cout, std::min, std::flush, std::endl;
|
||||
using std::string_literals::operator""s, std::to_string, std::future, std::async, std::bitset, std::future_status;
|
||||
using std::string_literals::operator""s, std::to_string;
|
||||
namespace fs = std::filesystem;
|
||||
namespace rng = std::ranges;
|
||||
using namespace Tools;
|
||||
|
@ -55,7 +62,7 @@ namespace Global {
|
|||
{"#801414", "██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ╚═╝"},
|
||||
{"#000000", "╚═════╝ ╚═╝ ╚═════╝ ╚═╝"},
|
||||
};
|
||||
const string Version = "1.0.9";
|
||||
const string Version = "1.2.8";
|
||||
|
||||
int coreCount;
|
||||
string overlay;
|
||||
|
@ -66,6 +73,7 @@ namespace Global {
|
|||
string fg_green = "\x1b[1;92m";
|
||||
string fg_red = "\x1b[0;91m";
|
||||
|
||||
uid_t real_uid, set_uid;
|
||||
|
||||
fs::path self_path;
|
||||
|
||||
|
@ -79,8 +87,9 @@ namespace Global {
|
|||
uint64_t start_time;
|
||||
|
||||
atomic<bool> resized (false);
|
||||
atomic<bool> resizing (false);
|
||||
atomic<bool> quitting (false);
|
||||
atomic<bool> should_quit (false);
|
||||
atomic<bool> should_sleep (false);
|
||||
atomic<bool> _runner_started (false);
|
||||
|
||||
bool arg_tty = false;
|
||||
|
@ -88,7 +97,6 @@ namespace Global {
|
|||
int arg_preset = -1;
|
||||
}
|
||||
|
||||
|
||||
//* A simple argument parser
|
||||
void argumentParser(const int& argc, char **argv) {
|
||||
for(int i = 1; i < argc; i++) {
|
||||
|
@ -150,9 +158,14 @@ void argumentParser(const int& argc, char **argv) {
|
|||
|
||||
//* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true
|
||||
void term_resize(bool force) {
|
||||
if (Global::resizing) return;
|
||||
atomic_lock lck(Global::resizing);
|
||||
if (auto refreshed = Term::refresh(); refreshed or force) {
|
||||
static atomic<bool> resizing (false);
|
||||
if (Input::polling) {
|
||||
Global::resized = true;
|
||||
Input::interrupt = true;
|
||||
return;
|
||||
}
|
||||
atomic_lock lck(resizing, true);
|
||||
if (auto refreshed = Term::refresh(true); refreshed or force) {
|
||||
if (force and refreshed) force = false;
|
||||
}
|
||||
else return;
|
||||
|
@ -160,6 +173,7 @@ void term_resize(bool force) {
|
|||
static const array<string, 4> all_boxes = {"cpu", "mem", "net", "proc"};
|
||||
Global::resized = true;
|
||||
if (Runner::active) Runner::stop();
|
||||
Term::refresh();
|
||||
Config::unlock();
|
||||
|
||||
auto boxes = Config::getS("shown_boxes");
|
||||
|
@ -175,11 +189,12 @@ void term_resize(bool force) {
|
|||
<< Mv::to((Term::height / 2) + 1, (Term::width / 2) - 12) << Global::fg_white
|
||||
<< "Needed for current config:" << Mv::to((Term::height / 2) + 2, (Term::width / 2) - 10)
|
||||
<< "Width = " << min_size.at(0) << " Height = " << min_size.at(1) << flush;
|
||||
while (not Term::refresh() and not Input::poll()) sleep_ms(10);
|
||||
if (Input::poll()) {
|
||||
bool got_key = false;
|
||||
for (; not Term::refresh() and not got_key; got_key = Input::poll(10));
|
||||
if (got_key) {
|
||||
auto key = Input::get();
|
||||
if (key == "q")
|
||||
exit(0);
|
||||
clean_quit(0);
|
||||
else if (is_in(key, "1", "2", "3", "4")) {
|
||||
Config::current_preset = -1;
|
||||
Config::toggle_box(all_boxes.at(std::stoi(key) - 1));
|
||||
|
@ -199,19 +214,26 @@ void clean_quit(int sig) {
|
|||
if (Global::quitting) return;
|
||||
Global::quitting = true;
|
||||
Runner::stop();
|
||||
if (Global::_runner_started and pthread_join(Runner::runner_id, NULL) != 0) {
|
||||
Logger::error("Failed to join _runner thread!");
|
||||
if (Global::_runner_started) {
|
||||
#ifdef __APPLE__
|
||||
if (pthread_join(Runner::runner_id, NULL) != 0) {
|
||||
Logger::warning("Failed to join _runner thread on exit!");
|
||||
pthread_cancel(Runner::runner_id);
|
||||
}
|
||||
#else
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 5;
|
||||
if (pthread_timedjoin_np(Runner::runner_id, NULL, &ts) != 0) {
|
||||
Logger::warning("Failed to join _runner thread on exit!");
|
||||
pthread_cancel(Runner::runner_id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Config::write();
|
||||
Input::clear();
|
||||
|
||||
//? Wait for any remaining Tools::atomic_lock destructors to finish for max 1000ms
|
||||
for (int i = 0; Tools::active_locks > 0 and i < 100; i++) {
|
||||
sleep_ms(10);
|
||||
}
|
||||
|
||||
if (Term::initialized) {
|
||||
Input::clear();
|
||||
Term::restore();
|
||||
}
|
||||
|
||||
|
@ -222,12 +244,13 @@ void clean_quit(int sig) {
|
|||
}
|
||||
Logger::info("Quitting! Runtime: " + sec_to_dhms(time_s() - Global::start_time));
|
||||
|
||||
//? Assume error if still not cleaned up and call quick_exit to avoid a segfault from Tools::atomic_lock destructor
|
||||
if (Tools::active_locks > 0) {
|
||||
quick_exit((sig != -1 ? sig : 0));
|
||||
}
|
||||
const auto excode = (sig != -1 ? sig : 0);
|
||||
|
||||
if (sig != -1) exit(sig);
|
||||
#ifdef __APPLE__
|
||||
_Exit(excode);
|
||||
#else
|
||||
quick_exit(excode);
|
||||
#endif
|
||||
}
|
||||
|
||||
//* Handler for SIGTSTP; stops threads, restores terminal and sends SIGSTOP
|
||||
|
@ -250,10 +273,24 @@ void _exit_handler() {
|
|||
void _signal_handler(const int sig) {
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
clean_quit(0);
|
||||
if (Runner::active) {
|
||||
Global::should_quit = true;
|
||||
Runner::stopping = true;
|
||||
Input::interrupt = true;
|
||||
}
|
||||
else {
|
||||
clean_quit(0);
|
||||
}
|
||||
break;
|
||||
case SIGTSTP:
|
||||
_sleep();
|
||||
if (Runner::active) {
|
||||
Global::should_sleep = true;
|
||||
Runner::stopping = true;
|
||||
Input::interrupt = true;
|
||||
}
|
||||
else {
|
||||
_sleep();
|
||||
}
|
||||
break;
|
||||
case SIGCONT:
|
||||
_resume();
|
||||
|
@ -291,10 +328,22 @@ namespace Runner {
|
|||
pthread_mutex_t& pt_mutex;
|
||||
public:
|
||||
int status;
|
||||
thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { status = pthread_mutex_lock(&pt_mutex); }
|
||||
thread_lock(pthread_mutex_t& mtx) : pt_mutex(mtx) { pthread_mutex_init(&pt_mutex, NULL); status = pthread_mutex_lock(&pt_mutex); }
|
||||
~thread_lock() { if (status == 0) pthread_mutex_unlock(&pt_mutex); }
|
||||
};
|
||||
|
||||
//* Wrapper for raising priviliges when using SUID bit
|
||||
class gain_priv {
|
||||
int status = -1;
|
||||
public:
|
||||
gain_priv() {
|
||||
if (Global::real_uid != Global::set_uid) this->status = seteuid(Global::set_uid);
|
||||
}
|
||||
~gain_priv() {
|
||||
if (status == 0) status = seteuid(Global::real_uid);
|
||||
}
|
||||
};
|
||||
|
||||
string output;
|
||||
string empty_bg;
|
||||
bool pause_output = false;
|
||||
|
@ -302,20 +351,6 @@ namespace Runner {
|
|||
pthread_t runner_id;
|
||||
pthread_mutex_t mtx;
|
||||
|
||||
const unordered_flat_map<string, uint_fast8_t> box_bits = {
|
||||
{"proc", 0b0000'0001},
|
||||
{"net", 0b0000'0100},
|
||||
{"mem", 0b0001'0000},
|
||||
{"cpu", 0b0100'0000},
|
||||
};
|
||||
|
||||
enum bit_pos {
|
||||
proc_present, proc_running,
|
||||
net_present, net_running,
|
||||
mem_present, mem_running,
|
||||
cpu_present, cpu_running
|
||||
};
|
||||
|
||||
enum debug_actions {
|
||||
collect_begin,
|
||||
draw_begin,
|
||||
|
@ -327,16 +362,11 @@ namespace Runner {
|
|||
draw
|
||||
};
|
||||
|
||||
const uint_fast8_t proc_done = 0b0000'0011;
|
||||
const uint_fast8_t net_done = 0b0000'1100;
|
||||
const uint_fast8_t mem_done = 0b0011'0000;
|
||||
const uint_fast8_t cpu_done = 0b1100'0000;
|
||||
|
||||
string debug_bg;
|
||||
unordered_flat_map<string, array<uint64_t, 2>> debug_times;
|
||||
|
||||
struct runner_conf {
|
||||
bitset<8> box_mask;
|
||||
vector<string> boxes;
|
||||
bool no_update;
|
||||
bool force_redraw;
|
||||
bool background_update;
|
||||
|
@ -366,10 +396,10 @@ namespace Runner {
|
|||
//? ------------------------------- Secondary thread: async launcher and drawing ----------------------------------
|
||||
void * _runner(void * _) {
|
||||
(void)_;
|
||||
//? Block all signals in this thread to avoid deadlock from any signal handlers trying to stop this thread
|
||||
//? Block some signals in this thread to avoid deadlock from any signal handlers trying to stop this thread
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTSTP);
|
||||
// sigaddset(&mask, SIGINT);
|
||||
// sigaddset(&mask, SIGTSTP);
|
||||
sigaddset(&mask, SIGWINCH);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
|
@ -386,13 +416,24 @@ namespace Runner {
|
|||
//* ----------------------------------------------- THREAD LOOP -----------------------------------------------
|
||||
while (not Global::quitting) {
|
||||
thread_wait();
|
||||
atomic_wait_for(active, true, 5000);
|
||||
if (active) {
|
||||
Global::exit_error_msg = "Runner thread failed to get active lock!";
|
||||
Global::thread_exception = true;
|
||||
Input::interrupt = true;
|
||||
stopping = true;
|
||||
}
|
||||
if (stopping or Global::resized) {
|
||||
sleep_ms(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
//? Atomic lock used for blocking non thread-safe actions in main thread
|
||||
atomic_lock lck(active);
|
||||
|
||||
//? Set effective user if SUID bit is set
|
||||
gain_priv powers{};
|
||||
|
||||
auto& conf = current_conf;
|
||||
|
||||
//! DEBUG stats
|
||||
|
@ -404,128 +445,85 @@ namespace Runner {
|
|||
|
||||
output.clear();
|
||||
|
||||
//* Start collection functions for all boxes in async threads and draw in this thread when finished
|
||||
//? Starting order below based on mean time to finish
|
||||
//* Run collection and draw functions for all boxes
|
||||
try {
|
||||
future<Cpu::cpu_info&> cpu;
|
||||
future<Mem::mem_info&> mem;
|
||||
future<Net::net_info&> net;
|
||||
future<vector<Proc::proc_info>&> proc;
|
||||
//? CPU
|
||||
if (v_contains(conf.boxes, "cpu")) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("cpu", collect_begin);
|
||||
|
||||
//? Loop until all box flags present in bitmask have been zeroed
|
||||
while (conf.box_mask.count() > 0) {
|
||||
if (stopping) break;
|
||||
//? Start collect
|
||||
auto cpu = Cpu::collect(conf.no_update);
|
||||
|
||||
//? PROC
|
||||
if (conf.box_mask.test(proc_present)) {
|
||||
if (not conf.box_mask.test(proc_running)) {
|
||||
if (Global::debug) debug_timer("proc", collect_begin);
|
||||
if (Global::debug) debug_timer("cpu", draw_begin);
|
||||
|
||||
//? Start async collect
|
||||
proc = async(Proc::collect, conf.no_update);
|
||||
conf.box_mask.set(proc_running);
|
||||
}
|
||||
else if (not proc.valid())
|
||||
throw std::runtime_error("Proc::collect() future not valid.");
|
||||
//? Draw box
|
||||
if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update);
|
||||
|
||||
else if (proc.wait_for(10us) == future_status::ready) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("proc", draw_begin);
|
||||
|
||||
//? Draw box
|
||||
if (not pause_output) output += Proc::draw(proc.get(), conf.force_redraw, conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("proc", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Proc:: -> " + (string)e.what());
|
||||
}
|
||||
conf.box_mask ^= proc_done;
|
||||
}
|
||||
if (Global::debug) debug_timer("cpu", draw_done);
|
||||
}
|
||||
|
||||
//? NET
|
||||
if (conf.box_mask.test(net_present)) {
|
||||
if (not conf.box_mask.test(net_running)) {
|
||||
if (Global::debug) debug_timer("net", collect_begin);
|
||||
|
||||
//? Start async collect
|
||||
net = async(Net::collect, conf.no_update);
|
||||
conf.box_mask.set(net_running);
|
||||
}
|
||||
else if (not net.valid())
|
||||
throw std::runtime_error("Net::collect() future not valid.");
|
||||
|
||||
else if (net.wait_for(10us) == future_status::ready) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("net", draw_begin);
|
||||
|
||||
//? Draw box
|
||||
if (not pause_output) output += Net::draw(net.get(), conf.force_redraw, conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("net", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Net:: -> " + (string)e.what());
|
||||
}
|
||||
conf.box_mask ^= net_done;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Cpu:: -> " + (string)e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//? MEM
|
||||
if (conf.box_mask.test(mem_present)) {
|
||||
if (not conf.box_mask.test(mem_running)) {
|
||||
if (Global::debug) debug_timer("mem", collect_begin);
|
||||
//? MEM
|
||||
if (v_contains(conf.boxes, "mem")) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("mem", collect_begin);
|
||||
|
||||
//? Start async collect
|
||||
mem = async(Mem::collect, conf.no_update);
|
||||
conf.box_mask.set(mem_running);
|
||||
}
|
||||
else if (not mem.valid())
|
||||
throw std::runtime_error("Mem::collect() future not valid.");
|
||||
//? Start collect
|
||||
auto mem = Mem::collect(conf.no_update);
|
||||
|
||||
else if (mem.wait_for(10us) == future_status::ready) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("mem", draw_begin);
|
||||
if (Global::debug) debug_timer("mem", draw_begin);
|
||||
|
||||
//? Draw box
|
||||
if (not pause_output) output += Mem::draw(mem.get(), conf.force_redraw, conf.no_update);
|
||||
//? Draw box
|
||||
if (not pause_output) output += Mem::draw(mem, conf.force_redraw, conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("mem", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Mem:: -> " + (string)e.what());
|
||||
}
|
||||
conf.box_mask ^= mem_done;
|
||||
}
|
||||
if (Global::debug) debug_timer("mem", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Mem:: -> " + (string)e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//? CPU
|
||||
if (conf.box_mask.test(cpu_present)) {
|
||||
if (not conf.box_mask.test(cpu_running)) {
|
||||
if (Global::debug) debug_timer("cpu", collect_begin);
|
||||
//? NET
|
||||
if (v_contains(conf.boxes, "net")) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("net", collect_begin);
|
||||
|
||||
//? Start async collect
|
||||
cpu = async(Cpu::collect, conf.no_update);
|
||||
conf.box_mask.set(cpu_running);
|
||||
}
|
||||
else if (not cpu.valid())
|
||||
throw std::runtime_error("Cpu::collect() future not valid.");
|
||||
//? Start collect
|
||||
auto net = Net::collect(conf.no_update);
|
||||
|
||||
else if (cpu.wait_for(10us) == future_status::ready) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("cpu", draw_begin);
|
||||
if (Global::debug) debug_timer("net", draw_begin);
|
||||
|
||||
//? Draw box
|
||||
if (not pause_output) output += Cpu::draw(cpu.get(), conf.force_redraw, conf.no_update);
|
||||
//? Draw box
|
||||
if (not pause_output) output += Net::draw(net, conf.force_redraw, conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("cpu", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Cpu:: -> " + (string)e.what());
|
||||
}
|
||||
conf.box_mask ^= cpu_done;
|
||||
}
|
||||
if (Global::debug) debug_timer("net", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Net:: -> " + (string)e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//? PROC
|
||||
if (v_contains(conf.boxes, "proc")) {
|
||||
try {
|
||||
if (Global::debug) debug_timer("proc", collect_begin);
|
||||
|
||||
//? Start collect
|
||||
auto proc = Proc::collect(conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("proc", draw_begin);
|
||||
|
||||
//? Draw box
|
||||
if (not pause_output) output += Proc::draw(proc, conf.force_redraw, conf.no_update);
|
||||
|
||||
if (Global::debug) debug_timer("proc", draw_done);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Proc:: -> " + (string)e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -581,15 +579,23 @@ namespace Runner {
|
|||
<< Term::sync_end << flush;
|
||||
}
|
||||
//* ----------------------------------------------- THREAD LOOP -----------------------------------------------
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
//? ------------------------------------------ Secondary thread end -----------------------------------------------
|
||||
|
||||
//* Runs collect and draw in a secondary thread, unlocks and locks config to update cached values
|
||||
void run(const string& box, const bool no_update, const bool force_redraw) {
|
||||
atomic_lock lck(waiting);
|
||||
atomic_wait(active);
|
||||
atomic_wait_for(active, true, 5000);
|
||||
if (active) {
|
||||
Logger::error("Stall in Runner thread, restarting!");
|
||||
active = false;
|
||||
// exit(1);
|
||||
pthread_cancel(Runner::runner_id);
|
||||
if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) {
|
||||
Global::exit_error_msg = "Failed to re-create _runner thread!";
|
||||
clean_quit(1);
|
||||
}
|
||||
}
|
||||
if (stopping or Global::resized) return;
|
||||
|
||||
if (box == "overlay") {
|
||||
|
@ -602,21 +608,21 @@ namespace Runner {
|
|||
Config::unlock();
|
||||
Config::lock();
|
||||
|
||||
//? Setup bitmask for selected boxes and pass to _runner thread
|
||||
bitset<8> box_mask;
|
||||
for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) {
|
||||
box_mask |= box_bits.at(box);
|
||||
}
|
||||
|
||||
current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock};
|
||||
current_conf = {
|
||||
(box == "all" ? Config::current_boxes : vector{box}),
|
||||
no_update, force_redraw,
|
||||
(not Config::getB("tty_mode") and Config::getB("background_update")),
|
||||
Global::overlay,
|
||||
Global::clock
|
||||
};
|
||||
|
||||
if (Menu::active and not current_conf.background_update) Global::overlay.clear();
|
||||
|
||||
thread_trigger();
|
||||
|
||||
//? Wait for _runner thread to be active before returning
|
||||
for (int i = 0; not active and i < 10; i++) sleep_ms(1);
|
||||
atomic_wait_for(active, false, 10);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//* Stops any work being done in runner thread and checks for thread errors
|
||||
|
@ -626,12 +632,23 @@ namespace Runner {
|
|||
if (ret != EBUSY and not Global::quitting) {
|
||||
if (active) active = false;
|
||||
Global::exit_error_msg = "Runner thread died unexpectedly!";
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
else if (ret == EBUSY) {
|
||||
atomic_wait(active);
|
||||
atomic_wait_for(active, true, 5000);
|
||||
if (active) {
|
||||
active = false;
|
||||
if (Global::quitting) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Global::exit_error_msg = "No response from Runner thread, quitting!";
|
||||
clean_quit(1);
|
||||
}
|
||||
}
|
||||
thread_trigger();
|
||||
sleep_ms(1);
|
||||
atomic_wait_for(active, false, 100);
|
||||
atomic_wait_for(active, true, 100);
|
||||
}
|
||||
stopping = false;
|
||||
}
|
||||
|
@ -646,16 +663,20 @@ int main(int argc, char **argv) {
|
|||
|
||||
Global::start_time = time_s();
|
||||
|
||||
//? Save real and effective userid's and drop priviliges until needed if running with SUID bit set
|
||||
Global::real_uid = getuid();
|
||||
Global::set_uid = geteuid();
|
||||
if (Global::real_uid != Global::set_uid) {
|
||||
if (seteuid(Global::real_uid) != 0) {
|
||||
Global::real_uid = Global::set_uid;
|
||||
Global::exit_error_msg = "Failed to change effective user ID. Unset btop SUID bit to ensure security on this system. Quitting!";
|
||||
clean_quit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//? Call argument parser if launched with arguments
|
||||
if (argc > 1) argumentParser(argc, argv);
|
||||
|
||||
//? Setup signal handlers for CTRL-C, CTRL-Z, resume and terminal resize
|
||||
std::atexit(_exit_handler);
|
||||
std::signal(SIGINT, _signal_handler);
|
||||
std::signal(SIGTSTP, _signal_handler);
|
||||
std::signal(SIGCONT, _signal_handler);
|
||||
std::signal(SIGWINCH, _signal_handler);
|
||||
|
||||
//? Setup paths for config, log and user themes
|
||||
for (const auto& env : {"XDG_CONFIG_HOME", "HOME"}) {
|
||||
if (std::getenv(env) != NULL and access(std::getenv(env), W_OK) != -1) {
|
||||
|
@ -680,10 +701,17 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
//? Try to find global btop theme path relative to binary path
|
||||
#if defined(__linux__)
|
||||
#ifdef __linux__
|
||||
{ std::error_code ec;
|
||||
Global::self_path = fs::read_symlink("/proc/self/exe", ec).remove_filename();
|
||||
}
|
||||
#elif __APPLE__
|
||||
{
|
||||
char buf [PATH_MAX];
|
||||
uint32_t bufsize = PATH_MAX;
|
||||
if(!_NSGetExecutablePath(buf, &bufsize))
|
||||
Global::self_path = fs::path(buf).remove_filename();
|
||||
}
|
||||
#endif
|
||||
if (std::error_code ec; not Global::self_path.empty()) {
|
||||
Theme::theme_dir = fs::canonical(Global::self_path / "../share/btop/themes", ec);
|
||||
|
@ -718,44 +746,76 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
//? Try to find and set a UTF-8 locale
|
||||
if (bool found = false; std::setlocale(LC_ALL, NULL) == NULL or not str_to_upper(s_replace((string)std::setlocale(LC_ALL, NULL), "-", "")).ends_with("UTF8")) {
|
||||
if (std::getenv("LANG") != NULL and str_to_upper(s_replace((string)std::getenv("LANG"), "-", "")).ends_with("UTF8")) {
|
||||
if (std::setlocale(LC_ALL, std::getenv("LANG")) != NULL) {
|
||||
found = true;
|
||||
if (std::setlocale(LC_ALL, "") != NULL and not s_contains((string)std::setlocale(LC_ALL, ""), ";")
|
||||
and str_to_upper(s_replace((string)std::setlocale(LC_ALL, ""), "-", "")).ends_with("UTF8")) {
|
||||
Logger::debug("Using locale " + (string)std::setlocale(LC_ALL, ""));
|
||||
}
|
||||
else {
|
||||
string found;
|
||||
bool set_failure = false;
|
||||
for (const auto loc_env : array{"LANG", "LC_ALL"}) {
|
||||
if (std::getenv(loc_env) != NULL and str_to_upper(s_replace((string)std::getenv(loc_env), "-", "")).ends_with("UTF8")) {
|
||||
found = std::getenv(loc_env);
|
||||
if (std::setlocale(LC_ALL, found.c_str()) == NULL) {
|
||||
set_failure = true;
|
||||
Logger::warning("Failed to set locale " + found + " continuing anyway.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (setenv("LANG", "", 1) == 0) {
|
||||
if (found.empty()) {
|
||||
if (setenv("LC_ALL", "", 1) == 0 and setenv("LANG", "", 1) == 0) {
|
||||
try {
|
||||
if (const auto loc = std::locale("").name(); not loc.empty() and loc != "*") {
|
||||
for (auto& l : ssplit(loc, ';')) {
|
||||
if (str_to_upper(s_replace(l, "-", "")).ends_with("UTF8")) {
|
||||
if (std::setlocale(LC_ALL, l.substr(l.find('=') + 1).c_str()) != NULL) {
|
||||
found = true;
|
||||
found = l.substr(l.find('=') + 1);
|
||||
if (std::setlocale(LC_ALL, found.c_str()) != NULL) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) { found = false; }
|
||||
catch (...) { found.clear(); }
|
||||
}
|
||||
}
|
||||
|
||||
if (not found and Global::utf_force)
|
||||
Logger::warning("No UTF-8 locale detected! Forcing start with --utf-force argument.");
|
||||
else if (not found) {
|
||||
Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it.";
|
||||
exit(1);
|
||||
#ifdef __APPLE__
|
||||
if (found.empty()) {
|
||||
CFLocaleRef cflocale = CFLocaleCopyCurrent();
|
||||
CFStringRef id_value = (CFStringRef)CFLocaleGetValue(cflocale, kCFLocaleIdentifier);
|
||||
auto loc_id = CFStringGetCStringPtr(id_value, kCFStringEncodingUTF8);
|
||||
CFRelease(cflocale);
|
||||
std::string cur_locale = (loc_id != nullptr ? loc_id : "");
|
||||
if (cur_locale.empty()) {
|
||||
Logger::warning("No UTF-8 locale detected! Some symbols might not display correctly.");
|
||||
}
|
||||
else if (std::setlocale(LC_ALL, string(cur_locale + ".UTF-8").c_str()) != NULL) {
|
||||
Logger::debug("Setting LC_ALL=" + cur_locale + ".UTF-8");
|
||||
}
|
||||
else if(std::setlocale(LC_ALL, "en_US.UTF-8") != NULL) {
|
||||
Logger::debug("Setting LC_ALL=en_US.UTF-8");
|
||||
}
|
||||
else {
|
||||
Logger::warning("Failed to set macos locale, continuing anyway.");
|
||||
}
|
||||
}
|
||||
else
|
||||
Logger::debug("Setting LC_ALL=" + (string)std::setlocale(LC_ALL, NULL));
|
||||
#else
|
||||
if (found.empty() and Global::utf_force)
|
||||
Logger::warning("No UTF-8 locale detected! Forcing start with --utf-force argument.");
|
||||
else if (found.empty()) {
|
||||
Global::exit_error_msg = "No UTF-8 locale detected!\nUse --utf-force argument to force start if you're sure your terminal can handle it.";
|
||||
clean_quit(1);
|
||||
}
|
||||
#endif
|
||||
else if (not set_failure)
|
||||
Logger::debug("Setting LC_ALL=" + found);
|
||||
}
|
||||
|
||||
//? Initialize terminal and set options
|
||||
if (not Term::init()) {
|
||||
Global::exit_error_msg = "No tty detected!\nbtop++ needs an interactive shell to run.";
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
|
||||
if (Term::current_tty != "unknown") Logger::info("Running on " + Term::current_tty);
|
||||
|
@ -763,10 +823,25 @@ int main(int argc, char **argv) {
|
|||
Config::set("tty_mode", true);
|
||||
Logger::info("Forcing tty mode: setting 16 color mode and using tty friendly graph symbols");
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
else if (not Global::arg_tty and Term::current_tty.starts_with("/dev/tty")) {
|
||||
Config::set("tty_mode", true);
|
||||
Logger::info("Real tty detected: setting 16 color mode and using tty friendly graph symbols");
|
||||
}
|
||||
#endif
|
||||
|
||||
//? Check for valid terminal dimensions
|
||||
{
|
||||
int t_count = 0;
|
||||
while (Term::width <= 0 or Term::width > 10000 or Term::height <= 0 or Term::height > 10000) {
|
||||
sleep_ms(10);
|
||||
Term::refresh();
|
||||
if (++t_count == 100) {
|
||||
Global::exit_error_msg = "Failed to get size of terminal!";
|
||||
clean_quit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//? Platform dependent init and error check
|
||||
try {
|
||||
|
@ -774,18 +849,25 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
catch (const std::exception& e) {
|
||||
Global::exit_error_msg = "Exception in Shared::init() -> " + (string)e.what();
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
|
||||
//? Update list of available themes and generate the selected theme
|
||||
Theme::updateThemes();
|
||||
Theme::setTheme();
|
||||
|
||||
//? Setup signal handlers for CTRL-C, CTRL-Z, resume and terminal resize
|
||||
std::atexit(_exit_handler);
|
||||
std::signal(SIGINT, _signal_handler);
|
||||
std::signal(SIGTSTP, _signal_handler);
|
||||
std::signal(SIGCONT, _signal_handler);
|
||||
std::signal(SIGWINCH, _signal_handler);
|
||||
|
||||
//? Start runner thread
|
||||
Runner::thread_sem_init();
|
||||
if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) {
|
||||
Global::exit_error_msg = "Failed to create _runner thread!";
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
else {
|
||||
Global::_runner_started = true;
|
||||
|
@ -808,8 +890,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
}
|
||||
|
||||
//? Print out box outlines
|
||||
Draw::calcSizes();
|
||||
|
||||
//? Print out box outlines
|
||||
cout << Term::sync_start << Cpu::box << Mem::box << Net::box << Proc::box << Term::sync_end << flush;
|
||||
|
||||
|
||||
|
@ -821,10 +904,12 @@ int main(int argc, char **argv) {
|
|||
try {
|
||||
while (not true not_eq not false) {
|
||||
//? Check for exceptions in secondary thread and exit with fail signal if true
|
||||
if (Global::thread_exception) exit(1);
|
||||
if (Global::thread_exception) clean_quit(1);
|
||||
else if (Global::should_quit) clean_quit(0);
|
||||
else if (Global::should_sleep) { Global::should_sleep = false; _sleep(); }
|
||||
|
||||
//? Make sure terminal size hasn't changed (in case of SIGWINCH not working properly)
|
||||
term_resize();
|
||||
term_resize(Global::resized);
|
||||
|
||||
//? Trigger secondary thread to redraw if terminal has been resized
|
||||
if (Global::resized) {
|
||||
|
@ -833,7 +918,7 @@ int main(int argc, char **argv) {
|
|||
Global::resized = false;
|
||||
if (Menu::active) Menu::process();
|
||||
else Runner::run("all", true, true);
|
||||
atomic_wait(Runner::active);
|
||||
atomic_wait_for(Runner::active, true, 1000);
|
||||
}
|
||||
|
||||
//? Update clock if needed
|
||||
|
@ -876,7 +961,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
catch (const std::exception& e) {
|
||||
Global::exit_error_msg = "Exception in main loop -> " + (string)e.what();
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,10 +50,13 @@ namespace Config {
|
|||
"#* Will force 16-color mode and TTY theme, set all graph symbols to \"tty\" and swap out other non tty friendly symbols."},
|
||||
|
||||
{"presets", "#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.\n"
|
||||
"#* Format: \"box_name:P:G,box_name:P:G\" P=(0 or 1) for alternate positons, G=graph symbol to use for box.\n"
|
||||
"#* Use withespace \" \" as seprator between different presets.\n"
|
||||
"#* Format: \"box_name:P:G,box_name:P:G\" P=(0 or 1) for alternate positions, G=graph symbol to use for box.\n"
|
||||
"#* Use withespace \" \" as separator between different presets.\n"
|
||||
"#* Example: \"cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty\""},
|
||||
|
||||
{"vim_keys", "#* Set to True to enable \"h,j,k,l,g,G\" keys for directional control in lists.\n"
|
||||
"#* Conflicting keys for h:\"help\" and k:\"kill\" is accessible while holding shift."},
|
||||
|
||||
{"rounded_corners", "#* Rounded corners on boxes, is ignored if TTY mode is ON."},
|
||||
|
||||
{"graph_symbol", "#* Default symbols to use for graph creation, \"braille\", \"block\" or \"tty\".\n"
|
||||
|
@ -74,8 +77,8 @@ namespace Config {
|
|||
|
||||
{"update_ms", "#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs."},
|
||||
|
||||
{"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"cpu lazy\" \"cpu responsive\",\n"
|
||||
"#* \"cpu lazy\" sorts top process over time (easier to follow), \"cpu responsive\" updates top process directly."},
|
||||
{"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"cpu lazy\" \"cpu direct\",\n"
|
||||
"#* \"cpu lazy\" sorts top process over time (easier to follow), \"cpu direct\" updates top process directly."},
|
||||
|
||||
{"proc_reversed", "#* Reverse sorting order, True or False."},
|
||||
|
||||
|
@ -89,10 +92,14 @@ namespace Config {
|
|||
|
||||
{"proc_mem_bytes", "#* Show process memory as bytes instead of percent."},
|
||||
|
||||
{"proc_cpu_graphs", "#* Show cpu graph for each process."},
|
||||
|
||||
{"proc_info_smaps", "#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)"},
|
||||
|
||||
{"proc_left", "#* Show proc box on left side of screen instead of right."},
|
||||
|
||||
{"proc_filter_kernel", "#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop)."},
|
||||
|
||||
{"cpu_graph_upper", "#* Sets the CPU stat shown in upper half of the CPU graph, \"total\" is always available.\n"
|
||||
"#* Select from a list of detected attributes from the options menu."},
|
||||
|
||||
|
@ -120,6 +127,8 @@ namespace Config {
|
|||
|
||||
{"temp_scale", "#* Which temperature scale to use, available values: \"celsius\", \"fahrenheit\", \"kelvin\" and \"rankine\"."},
|
||||
|
||||
{"base_10_sizes", "#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024."},
|
||||
|
||||
{"show_cpu_freq", "#* Show CPU frequency."},
|
||||
|
||||
{"clock_format", "#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.\n"
|
||||
|
@ -136,6 +145,8 @@ namespace Config {
|
|||
|
||||
{"mem_below_net", "#* Show mem box below net box instead of above."},
|
||||
|
||||
{"zfs_arc_cached", "#* Count ZFS ARC in cached and available memory."},
|
||||
|
||||
{"show_swap", "#* If swap memory should be shown in memory box."},
|
||||
|
||||
{"swap_disk", "#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk."},
|
||||
|
@ -146,6 +157,10 @@ namespace Config {
|
|||
|
||||
{"use_fstab", "#* Read disks list from /etc/fstab. This also disables only_physical."},
|
||||
|
||||
{"zfs_hide_datasets", "#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)"},
|
||||
|
||||
{"disk_free_priv", "#* Set to true to show available disk space for privileged users."},
|
||||
|
||||
{"show_io_stat", "#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view."},
|
||||
|
||||
{"io_mode", "#* Toggles io mode for disks, showing big graphs for disk read/write speeds."},
|
||||
|
@ -167,6 +182,8 @@ namespace Config {
|
|||
|
||||
{"show_battery", "#* Show battery stats in top right if battery is present."},
|
||||
|
||||
{"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."},
|
||||
|
||||
{"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n"
|
||||
"#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."}
|
||||
};
|
||||
|
@ -184,6 +201,7 @@ namespace Config {
|
|||
{"cpu_graph_upper", "total"},
|
||||
{"cpu_graph_lower", "total"},
|
||||
{"cpu_sensor", "Auto"},
|
||||
{"selected_battery", "Auto"},
|
||||
{"cpu_core_map", ""},
|
||||
{"temp_scale", "celsius"},
|
||||
{"clock_format", "%X"},
|
||||
|
@ -206,10 +224,12 @@ namespace Config {
|
|||
{"proc_tree", false},
|
||||
{"proc_colors", true},
|
||||
{"proc_gradient", true},
|
||||
{"proc_per_core", true},
|
||||
{"proc_per_core", false},
|
||||
{"proc_mem_bytes", true},
|
||||
{"proc_cpu_graphs", true},
|
||||
{"proc_info_smaps", false},
|
||||
{"proc_left", false},
|
||||
{"proc_filter_kernel", false},
|
||||
{"cpu_invert_lower", true},
|
||||
{"cpu_single_graph", false},
|
||||
{"cpu_bottom", false},
|
||||
|
@ -220,18 +240,23 @@ namespace Config {
|
|||
{"background_update", true},
|
||||
{"mem_graphs", true},
|
||||
{"mem_below_net", false},
|
||||
{"zfs_arc_cached", true},
|
||||
{"show_swap", true},
|
||||
{"swap_disk", true},
|
||||
{"show_disks", true},
|
||||
{"only_physical", true},
|
||||
{"use_fstab", true},
|
||||
{"zfs_hide_datasets", false},
|
||||
{"show_io_stat", true},
|
||||
{"io_mode", false},
|
||||
{"base_10_sizes", false},
|
||||
{"io_graph_combined", false},
|
||||
{"net_auto", true},
|
||||
{"net_sync", false},
|
||||
{"net_sync", true},
|
||||
{"show_battery", true},
|
||||
{"vim_keys", false},
|
||||
{"tty_mode", false},
|
||||
{"disk_free_priv", false},
|
||||
{"force_tty", false},
|
||||
{"lowcolor", false},
|
||||
{"show_detailed", false},
|
||||
|
@ -245,6 +270,7 @@ namespace Config {
|
|||
{"net_upload", 100},
|
||||
{"detailed_pid", 0},
|
||||
{"selected_pid", 0},
|
||||
{"selected_depth", 0},
|
||||
{"proc_start", 0},
|
||||
{"proc_selected", 0},
|
||||
{"proc_last_selected", 0},
|
||||
|
@ -252,7 +278,7 @@ namespace Config {
|
|||
unordered_flat_map<string, int> intsTmp;
|
||||
|
||||
bool _locked(const string& name) {
|
||||
atomic_wait(writelock);
|
||||
atomic_wait(writelock, true);
|
||||
if (not write_new and rng::find_if(descriptions, [&name](const auto& a) { return a.at(0) == name; }) != descriptions.end())
|
||||
write_new = true;
|
||||
return locked.load();
|
||||
|
@ -261,6 +287,8 @@ namespace Config {
|
|||
fs::path conf_dir;
|
||||
fs::path conf_file;
|
||||
|
||||
vector<string> available_batteries = {"Auto"};
|
||||
|
||||
vector<string> current_boxes;
|
||||
vector<string> preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"};
|
||||
int current_preset = -1;
|
||||
|
@ -444,13 +472,14 @@ namespace Config {
|
|||
void unlock() {
|
||||
if (not locked) return;
|
||||
atomic_wait(Runner::active);
|
||||
atomic_lock lck(writelock);
|
||||
atomic_lock lck(writelock, true);
|
||||
try {
|
||||
if (Proc::shown) {
|
||||
ints.at("selected_pid") = Proc::selected_pid;
|
||||
strings.at("selected_name") = Proc::selected_name;
|
||||
ints.at("proc_start") = Proc::start;
|
||||
ints.at("proc_selected") = Proc::selected;
|
||||
ints.at("selected_depth") = Proc::selected_depth;
|
||||
}
|
||||
|
||||
for (auto& item : stringsTmp) {
|
||||
|
@ -470,7 +499,7 @@ namespace Config {
|
|||
}
|
||||
catch (const std::exception& e) {
|
||||
Global::exit_error_msg = "Exception during Config::unlock() : " + (string)e.what();
|
||||
exit(1);
|
||||
clean_quit(1);
|
||||
}
|
||||
|
||||
locked = false;
|
||||
|
@ -521,9 +550,7 @@ namespace Config {
|
|||
vector<string> valid_names;
|
||||
for (auto &n : descriptions)
|
||||
valid_names.push_back(n[0]);
|
||||
string v_string;
|
||||
getline(cread, v_string, '\n');
|
||||
if (not s_contains(v_string, Global::Version))
|
||||
if (string v_string; cread.peek() != '#' or (getline(cread, v_string, '\n') and not s_contains(v_string, Global::Version)))
|
||||
write_new = true;
|
||||
while (not cread.eof()) {
|
||||
cread >> std::ws;
|
||||
|
@ -580,6 +607,7 @@ namespace Config {
|
|||
void write() {
|
||||
if (conf_file.empty() or not write_new) return;
|
||||
Logger::debug("Writing new config file");
|
||||
if (geteuid() != Global::real_uid and seteuid(Global::real_uid) != 0) return;
|
||||
std::ofstream cwrite(conf_file, std::ios::trunc);
|
||||
if (cwrite.good()) {
|
||||
cwrite << "#? Config file for btop v. " << Global::Version;
|
||||
|
@ -595,4 +623,4 @@ namespace Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,9 +45,10 @@ namespace Config {
|
|||
|
||||
extern vector<string> current_boxes;
|
||||
extern vector<string> preset_list;
|
||||
extern vector<string> available_batteries;
|
||||
extern int current_preset;
|
||||
|
||||
//* Check if string only contains space seperated valid names for boxes
|
||||
//* Check if string only contains space separated valid names for boxes
|
||||
bool check_boxes(const string& boxes);
|
||||
|
||||
//* Toggle box and update config string shown_boxes
|
||||
|
|
|
@ -43,42 +43,42 @@ namespace Symbols {
|
|||
|
||||
const unordered_flat_map<string, vector<string>> graph_symbols = {
|
||||
{ "braille_up", {
|
||||
" ", "⢀", "⢠", "⢰", "⢸",
|
||||
" ", "⢀", "⢠", "⢰", "⢸",
|
||||
"⡀", "⣀", "⣠", "⣰", "⣸",
|
||||
"⡄", "⣄", "⣤", "⣴", "⣼",
|
||||
"⡆", "⣆", "⣦", "⣶", "⣾",
|
||||
"⡇", "⣇", "⣧", "⣷", "⣿"
|
||||
}},
|
||||
{"braille_down", {
|
||||
" ", "⠈", "⠘", "⠸", "⢸",
|
||||
" ", "⠈", "⠘", "⠸", "⢸",
|
||||
"⠁", "⠉", "⠙", "⠹", "⢹",
|
||||
"⠃", "⠋", "⠛", "⠻", "⢻",
|
||||
"⠇", "⠏", "⠟", "⠿", "⢿",
|
||||
"⡇", "⡏", "⡟", "⡿", "⣿"
|
||||
}},
|
||||
{"block_up", {
|
||||
" ", "▗", "▗", "▐", "▐",
|
||||
" ", "▗", "▗", "▐", "▐",
|
||||
"▖", "▄", "▄", "▟", "▟",
|
||||
"▖", "▄", "▄", "▟", "▟",
|
||||
"▌", "▙", "▙", "█", "█",
|
||||
"▌", "▙", "▙", "█", "█"
|
||||
}},
|
||||
{"block_down", {
|
||||
" ", "▝", "▝", "▐", "▐",
|
||||
" ", "▝", "▝", "▐", "▐",
|
||||
"▘", "▀", "▀", "▜", "▜",
|
||||
"▘", "▀", "▀", "▜", "▜",
|
||||
"▌", "▛", "▛", "█", "█",
|
||||
"▌", "▛", "▛", "█", "█"
|
||||
}},
|
||||
{"tty_up", {
|
||||
" ", "░", "░", "▒", "▒",
|
||||
" ", "░", "░", "▒", "▒",
|
||||
"░", "░", "▒", "▒", "█",
|
||||
"░", "▒", "▒", "▒", "█",
|
||||
"▒", "▒", "▒", "█", "█",
|
||||
"▒", "█", "█", "█", "█"
|
||||
}},
|
||||
{"tty_down", {
|
||||
" ", "░", "░", "▒", "▒",
|
||||
" ", "░", "░", "▒", "▒",
|
||||
"░", "░", "▒", "▒", "█",
|
||||
"░", "▒", "▒", "▒", "█",
|
||||
"▒", "▒", "▒", "█", "█",
|
||||
|
@ -111,7 +111,7 @@ namespace Draw {
|
|||
}
|
||||
for (size_t i = 0; i < line[1].size(); i += 3) {
|
||||
if (line[1][i] == ' ') {
|
||||
letter = ' ';
|
||||
letter = Mv::r(1);
|
||||
i -= 2;
|
||||
}
|
||||
else
|
||||
|
@ -388,15 +388,22 @@ namespace Draw {
|
|||
}
|
||||
}
|
||||
//? Generate graph symbol from 5x5 2D vector
|
||||
graphs.at(current).at(horizon) += (height == 1 and result.at(0) + result.at(1) == 0) ? Mv::r(1) : graph_symbol.at((result.at(0) * 5 + result.at(1)));
|
||||
if (height == 1) {
|
||||
if (result.at(0) + result.at(1) == 0) graphs.at(current).at(horizon) += Mv::r(1);
|
||||
else {
|
||||
if (not color_gradient.empty()) graphs.at(current).at(horizon) += Theme::g(color_gradient).at(clamp(max(last, data_value), 0ll, 100ll));
|
||||
graphs.at(current).at(horizon) += graph_symbol.at((result.at(0) * 5 + result.at(1)));
|
||||
}
|
||||
}
|
||||
else graphs.at(current).at(horizon) += graph_symbol.at((result.at(0) * 5 + result.at(1)));
|
||||
}
|
||||
if (mult and i >= 0) last = data_value;
|
||||
}
|
||||
last = data_value;
|
||||
out.clear();
|
||||
if (height == 1) {
|
||||
if (not color_gradient.empty())
|
||||
out += (last < 1 and not color_gradient.empty() ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(clamp(last, 0ll, 100ll)));
|
||||
//if (not color_gradient.empty())
|
||||
// out += (last < 1 ? Theme::c("inactive_fg") : Theme::g(color_gradient).at(clamp(last, 0ll, 100ll)));
|
||||
out += graphs.at(current).at(0);
|
||||
}
|
||||
else {
|
||||
|
@ -431,7 +438,7 @@ namespace Draw {
|
|||
//? Populate the two switching graph vectors and fill empty space if data size < width
|
||||
for (const int& i : iota(0, height * 2)) {
|
||||
if (tty_mode and i % 2 != current) continue;
|
||||
graphs[(i % 2 != 0)].push_back((value_width < width) ? ((height == 1) ? Mv::r(1) : " "s) * (width - value_width) : "");
|
||||
graphs[(i % 2 != 0)].push_back((value_width < width) ? ((height == 1) ? Mv::r(1) : " "s) * (width - value_width) : "");
|
||||
}
|
||||
if (data.size() == 0) return;
|
||||
this->_create(data, data_offset);
|
||||
|
@ -443,7 +450,11 @@ namespace Draw {
|
|||
//? Make room for new characters on graph
|
||||
if (not tty_mode) current = not current;
|
||||
for (const int& i : iota(0, height)) {
|
||||
if (graphs.at(current).at(i).at(1) == '[') graphs.at(current).at(i).erase(0, 4);
|
||||
if (height == 1 and graphs.at(current).at(i).at(1) == '[') {
|
||||
if (graphs.at(current).at(i).at(3) == 'C') graphs.at(current).at(i).erase(0, 4);
|
||||
else graphs.at(current).at(i).erase(0, graphs.at(current).at(i).find_first_of('m') + 4);
|
||||
}
|
||||
else if (graphs.at(current).at(i).at(0) == ' ') graphs.at(current).at(i).erase(0, 1);
|
||||
else graphs.at(current).at(i).erase(0, 3);
|
||||
}
|
||||
this->_create(data, (int)data.size() - 1);
|
||||
|
@ -472,21 +483,6 @@ namespace Cpu {
|
|||
vector<Draw::Graph> core_graphs;
|
||||
vector<Draw::Graph> temp_graphs;
|
||||
|
||||
unsigned long fastrand(void) {
|
||||
static unsigned long x=123456789, y=362436069, z=521288629;
|
||||
unsigned long t;
|
||||
x ^= x << 16;
|
||||
x ^= x >> 5;
|
||||
x ^= x << 1;
|
||||
|
||||
t = x;
|
||||
x = y;
|
||||
y = z;
|
||||
z = t ^ x ^ y;
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
string draw(const cpu_info& cpu, const bool force_redraw, const bool data_same) {
|
||||
if (Runner::stopping) return "";
|
||||
if (force_redraw) redraw = true;
|
||||
|
@ -504,6 +500,7 @@ namespace Cpu {
|
|||
const string& title_left = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_left_down : Symbols::title_left);
|
||||
const string& title_right = Theme::c("cpu_box") + (cpu_bottom ? Symbols::title_right_down : Symbols::title_right);
|
||||
static int bat_pos = 0, bat_len = 0;
|
||||
if (cpu.cpu_percent.at("total").empty() or cpu.core_percent.at(0).empty() or (show_temps and cpu.temp.at(0).empty())) return "";
|
||||
string out;
|
||||
out.reserve(width * height);
|
||||
|
||||
|
@ -541,15 +538,15 @@ namespace Cpu {
|
|||
if (b_column_size > 0 or extra_width > 0) {
|
||||
core_graphs.clear();
|
||||
for (const auto& core_data : cpu.core_percent) {
|
||||
core_graphs.emplace_back(5 * b_column_size + extra_width, 1, "", core_data, graph_symbol);
|
||||
core_graphs.emplace_back(5 * b_column_size + extra_width, 1, "cpu", core_data, graph_symbol);
|
||||
}
|
||||
}
|
||||
if (show_temps) {
|
||||
temp_graphs.clear();
|
||||
temp_graphs.emplace_back(5, 1, "", cpu.temp.at(0), graph_symbol, false, false, cpu.temp_max, -23);
|
||||
temp_graphs.emplace_back(5, 1, "temp", cpu.temp.at(0), graph_symbol, false, false, cpu.temp_max, -23);
|
||||
if (not hide_cores and b_column_size > 1) {
|
||||
for (const auto& i : iota((size_t)1, cpu.temp.size())) {
|
||||
temp_graphs.emplace_back(5, 1, "", cpu.temp.at(i), graph_symbol, false, false, cpu.temp_max, -23);
|
||||
temp_graphs.emplace_back(5, 1, "temp", cpu.temp.at(i), graph_symbol, false, false, cpu.temp_max, -23);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -587,7 +584,7 @@ namespace Cpu {
|
|||
|
||||
out += Mv::to(y, bat_pos) + title_left + Theme::c("title") + Fx::b + "BAT" + bat_symbol + ' ' + str_percent
|
||||
+ (Term::width >= 100 ? Fx::ub + ' ' + bat_meter(percent) + Fx::b : "")
|
||||
+ (not str_time.empty() ? ' ' + Theme::c("title") + str_time : "") + Fx::ub + title_right;
|
||||
+ (not str_time.empty() ? ' ' + Theme::c("title") + str_time : " ") + Fx::ub + title_right;
|
||||
}
|
||||
}
|
||||
else if (bat_pos > 0) {
|
||||
|
@ -639,16 +636,16 @@ namespace Cpu {
|
|||
+ ljust(to_string(n), core_width);
|
||||
if (b_column_size > 0 or extra_width > 0)
|
||||
out += Theme::c("inactive_fg") + graph_bg * (5 * b_column_size + extra_width) + Mv::l(5 * b_column_size + extra_width)
|
||||
+ Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll)) + core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw);
|
||||
else
|
||||
out += Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll));
|
||||
+ core_graphs.at(n)(cpu.core_percent.at(n), data_same or redraw);
|
||||
|
||||
out += Theme::g("cpu").at(clamp(cpu.core_percent.at(n).back(), 0ll, 100ll));
|
||||
out += rjust(to_string(cpu.core_percent.at(n).back()), (b_column_size < 2 ? 3 : 4)) + Theme::c("main_fg") + '%';
|
||||
|
||||
if (show_temps and not hide_cores) {
|
||||
const auto [temp, unit] = celsius_to(cpu.temp.at(n+1).back(), temp_scale);
|
||||
const auto& temp_color = Theme::g("temp").at(clamp(cpu.temp.at(n+1).back() * 100 / cpu.temp_max, 0ll, 100ll));
|
||||
if (b_column_size > 1)
|
||||
out += ' ' + Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5) + temp_color
|
||||
out += ' ' + Theme::c("inactive_fg") + graph_bg * 5 + Mv::l(5)
|
||||
+ temp_graphs.at(n+1)(cpu.temp.at(n+1), data_same or redraw);
|
||||
out += temp_color + rjust(to_string(temp), 4) + Theme::c("main_fg") + unit;
|
||||
}
|
||||
|
@ -711,6 +708,7 @@ namespace Mem {
|
|||
auto& tty_mode = Config::getB("tty_mode");
|
||||
auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_mem"));
|
||||
auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6);
|
||||
auto totalMem = Mem::get_totalMem();
|
||||
string out;
|
||||
out.reserve(height * width);
|
||||
|
||||
|
@ -765,7 +763,7 @@ namespace Mem {
|
|||
for (const auto& [name, disk] : mem.disks) {
|
||||
if (disk.io_read.empty()) continue;
|
||||
|
||||
io_graphs[name + "_activity"] = Draw::Graph{disks_width - 6, 1, "", disk.io_activity, graph_symbol};
|
||||
io_graphs[name + "_activity"] = Draw::Graph{disks_width - 6, 1, "available", disk.io_activity, graph_symbol};
|
||||
|
||||
if (io_mode) {
|
||||
//? Create one combined graph for IO read/write if enabled
|
||||
|
@ -804,7 +802,7 @@ namespace Mem {
|
|||
string up = (graph_height >= 2 ? Mv::l(mem_width - 2) + Mv::u(graph_height - 1) : "");
|
||||
bool big_mem = mem_width > 21;
|
||||
|
||||
out += Mv::to(y + 1, x + 2) + Theme::c("title") + Fx::b + "Total:" + rjust(floating_humanizer(Shared::totalMem), mem_width - 9) + Fx::ub + Theme::c("main_fg");
|
||||
out += Mv::to(y + 1, x + 2) + Theme::c("title") + Fx::b + "Total:" + rjust(floating_humanizer(totalMem), mem_width - 9) + Fx::ub + Theme::c("main_fg");
|
||||
vector<string> comb_names (mem_names.begin(), mem_names.end());
|
||||
if (show_swap and has_swap and not swap_disk) comb_names.insert(comb_names.end(), swap_names.begin(), swap_names.end());
|
||||
for (auto name : comb_names) {
|
||||
|
@ -828,7 +826,7 @@ namespace Mem {
|
|||
const string humanized = floating_humanizer(mem.stats.at(name));
|
||||
const string graphics = (use_graphs ? mem_graphs.at(name)(mem.percent.at(name), redraw or data_same) : mem_meters.at(name)(mem.percent.at(name).back()));
|
||||
if (mem_size > 2) {
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + ljust(title, 4, false, false, not big_mem) + ljust(":", (big_mem ? 1 : 6))
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + title.substr(0, big_mem ? 10 : 5) + ":"
|
||||
+ Mv::to(y+1+cy, x+cx + mem_width - 2 - humanized.size()) + trans(humanized)
|
||||
+ Mv::to(y+2+cy, x+cx + (graph_height >= 2 ? 0 : 1)) + graphics + up + rjust(to_string(mem.percent.at(name).back()) + "%", 4);
|
||||
cy += (graph_height == 0 ? 2 : graph_height + 1);
|
||||
|
@ -848,6 +846,7 @@ namespace Mem {
|
|||
cx = mem_width; cy = 0;
|
||||
const bool big_disk = disks_width >= 25;
|
||||
divider = Mv::l(1) + Theme::c("div_line") + Symbols::div_left + Symbols::h_line * disks_width + Theme::c("mem_box") + Fx::ub + Symbols::div_right + Mv::l(disks_width);
|
||||
const string hu_div = Theme::c("div_line") + Symbols::h_line + Theme::c("main_fg");
|
||||
if (io_mode) {
|
||||
for (const auto& mount : mem.disks_order) {
|
||||
if (not disks.contains(mount)) continue;
|
||||
|
@ -855,13 +854,13 @@ namespace Mem {
|
|||
const auto& disk = disks.at(mount);
|
||||
if (disk.io_read.empty()) continue;
|
||||
const string total = floating_humanizer(disk.total, not big_disk);
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - total.size())
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 8) + Mv::to(y+1+cy, x+cx + disks_width - total.size())
|
||||
+ trans(total) + Fx::ub;
|
||||
if (big_disk) {
|
||||
const string used_percent = to_string(disk.used_percent);
|
||||
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2)) + Theme::c("main_fg") + used_percent + '%';
|
||||
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)used_percent.size() / 2) - 1) + hu_div + used_percent + '%' + hu_div;
|
||||
}
|
||||
out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll))
|
||||
out += Mv::to(y+2+cy++, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6)
|
||||
+ Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg");
|
||||
if (++cy > height - 3) break;
|
||||
if (io_graph_combined) {
|
||||
|
@ -890,21 +889,21 @@ namespace Mem {
|
|||
if (cy > height - 3) break;
|
||||
const auto& disk = disks.at(mount);
|
||||
auto comb_val = (not disk.io_read.empty() ? disk.io_read.back() + disk.io_write.back() : 0ll);
|
||||
const string human_io = (comb_val > 0 and big_disk ? (disk.io_write.back() > 0 ? "▼"s : ""s) + (disk.io_read.back() > 0 ? "▲"s : ""s)
|
||||
const string human_io = (comb_val > 0 ? (disk.io_write.back() > 0 and big_disk ? "▼"s : ""s) + (disk.io_read.back() > 0 and big_disk ? "▲"s : ""s)
|
||||
+ floating_humanizer(comb_val, true) : "");
|
||||
const string human_total = floating_humanizer(disk.total, not big_disk);
|
||||
const string human_used = floating_humanizer(disk.used, not big_disk);
|
||||
const string human_free = floating_humanizer(disk.free, not big_disk);
|
||||
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 2) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size())
|
||||
out += Mv::to(y+1+cy, x+1+cx) + divider + Theme::c("title") + Fx::b + uresize(disk.name, disks_width - 8) + Mv::to(y+1+cy, x+cx + disks_width - human_total.size())
|
||||
+ trans(human_total) + Fx::ub + Theme::c("main_fg");
|
||||
if (big_disk and not human_io.empty())
|
||||
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2)) + Theme::c("main_fg") + human_io;
|
||||
out += Mv::to(y+1+cy, x+1+cx + round((double)disks_width / 2) - round((double)human_io.size() / 2) - 1) + hu_div + human_io + hu_div;
|
||||
if (++cy > height - 3) break;
|
||||
if (show_io_stat and io_graphs.contains(mount + "_activity")) {
|
||||
out += Mv::to(y+1+cy, x+1+cx) + (big_disk ? " IO% " : " IO " + Mv::l(2)) + Theme::c("inactive_fg") + graph_bg * (disks_width - 6) + Theme::g("available").at(clamp(disk.io_activity.back(), 50ll, 100ll))
|
||||
+ Mv::l(disks_width - 6) + io_graphs.at(mount + "_activity")(disk.io_activity, redraw or data_same) + Theme::c("main_fg");
|
||||
if (not big_disk) out += Mv::to(y+1+cy, x+cx) + Theme::c("main_fg") + human_io;
|
||||
if (not big_disk) out += Mv::to(y+1+cy, x+cx+1) + Theme::c("main_fg") + human_io;
|
||||
if (++cy > height - 3) break;
|
||||
}
|
||||
|
||||
|
@ -959,8 +958,8 @@ namespace Net {
|
|||
const string title_left = Theme::c("net_box") + Fx::ub + Symbols::title_left;
|
||||
const string title_right = Theme::c("net_box") + Fx::ub + Symbols::title_right;
|
||||
const int i_size = min((int)selected_iface.size(), 10);
|
||||
const long long down_max = (net_auto ? graph_max.at("download") : (long long)(Config::getI("net_download") << 20) / 8);
|
||||
const long long up_max = (net_auto ? graph_max.at("upload") : (long long)(Config::getI("net_upload") << 20) / 8);
|
||||
const long long down_max = (net_auto ? graph_max.at("download") : ((long long)(Config::getI("net_download")) << 20) / 8);
|
||||
const long long up_max = (net_auto ? graph_max.at("upload") : ((long long)(Config::getI("net_upload")) << 20) / 8);
|
||||
|
||||
//* Redraw elements not needed to be updated every cycle
|
||||
if (redraw) {
|
||||
|
@ -974,13 +973,13 @@ namespace Net {
|
|||
|
||||
//? Interface selector and buttons
|
||||
|
||||
out += Mv::to(y, x+width - i_size - 10) + title_left + Fx::b + Theme::c("hi_fg") + "<b " + Theme::c("title")
|
||||
out += Mv::to(y, x+width - i_size - 9) + title_left + Fx::b + Theme::c("hi_fg") + "<b " + Theme::c("title")
|
||||
+ uresize(selected_iface, 10) + Theme::c("hi_fg") + " n>" + title_right
|
||||
+ Mv::to(y, x+width - i_size - 16) + title_left + Theme::c("hi_fg") + (net.stat.at("download").offset + net.stat.at("upload").offset > 0 ? Fx::b : "") + 'z'
|
||||
+ Mv::to(y, x+width - i_size - 15) + title_left + Theme::c("hi_fg") + (net.stat.at("download").offset + net.stat.at("upload").offset > 0 ? Fx::b : "") + 'z'
|
||||
+ Theme::c("title") + "ero" + title_right;
|
||||
Input::mouse_mappings["b"] = {y, x+width - i_size - 9, 1, 3};
|
||||
Input::mouse_mappings["b"] = {y, x+width - i_size - 8, 1, 3};
|
||||
Input::mouse_mappings["n"] = {y, x+width - 6, 1, 3};
|
||||
Input::mouse_mappings["z"] = {y, x+width - i_size - 15, 1, 4};
|
||||
Input::mouse_mappings["z"] = {y, x+width - i_size - 14, 1, 4};
|
||||
if (width - i_size - 20 > 6) {
|
||||
out += Mv::to(y, x+width - i_size - 21) + title_left + Theme::c("hi_fg") + (net_auto ? Fx::b : "") + 'a' + Theme::c("title") + "uto" + title_right;
|
||||
Input::mouse_mappings["a"] = {y, x+width - i_size - 20, 1, 4};
|
||||
|
@ -1033,9 +1032,10 @@ namespace Proc {
|
|||
int x, y, width = 20, height;
|
||||
int start, selected, select_max;
|
||||
bool shown = true, redraw = true;
|
||||
int selected_pid = 0;
|
||||
int selected_pid = 0, selected_depth = 0;
|
||||
string selected_name;
|
||||
unordered_flat_map<size_t, Draw::Graph> p_graphs;
|
||||
unordered_flat_map<size_t, bool> p_wide_cmd;
|
||||
unordered_flat_map<size_t, int> p_counters;
|
||||
int counter = 0;
|
||||
Draw::TextEdit filter;
|
||||
|
@ -1051,9 +1051,10 @@ namespace Proc {
|
|||
auto selected = Config::getI("proc_selected");
|
||||
auto last_selected = Config::getI("proc_last_selected");
|
||||
const int select_max = (Config::getB("show_detailed") ? Proc::select_max - 8 : Proc::select_max);
|
||||
auto& vim_keys = Config::getB("vim_keys");
|
||||
|
||||
int numpids = Proc::numpids;
|
||||
if (cmd_key == "up" and selected > 0) {
|
||||
if ((cmd_key == "up" or (vim_keys and cmd_key == "k")) and selected > 0) {
|
||||
if (start > 0 and selected == 1) start--;
|
||||
else selected--;
|
||||
if (Config::getI("proc_last_selected") > 0) Config::set("proc_last_selected", 0);
|
||||
|
@ -1064,7 +1065,7 @@ namespace Proc {
|
|||
else if (cmd_key == "mouse_scroll_down" and start < numpids - select_max) {
|
||||
start = min(numpids - select_max, start + 3);
|
||||
}
|
||||
else if (cmd_key == "down") {
|
||||
else if (cmd_key == "down" or (vim_keys and cmd_key == "j")) {
|
||||
if (start < numpids - select_max and selected == select_max) start++;
|
||||
else if (selected == 0 and last_selected > 0) {
|
||||
selected = last_selected;
|
||||
|
@ -1080,11 +1081,11 @@ namespace Proc {
|
|||
if (selected > 0 and start >= numpids - select_max) selected = select_max;
|
||||
else start = clamp(start + select_max, 0, max(0, numpids - select_max));
|
||||
}
|
||||
else if (cmd_key == "home") {
|
||||
else if (cmd_key == "home" or (vim_keys and cmd_key == "g")) {
|
||||
start = 0;
|
||||
if (selected > 0) selected = 1;
|
||||
}
|
||||
else if (cmd_key == "end") {
|
||||
else if (cmd_key == "end" or (vim_keys and cmd_key == "G")) {
|
||||
start = max(0, numpids - select_max);
|
||||
if (selected > 0) selected = select_max;
|
||||
}
|
||||
|
@ -1115,11 +1116,14 @@ namespace Proc {
|
|||
auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_proc"));
|
||||
auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6);
|
||||
auto& mem_bytes = Config::getB("proc_mem_bytes");
|
||||
auto& vim_keys = Config::getB("vim_keys");
|
||||
auto& show_graphs = Config::getB("proc_cpu_graphs");
|
||||
start = Config::getI("proc_start");
|
||||
selected = Config::getI("proc_selected");
|
||||
const int y = show_detailed ? Proc::y + 8 : Proc::y;
|
||||
const int height = show_detailed ? Proc::height - 8 : Proc::height;
|
||||
const int select_max = show_detailed ? Proc::select_max - 8 : Proc::select_max;
|
||||
auto totalMem = Mem::get_totalMem();
|
||||
int numpids = Proc::numpids;
|
||||
if (force_redraw) redraw = true;
|
||||
string out;
|
||||
|
@ -1141,6 +1145,10 @@ namespace Proc {
|
|||
prog_size = (width > 70 ? 16 : ( width > 55 ? 8 : width - user_size - thread_size - 33));
|
||||
cmd_size = (width > 55 ? width - prog_size - user_size - thread_size - 33 : -1);
|
||||
tree_size = width - user_size - thread_size - 23;
|
||||
if (not show_graphs) {
|
||||
cmd_size += 5;
|
||||
tree_size += 5;
|
||||
}
|
||||
|
||||
//? Detailed box
|
||||
if (show_detailed) {
|
||||
|
@ -1178,7 +1186,7 @@ namespace Proc {
|
|||
if (alive and selected == 0) Input::mouse_mappings["t"] = {d_y, mouse_x, 1, 9};
|
||||
mouse_x += 11;
|
||||
}
|
||||
out += title_left + hi_color + Fx::b + 'k' + t_color + "ill" + Fx::ub + title_right
|
||||
out += title_left + hi_color + Fx::b + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right
|
||||
+ title_left + hi_color + Fx::b + 's' + t_color + "ignals" + Fx::ub + title_right
|
||||
+ Mv::to(d_y, d_x + d_width - 10) + title_left + t_color + Fx::b + hide + Symbols::enter + Fx::ub + title_right;
|
||||
if (alive and selected == 0) {
|
||||
|
@ -1271,7 +1279,7 @@ namespace Proc {
|
|||
mouse_x += 11;
|
||||
}
|
||||
if (width > 55) {
|
||||
out += title_left_down + Fx::b + hi_color + 'k' + t_color + "ill" + Fx::ub + title_right_down;
|
||||
out += title_left_down + Fx::b + hi_color + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right_down;
|
||||
if (selected > 0) Input::mouse_mappings["k"] = {y + height - 1, mouse_x, 1, 4};
|
||||
mouse_x += 6;
|
||||
}
|
||||
|
@ -1291,7 +1299,7 @@ namespace Proc {
|
|||
out += (thread_size > 0 ? Mv::l(4) + "Threads: " : "")
|
||||
+ ljust("User:", user_size) + ' '
|
||||
+ rjust((mem_bytes ? "MemB" : "Mem%"), 5) + ' '
|
||||
+ rjust("Cpu%", 10) + Fx::ub;
|
||||
+ rjust("Cpu%", (show_graphs ? 10 : 5)) + Fx::ub;
|
||||
}
|
||||
//* End of redraw block
|
||||
|
||||
|
@ -1325,7 +1333,7 @@ namespace Proc {
|
|||
if (item_fit >= 8) out += cjust(to_string(detailed.entry.p_nice), item_width);
|
||||
|
||||
|
||||
const double mem_p = (double)detailed.mem_bytes.back() * 100 / Shared::totalMem;
|
||||
const double mem_p = (double)detailed.mem_bytes.back() * 100 / totalMem;
|
||||
string mem_str = to_string(mem_p);
|
||||
mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4));
|
||||
out += Mv::to(d_y + 4, d_x + 1) + Theme::c("title") + Fx::b + rjust((item_fit > 4 ? "Memory: " : "M:") + mem_str + "% ", (d_width / 3) - 2)
|
||||
|
@ -1352,11 +1360,12 @@ namespace Proc {
|
|||
if (is_selected) {
|
||||
selected_pid = (int)p.pid;
|
||||
selected_name = p.name;
|
||||
selected_depth = p.depth;
|
||||
}
|
||||
|
||||
//? Update graphs for processes with above 0.0% cpu usage, delete if below 0.1% 10x times
|
||||
const bool has_graph = p_counters.contains(p.pid);
|
||||
if ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph)) {
|
||||
const bool has_graph = show_graphs ? p_counters.contains(p.pid) : false;
|
||||
if (show_graphs and ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph))) {
|
||||
if (not has_graph) {
|
||||
p_graphs[p.pid] = Draw::Graph{5, 1, "", {}, graph_symbol};
|
||||
p_counters[p.pid] = 0;
|
||||
|
@ -1383,7 +1392,7 @@ namespace Proc {
|
|||
if (proc_colors) {
|
||||
end = Theme::c("main_fg") + Fx::ub;
|
||||
array<string, 3> colors;
|
||||
for (int i = 0; int v : {(int)round(p.cpu_p), (int)round(p.mem * 100 / Shared::totalMem), (int)p.threads / 3}) {
|
||||
for (int i = 0; int v : {(int)round(p.cpu_p), (int)round(p.mem * 100 / totalMem), (int)p.threads / 3}) {
|
||||
if (proc_gradient) {
|
||||
int val = (min(v, 100) + 100) - calc * 100 / select_max;
|
||||
if (val < 100) colors[i++] = Theme::g("proc_color").at(max(0, val));
|
||||
|
@ -1403,12 +1412,14 @@ namespace Proc {
|
|||
}
|
||||
}
|
||||
|
||||
if (not p_wide_cmd.contains(p.pid)) p_wide_cmd[p.pid] = ulen(p.cmd) != ulen(p.cmd, true);
|
||||
|
||||
//? Normal view line
|
||||
if (not proc_tree) {
|
||||
out += Mv::to(y+2+lc, x+1)
|
||||
+ g_color + rjust(to_string(p.pid), 8) + ' '
|
||||
+ c_color + ljust(p.name, prog_size, true) + ' ' + end
|
||||
+ (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, true) + ' ' : "");
|
||||
+ (cmd_size > 0 ? g_color + ljust(p.cmd, cmd_size, true, p_wide_cmd[p.pid]) + Mv::to(y+2+lc, x+11+prog_size+cmd_size) + ' ' : "");
|
||||
}
|
||||
//? Tree view line
|
||||
else {
|
||||
|
@ -1421,17 +1432,23 @@ namespace Proc {
|
|||
width_left -= (ulen(p.name) + 1);
|
||||
}
|
||||
if (width_left > 7 and p.short_cmd != p.name) {
|
||||
out += g_color + '(' + uresize(p.short_cmd, width_left - 3, true) + ") ";
|
||||
out += g_color + '(' + uresize(p.short_cmd, width_left - 3, p_wide_cmd[p.pid]) + ") ";
|
||||
width_left -= (ulen(p.short_cmd, true) + 3);
|
||||
}
|
||||
out += string(max(0, width_left), ' ');
|
||||
out += string(max(0, width_left), ' ') + Mv::to(y+2+lc, x+2+tree_size);
|
||||
}
|
||||
//? Common end of line
|
||||
string cpu_str = to_string(p.cpu_p);
|
||||
if (p.cpu_p < 10 or p.cpu_p >= 100) cpu_str.resize(3);
|
||||
if (p.cpu_p < 10 or (p.cpu_p >= 100 and p.cpu_p < 1000)) cpu_str.resize(3);
|
||||
else if (p.cpu_p >= 10'000) {
|
||||
cpu_str = to_string(p.cpu_p / 1000);
|
||||
cpu_str.resize(3);
|
||||
if (cpu_str.ends_with('.')) cpu_str.pop_back();
|
||||
cpu_str += "k";
|
||||
}
|
||||
string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : "");
|
||||
if (not mem_bytes) {
|
||||
double mem_p = clamp((double)p.mem * 100 / Shared::totalMem, 0.0, 100.0);
|
||||
double mem_p = clamp((double)p.mem * 100 / totalMem, 0.0, 100.0);
|
||||
mem_str = to_string(mem_p);
|
||||
if (mem_str.size() < 4) mem_str = "0";
|
||||
else mem_str.resize((mem_p < 10 or mem_p >= 100 ? 3 : 4));
|
||||
|
@ -1440,7 +1457,7 @@ namespace Proc {
|
|||
out += (thread_size > 0 ? t_color + rjust(to_string(min(p.threads, (size_t)9999)), thread_size) + ' ' + end : "" )
|
||||
+ g_color + ljust((cmp_greater(p.user.size(), user_size) ? p.user.substr(0, user_size - 1) + '+' : p.user), user_size) + ' '
|
||||
+ m_color + rjust(mem_str, 5) + end + ' '
|
||||
+ (is_selected ? "" : Theme::c("inactive_fg")) + graph_bg * 5
|
||||
+ (is_selected ? "" : Theme::c("inactive_fg")) + (show_graphs ? graph_bg * 5: "")
|
||||
+ (p_graphs.contains(p.pid) ? Mv::l(5) + c_color + p_graphs.at(p.pid)({(p.cpu_p >= 0.1 and p.cpu_p < 5 ? 5ll : (long long)round(p.cpu_p))}, data_same) : "") + end + ' '
|
||||
+ c_color + rjust(cpu_str, 4) + " " + end;
|
||||
if (lc++ > height - 5) break;
|
||||
|
@ -1476,6 +1493,15 @@ namespace Proc {
|
|||
}
|
||||
p_graphs.compact();
|
||||
p_counters.compact();
|
||||
|
||||
for (auto element = p_wide_cmd.begin(); element != p_wide_cmd.end();) {
|
||||
if (rng::find(plist, element->first, &proc_info::pid) == plist.end()) {
|
||||
element = p_wide_cmd.erase(element);
|
||||
}
|
||||
else
|
||||
++element;
|
||||
}
|
||||
p_wide_cmd.compact();
|
||||
}
|
||||
|
||||
if (selected == 0 and selected_pid != 0) {
|
||||
|
@ -1653,4 +1679,4 @@ namespace Draw {
|
|||
box = createBox(x, y, width, height, Theme::c("proc_box"), true, "proc", "", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Symbols {
|
|||
const string down = "↓";
|
||||
const string left = "←";
|
||||
const string right = "→";
|
||||
const string enter = "↲";
|
||||
const string enter = "↵";
|
||||
}
|
||||
|
||||
namespace Draw {
|
||||
|
|
|
@ -19,6 +19,8 @@ tab-size = 4
|
|||
#include <iostream>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <btop_input.hpp>
|
||||
#include <btop_tools.hpp>
|
||||
|
@ -72,20 +74,74 @@ namespace Input {
|
|||
};
|
||||
|
||||
std::atomic<bool> interrupt (false);
|
||||
std::atomic<bool> polling (false);
|
||||
array<int, 2> mouse_pos;
|
||||
unordered_flat_map<string, Mouse_loc> mouse_mappings;
|
||||
|
||||
deque<string> history(50, "");
|
||||
string old_filter;
|
||||
|
||||
struct InputThr {
|
||||
InputThr() : thr(run, this) {
|
||||
}
|
||||
|
||||
static void run(InputThr* that) {
|
||||
that->runImpl();
|
||||
}
|
||||
|
||||
void runImpl() {
|
||||
char ch = 0;
|
||||
|
||||
// TODO(pg83): read whole buffer
|
||||
while (cin.get(ch)) {
|
||||
std::lock_guard<std::mutex> g(lock);
|
||||
current.push_back(ch);
|
||||
if (current.size() > 100) {
|
||||
current.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t avail() {
|
||||
std::lock_guard<std::mutex> g(lock);
|
||||
|
||||
return current.size();
|
||||
}
|
||||
|
||||
std::string get() {
|
||||
std::string res;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> g(lock);
|
||||
|
||||
res.swap(current);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static InputThr& instance() {
|
||||
// intentional memory leak, to simplify shutdown process
|
||||
static InputThr* input = new InputThr();
|
||||
|
||||
return *input;
|
||||
}
|
||||
|
||||
std::string current;
|
||||
// TODO(pg83): use std::conditional_variable instead of sleep
|
||||
std::mutex lock;
|
||||
std::thread thr;
|
||||
};
|
||||
|
||||
bool poll(int timeout) {
|
||||
if (timeout < 1) return cin.rdbuf()->in_avail() > 0;
|
||||
atomic_lock lck(polling);
|
||||
if (timeout < 1) return InputThr::instance().avail() > 0;
|
||||
while (timeout > 0) {
|
||||
if (interrupt) {
|
||||
interrupt = false;
|
||||
return false;
|
||||
}
|
||||
if (cin.rdbuf()->in_avail() > 0) return true;
|
||||
if (InputThr::instance().avail() > 0) return true;
|
||||
sleep_ms(timeout < 10 ? timeout : 10);
|
||||
timeout -= 10;
|
||||
}
|
||||
|
@ -93,9 +149,7 @@ namespace Input {
|
|||
}
|
||||
|
||||
string get() {
|
||||
string key;
|
||||
while (cin.rdbuf()->in_avail() > 0 and key.size() < 100) key += cin.get();
|
||||
if (cin.rdbuf()->in_avail() > 0) cin.ignore(cin.rdbuf()->in_avail());
|
||||
string key = InputThr::instance().get();
|
||||
if (not key.empty()) {
|
||||
//? Remove escape code prefix if present
|
||||
if (key.substr(0, 2) == Fx::e) {
|
||||
|
@ -105,14 +159,14 @@ namespace Input {
|
|||
if (key.starts_with("[<")) {
|
||||
std::string_view key_view = key;
|
||||
string mouse_event;
|
||||
if (key_view.starts_with("[<0;") and key_view.ends_with('M')) {
|
||||
if (key_view.starts_with("[<0;") and key_view.find('M') != std::string_view::npos) {
|
||||
mouse_event = "mouse_click";
|
||||
key_view.remove_prefix(4);
|
||||
}
|
||||
else if (key_view.starts_with("[<0;") and key_view.ends_with('m')) {
|
||||
mouse_event = "mouse_release";
|
||||
key_view.remove_prefix(4);
|
||||
}
|
||||
// else if (key_view.starts_with("[<0;") and key_view.ends_with('m')) {
|
||||
// mouse_event = "mouse_release";
|
||||
// key_view.remove_prefix(4);
|
||||
// }
|
||||
else if (key_view.starts_with("[<64;")) {
|
||||
mouse_event = "mouse_scroll_up";
|
||||
key_view.remove_prefix(5);
|
||||
|
@ -168,32 +222,34 @@ namespace Input {
|
|||
}
|
||||
|
||||
string wait() {
|
||||
while (cin.rdbuf()->in_avail() < 1) {
|
||||
while (InputThr::instance().avail() < 1) {
|
||||
sleep_ms(10);
|
||||
}
|
||||
return get();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (cin.rdbuf()->in_avail() > 0) cin.ignore(SSmax);
|
||||
// do not need it, actually
|
||||
}
|
||||
|
||||
void process(const string& key) {
|
||||
if (key.empty()) return;
|
||||
try {
|
||||
auto& filtering = Config::getB("proc_filtering");
|
||||
|
||||
auto& vim_keys = Config::getB("vim_keys");
|
||||
auto help_key = (vim_keys ? "H" : "h");
|
||||
auto kill_key = (vim_keys ? "K" : "k");
|
||||
//? Global input actions
|
||||
if (not filtering) {
|
||||
bool keep_going = false;
|
||||
if (str_to_lower(key) == "q") {
|
||||
exit(0);
|
||||
clean_quit(0);
|
||||
}
|
||||
else if (is_in(key, "escape", "m")) {
|
||||
Menu::show(Menu::Menus::Main);
|
||||
return;
|
||||
}
|
||||
else if (is_in(key, "F1", "h")) {
|
||||
else if (is_in(key, "F1", "?", help_key)) {
|
||||
Menu::show(Menu::Menus::Help);
|
||||
return;
|
||||
}
|
||||
|
@ -235,11 +291,15 @@ namespace Input {
|
|||
bool no_update = true;
|
||||
bool redraw = true;
|
||||
if (filtering) {
|
||||
if (key == "enter") {
|
||||
if (key == "enter" or key == "down") {
|
||||
Config::set("proc_filter", Proc::filter.text);
|
||||
Config::set("proc_filtering", false);
|
||||
old_filter.clear();
|
||||
}
|
||||
old_filter.clear();
|
||||
if(key == "down"){
|
||||
process("down");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (key == "escape" or key == "mouse_click") {
|
||||
Config::set("proc_filter", old_filter);
|
||||
Config::set("proc_filtering", false);
|
||||
|
@ -252,19 +312,19 @@ namespace Input {
|
|||
else
|
||||
return;
|
||||
}
|
||||
else if (key == "left") {
|
||||
else if (key == "left" or (vim_keys and key == "h")) {
|
||||
int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting"));
|
||||
if (--cur_i < 0)
|
||||
cur_i = Proc::sort_vector.size() - 1;
|
||||
Config::set("proc_sorting", Proc::sort_vector.at(cur_i));
|
||||
}
|
||||
else if (key == "right") {
|
||||
else if (key == "right" or (vim_keys and key == "l")) {
|
||||
int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting"));
|
||||
if (std::cmp_greater(++cur_i, Proc::sort_vector.size() - 1))
|
||||
cur_i = 0;
|
||||
Config::set("proc_sorting", Proc::sort_vector.at(cur_i));
|
||||
}
|
||||
else if (key == "f") {
|
||||
else if (is_in(key, "f", "/")) {
|
||||
Config::flip("proc_filtering");
|
||||
Proc::filter = { Config::getS("proc_filter") };
|
||||
old_filter = Proc::filter.text;
|
||||
|
@ -294,7 +354,16 @@ namespace Input {
|
|||
const auto& current_selection = Config::getI("proc_selected");
|
||||
if (current_selection == line - y - 1) {
|
||||
redraw = true;
|
||||
goto proc_mouse_enter;
|
||||
if (Config::getB("proc_tree")) {
|
||||
const int x_pos = col - Proc::x;
|
||||
const int offset = Config::getI("selected_depth") * 3;
|
||||
if (x_pos > offset and x_pos < 4 + offset) {
|
||||
process("space");
|
||||
return;
|
||||
}
|
||||
}
|
||||
process("enter");
|
||||
return;
|
||||
}
|
||||
else if (current_selection == 0 or line - y - 1 == 0)
|
||||
redraw = true;
|
||||
|
@ -320,7 +389,6 @@ namespace Input {
|
|||
keep_going = true;
|
||||
}
|
||||
else if (key == "enter") {
|
||||
proc_mouse_enter:
|
||||
if (Config::getI("proc_selected") == 0 and not Config::getB("show_detailed")) {
|
||||
return;
|
||||
}
|
||||
|
@ -344,7 +412,7 @@ namespace Input {
|
|||
if (key == "-" or key == "space") Proc::collapse = pid;
|
||||
no_update = false;
|
||||
}
|
||||
else if (is_in(key, "t", "k") and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) {
|
||||
else if (is_in(key, "t", kill_key) and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) {
|
||||
atomic_wait(Runner::active);
|
||||
if (Config::getB("show_detailed") and Config::getI("proc_selected") == 0 and Proc::detailed.status == "Dead") return;
|
||||
Menu::show(Menu::Menus::SignalSend, (key == "t" ? SIGTERM : SIGKILL));
|
||||
|
@ -356,7 +424,7 @@ namespace Input {
|
|||
Menu::show(Menu::Menus::SignalChoose);
|
||||
return;
|
||||
}
|
||||
else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end")) {
|
||||
else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k", "g", "G"))) {
|
||||
proc_mouse_scroll:
|
||||
redraw = false;
|
||||
auto old_selected = Config::getI("proc_selected");
|
||||
|
@ -463,8 +531,8 @@ namespace Input {
|
|||
ndev.stat.at("upload").offset = 0;
|
||||
}
|
||||
else {
|
||||
ndev.stat.at("download").offset = ndev.stat.at("download").last;
|
||||
ndev.stat.at("upload").offset = ndev.stat.at("upload").last;
|
||||
ndev.stat.at("download").offset = ndev.stat.at("download").last + ndev.stat.at("download").rollover;
|
||||
ndev.stat.at("upload").offset = ndev.stat.at("upload").last + ndev.stat.at("upload").rollover;
|
||||
}
|
||||
no_update = false;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace Input {
|
|||
extern unordered_flat_map<string, Mouse_loc> mouse_mappings;
|
||||
|
||||
extern atomic<bool> interrupt;
|
||||
extern atomic<bool> polling;
|
||||
|
||||
//* Mouse column and line position
|
||||
extern array<int, 2> mouse_pos;
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace Menu {
|
|||
{"4", "Toggle PROC box."},
|
||||
{"d", "Toggle disks view in MEM box."},
|
||||
{"F2, o", "Shows options."},
|
||||
{"F1, h", "Shows this window."},
|
||||
{"F1, ?, h", "Shows this window."},
|
||||
{"ctrl + z", "Sleep program and put in background."},
|
||||
{"q, ctrl + c", "Quits program."},
|
||||
{"+, -", "Add/Subtract 100ms to/from update timer."},
|
||||
|
@ -126,7 +126,7 @@ namespace Menu {
|
|||
{"z", "Toggle totals reset for current network device"},
|
||||
{"a", "Toggle auto scaling for the network graphs."},
|
||||
{"y", "Toggle synced scaling mode for network graphs."},
|
||||
{"f", "To enter a process filter."},
|
||||
{"f, /", "To enter a process filter."},
|
||||
{"delete", "Clear any entered filter."},
|
||||
{"c", "Toggle per-core cpu usage of processes."},
|
||||
{"r", "Reverse sorting order in processes box."},
|
||||
|
@ -177,6 +177,15 @@ namespace Menu {
|
|||
"Will force 16-color mode and TTY theme,",
|
||||
"set all graph symbols to \"tty\" and swap",
|
||||
"out other non tty friendly symbols."},
|
||||
{"vim_keys",
|
||||
"Enable vim keys.",
|
||||
"Set to True to enable \"h,j,k,l\" keys for",
|
||||
"directional control in lists.",
|
||||
"",
|
||||
"Conflicting keys for",
|
||||
"h (help) and k (kill)",
|
||||
"is accessible while holding shift."},
|
||||
|
||||
{"presets",
|
||||
"Define presets for the layout of the boxes.",
|
||||
"",
|
||||
|
@ -185,10 +194,10 @@ namespace Menu {
|
|||
"Max 9 presets.",
|
||||
"",
|
||||
"Format: \"box_name:P:G,box_name:P:G\"",
|
||||
"P=(0 or 1) for alternate positons.",
|
||||
"P=(0 or 1) for alternate positions.",
|
||||
"G=graph symbol to use for box.",
|
||||
"",
|
||||
"Use withespace \" \" as seprator between",
|
||||
"Use withespace \" \" as separator between",
|
||||
"different presets.",
|
||||
"",
|
||||
"Example:",
|
||||
|
@ -197,7 +206,7 @@ namespace Menu {
|
|||
"Manually set which boxes to show.",
|
||||
"",
|
||||
"Available values are \"cpu mem net proc\".",
|
||||
"Seperate values with whitespace.",
|
||||
"Separate values with whitespace.",
|
||||
"",
|
||||
"Toggle between presets with key \"p\"."},
|
||||
{"update_ms",
|
||||
|
@ -248,6 +257,14 @@ namespace Menu {
|
|||
"\"%H\" = 24h hour, \"%I\" = 12h hour",
|
||||
"\"%M\" = minute, \"%S\" = second",
|
||||
"\"%d\" = day, \"%m\" = month, \"%y\" = year"},
|
||||
{"base_10_sizes",
|
||||
"Use base 10 for bits and bytes sizes.",
|
||||
"",
|
||||
"Uses KB = 1000 instead of KiB = 1024,",
|
||||
"MB = 1000KB instead of MiB = 1024KiB,",
|
||||
"and so on.",
|
||||
"",
|
||||
"True or False."},
|
||||
{"background_update",
|
||||
"Update main ui when menus are showing.",
|
||||
"",
|
||||
|
@ -261,6 +278,13 @@ namespace Menu {
|
|||
"",
|
||||
"Show battery stats in the top right corner",
|
||||
"if a battery is present."},
|
||||
{"selected_battery",
|
||||
"Select battery.",
|
||||
"",
|
||||
"Which battery to use if multiple are present.",
|
||||
"Can be both batteries and UPS.",
|
||||
"",
|
||||
"\"Auto\" for auto detection."},
|
||||
{"log_level",
|
||||
"Set loglevel for error.log",
|
||||
"",
|
||||
|
@ -419,7 +443,7 @@ namespace Menu {
|
|||
"equals 100 percent in the io graphs.",
|
||||
"(100 MiB/s by default).",
|
||||
"",
|
||||
"Format: \"device:speed\" seperate disks with",
|
||||
"Format: \"device:speed\" separate disks with",
|
||||
"whitespace \" \".",
|
||||
"",
|
||||
"Example: \"/dev/sda:100, /dev/sdb:20\"."},
|
||||
|
@ -440,12 +464,28 @@ namespace Menu {
|
|||
"",
|
||||
"True or False."},
|
||||
{"use_fstab",
|
||||
"Read disks list from /etc/fstab.",
|
||||
"(Has no effect on macOS X)",
|
||||
"(Linux) Read disks list from /etc/fstab.",
|
||||
"",
|
||||
"This also disables only_physical.",
|
||||
"",
|
||||
"True or False."},
|
||||
{"zfs_hide_datasets",
|
||||
"(Linux) Hide ZFS datasets in disks list.",
|
||||
"",
|
||||
"Setting this to True will hide all datasets,",
|
||||
"and only show ZFS pools.",
|
||||
"",
|
||||
"(IO stats will be calculated per-pool)",
|
||||
"",
|
||||
"True or False."},
|
||||
{"disk_free_priv",
|
||||
"(Linux) Type of available disk space.",
|
||||
"",
|
||||
"Set to true to show how much disk space is",
|
||||
"available for privileged users.",
|
||||
"",
|
||||
"Set to false to show available for normal",
|
||||
"users."},
|
||||
{"disks_filter",
|
||||
"Optional filter for shown disks.",
|
||||
"",
|
||||
|
@ -459,6 +499,15 @@ namespace Menu {
|
|||
"",
|
||||
"Example:",
|
||||
"\"exclude=/boot /home/user\""},
|
||||
{"zfs_arc_cached",
|
||||
"(Linux) Count ZFS ARC as cached memory.",
|
||||
"",
|
||||
"Add ZFS ARC used to cached memory and",
|
||||
"ZFS ARC available to available memory.",
|
||||
"These are otherwise reported by the Linux",
|
||||
"kernel as used memory.",
|
||||
"",
|
||||
"True or False."},
|
||||
},
|
||||
{
|
||||
{"graph_symbol_net",
|
||||
|
@ -470,13 +519,13 @@ namespace Menu {
|
|||
{"net_download",
|
||||
"Fixed network graph download value.",
|
||||
"",
|
||||
"Value in Mebibytes, default \"100\".",
|
||||
"Value in Mebibits, default \"100\".",
|
||||
"",
|
||||
"Can be toggled with auto button."},
|
||||
{"net_upload",
|
||||
"Fixed network graph upload value.",
|
||||
"",
|
||||
"Value in Mebibytes, default \"100\".",
|
||||
"Value in Mebibits, default \"100\".",
|
||||
"",
|
||||
"Can be toggled with auto button."},
|
||||
{"net_auto",
|
||||
|
@ -519,10 +568,10 @@ namespace Menu {
|
|||
"Possible values:",
|
||||
"\"pid\", \"program\", \"arguments\", \"threads\",",
|
||||
"\"user\", \"memory\", \"cpu lazy\" and",
|
||||
"\"cpu responsive\".",
|
||||
"\"cpu direct\".",
|
||||
"",
|
||||
"\"cpu lazy\" updates top process over time.",
|
||||
"\"cpu responsive\" updates top process",
|
||||
"\"cpu direct\" updates top process",
|
||||
"directly."},
|
||||
{"proc_reversed",
|
||||
"Reverse processes sorting order.",
|
||||
|
@ -558,6 +607,15 @@ namespace Menu {
|
|||
" ",
|
||||
"Will show percentage of total memory",
|
||||
"if False."},
|
||||
{"proc_cpu_graphs",
|
||||
"Show cpu graph for each process.",
|
||||
"",
|
||||
"True or False"},
|
||||
{"proc_filter_kernel",
|
||||
"(Linux) Filter kernel processes from output.",
|
||||
"",
|
||||
"Set to 'True' to filter out internal",
|
||||
"processes started by the Linux kernel."},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -581,7 +639,7 @@ namespace Menu {
|
|||
|
||||
box_contents = Draw::createBox(x, y, width, height, Theme::c("hi_fg"), true, title) + Mv::d(1);
|
||||
for (const auto& line : content) {
|
||||
box_contents += Mv::save + Mv::r(width / 2 - Fx::uncolor(line).size() / 2 - 1) + line + Mv::restore + Mv::d(1);
|
||||
box_contents += Mv::save + Mv::r(max((size_t)0, (width / 2) - (Fx::uncolor(line).size() / 2) - 1)) + line + Mv::restore + Mv::d(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +721,7 @@ namespace Menu {
|
|||
if (redraw) {
|
||||
x = Term::width/2 - 40;
|
||||
y = Term::height/2 - 9;
|
||||
bg = Draw::createBox(x + 2, y, 78, 18, Theme::c("hi_fg"), true, "signals");
|
||||
bg = Draw::createBox(x + 2, y, 78, 19, Theme::c("hi_fg"), true, "signals");
|
||||
bg += Mv::to(y+2, x+3) + Theme::c("title") + Fx::b + cjust("Send signal to PID " + to_string(s_pid) + " ("
|
||||
+ uresize((s_pid == Config::getI("detailed_pid") ? Proc::detailed.entry.name : Config::getS("selected_name")), 30) + ")", 76);
|
||||
}
|
||||
|
@ -695,7 +753,7 @@ namespace Menu {
|
|||
else if (key == "backspace" and selected_signal != -1) {
|
||||
selected_signal = (selected_signal < 10 ? -1 : selected_signal / 10);
|
||||
}
|
||||
else if (key == "up" and selected_signal != 16) {
|
||||
else if (is_in(key, "up", "k") and selected_signal != 16) {
|
||||
if (selected_signal == 1) selected_signal = 31;
|
||||
else if (selected_signal < 6) selected_signal += 25;
|
||||
else {
|
||||
|
@ -704,7 +762,7 @@ namespace Menu {
|
|||
if (selected_signal <= 16 and offset) selected_signal--;
|
||||
}
|
||||
}
|
||||
else if (key == "down") {
|
||||
else if (is_in(key, "down", "j")) {
|
||||
if (selected_signal == 31) selected_signal = 1;
|
||||
else if (selected_signal < 1 or selected_signal == 16) selected_signal = 1;
|
||||
else if (selected_signal > 26) selected_signal -= 25;
|
||||
|
@ -715,11 +773,11 @@ namespace Menu {
|
|||
if (selected_signal > 31) selected_signal = 31;
|
||||
}
|
||||
}
|
||||
else if (key == "left" and selected_signal > 0 and selected_signal != 16) {
|
||||
else if (is_in(key, "left", "h") and selected_signal > 0 and selected_signal != 16) {
|
||||
if (--selected_signal < 1) selected_signal = 31;
|
||||
else if (selected_signal == 16) selected_signal--;
|
||||
}
|
||||
else if (key == "right" and selected_signal <= 31 and selected_signal != 16) {
|
||||
else if (is_in(key, "right", "l") and selected_signal <= 31 and selected_signal != 16) {
|
||||
if (++selected_signal > 31) selected_signal = 1;
|
||||
else if (selected_signal == 16) selected_signal++;
|
||||
}
|
||||
|
@ -745,11 +803,12 @@ namespace Menu {
|
|||
}
|
||||
|
||||
cy++;
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 38) + Theme::c("main_fg") + Fx::ub + " | To send signal.";
|
||||
mouse_mappings["enter"] = {cy, x, 1, 78};
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓ ← →", 38, true) + Theme::c("main_fg") + Fx::ub + " | To choose signal.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or \"q\"", 38) + Theme::c("main_fg") + Fx::ub + " | To abort.";
|
||||
mouse_mappings["escape"] = {cy, x, 1, 78};
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust( "↑ ↓ ← →", 33, true) + Theme::c("main_fg") + Fx::ub + " | To choose signal.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("0-9", 33) + Theme::c("main_fg") + Fx::ub + " | Enter manually.";
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ENTER", 33) + Theme::c("main_fg") + Fx::ub + " | To send signal.";
|
||||
mouse_mappings["enter"] = {cy, x, 1, 73};
|
||||
out += Mv::to(++cy, x+3) + Fx::b + Theme::c("hi_fg") + rjust("ESC or \"q\"", 33) + Theme::c("main_fg") + Fx::ub + " | To abort.";
|
||||
mouse_mappings["escape"] = {cy, x, 1, 73};
|
||||
|
||||
out += Fx::reset;
|
||||
}
|
||||
|
@ -876,10 +935,7 @@ namespace Menu {
|
|||
};
|
||||
}
|
||||
}
|
||||
else if (key == "q") {
|
||||
exit(0);
|
||||
}
|
||||
else if (is_in(key, "escape", "m", "mouse_click")) {
|
||||
else if (is_in(key, "escape", "q", "m", "mouse_click")) {
|
||||
return Closed;
|
||||
}
|
||||
else if (key.starts_with("button_")) {
|
||||
|
@ -900,13 +956,13 @@ namespace Menu {
|
|||
currentMenu = Menus::Help;
|
||||
return Switch;
|
||||
case Quit:
|
||||
exit(0);
|
||||
clean_quit(0);
|
||||
}
|
||||
}
|
||||
else if (is_in(key, "down", "tab", "mouse_scroll_down")) {
|
||||
else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) {
|
||||
if (++selected > 2) selected = 0;
|
||||
}
|
||||
else if (is_in(key, "up", "shift_tab", "mouse_scroll_up")) {
|
||||
else if (is_in(key, "up", "shift_tab", "mouse_scroll_up", "k")) {
|
||||
if (--selected < 0) selected = 2;
|
||||
}
|
||||
else {
|
||||
|
@ -953,9 +1009,11 @@ namespace Menu {
|
|||
{"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)},
|
||||
{"cpu_graph_upper", std::cref(Cpu::available_fields)},
|
||||
{"cpu_graph_lower", std::cref(Cpu::available_fields)},
|
||||
{"cpu_sensor", std::cref(Cpu::available_sensors)}
|
||||
{"cpu_sensor", std::cref(Cpu::available_sensors)},
|
||||
{"selected_battery", std::cref(Config::available_batteries)},
|
||||
};
|
||||
auto& tty_mode = Config::getB("tty_mode");
|
||||
auto& vim_keys = Config::getB("vim_keys");
|
||||
if (max_items == 0) {
|
||||
for (const auto& cat : categories) {
|
||||
if ((int)cat.size() > max_items) max_items = cat.size();
|
||||
|
@ -1054,14 +1112,14 @@ namespace Menu {
|
|||
else if (is_in(key, "escape", "q", "o", "backspace")) {
|
||||
return Closed;
|
||||
}
|
||||
else if (is_in(key, "down", "mouse_scroll_down")) {
|
||||
else if (is_in(key, "down", "mouse_scroll_down") or (vim_keys and key == "j")) {
|
||||
if (++selected > select_max or selected >= item_height) {
|
||||
if (page < pages - 1) page++;
|
||||
else if (pages > 1) page = 0;
|
||||
selected = 0;
|
||||
}
|
||||
}
|
||||
else if (is_in(key, "up", "mouse_scroll_up")) {
|
||||
else if (is_in(key, "up", "mouse_scroll_up") or (vim_keys and key == "k")) {
|
||||
if (--selected < 0) {
|
||||
if (page > 0) page--;
|
||||
else if (pages > 1) page = pages - 1;
|
||||
|
@ -1089,12 +1147,12 @@ namespace Menu {
|
|||
selected_cat = key.back() - '0' - 1;
|
||||
page = selected = 0;
|
||||
}
|
||||
else if (is_in(key, "left", "right")) {
|
||||
else if (is_in(key, "left", "right") or (vim_keys and is_in(key, "h", "l"))) {
|
||||
const auto& option = categories[selected_cat][item_height * page + selected][0];
|
||||
if (selPred.test(isInt)) {
|
||||
const int mod = (option == "update_ms" ? 100 : 1);
|
||||
long value = Config::getI(option);
|
||||
if (key == "right") value += mod;
|
||||
if (key == "right" or (vim_keys and key == "l")) value += mod;
|
||||
else value -= mod;
|
||||
|
||||
if (Config::intValid(option, to_string(value)))
|
||||
|
@ -1119,13 +1177,16 @@ namespace Menu {
|
|||
else if (option == "background_update") {
|
||||
Runner::pause_output = false;
|
||||
}
|
||||
else if (option == "base_10_sizes") {
|
||||
recollect = true;
|
||||
}
|
||||
}
|
||||
else if (selPred.test(isBrowseable)) {
|
||||
auto& optList = optionsList.at(option).get();
|
||||
int i = v_index(optList, Config::getS(option));
|
||||
|
||||
if (key == "right" and ++i >= (int)optList.size()) i = 0;
|
||||
else if (key == "left" and --i < 0) i = optList.size() - 1;
|
||||
if ((key == "right" or (vim_keys and key == "l")) and ++i >= (int)optList.size()) i = 0;
|
||||
else if ((key == "left" or (vim_keys and key == "h")) and --i < 0) i = optList.size() - 1;
|
||||
Config::set(option, optList.at(i));
|
||||
|
||||
if (option == "color_theme")
|
||||
|
|
174
src/btop_shared.cpp
Normal file
174
src/btop_shared.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <btop_shared.hpp>
|
||||
#include <btop_tools.hpp>
|
||||
|
||||
using std::string_literals::operator""s;
|
||||
namespace rng = std::ranges;
|
||||
using namespace Tools;
|
||||
|
||||
|
||||
namespace Proc {
|
||||
void proc_sorter(vector<proc_info>& proc_vec, const string& sorting, const bool reverse, const bool tree) {
|
||||
if (reverse) {
|
||||
switch (v_index(sort_vector, sorting)) {
|
||||
case 0: rng::stable_sort(proc_vec, rng::less{}, &proc_info::pid); break;
|
||||
case 1: rng::stable_sort(proc_vec, rng::less{}, &proc_info::name); break;
|
||||
case 2: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cmd); break;
|
||||
case 3: rng::stable_sort(proc_vec, rng::less{}, &proc_info::threads); break;
|
||||
case 4: rng::stable_sort(proc_vec, rng::less{}, &proc_info::user); break;
|
||||
case 5: rng::stable_sort(proc_vec, rng::less{}, &proc_info::mem); break;
|
||||
case 6: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_p); break;
|
||||
case 7: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_c); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (v_index(sort_vector, sorting)) {
|
||||
case 0: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::pid); break;
|
||||
case 1: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::name); break;
|
||||
case 2: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cmd); break;
|
||||
case 3: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::threads); break;
|
||||
case 4: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::user); break;
|
||||
case 5: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::mem); break;
|
||||
case 6: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_p); break;
|
||||
case 7: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_c); break;
|
||||
}
|
||||
}
|
||||
|
||||
//* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage
|
||||
if (not tree and not reverse and sorting == "cpu lazy") {
|
||||
double max = 10.0, target = 30.0;
|
||||
for (size_t i = 0, x = 0, offset = 0; i < proc_vec.size(); i++) {
|
||||
if (i <= 5 and proc_vec.at(i).cpu_p > max)
|
||||
max = proc_vec.at(i).cpu_p;
|
||||
else if (i == 6)
|
||||
target = (max > 30.0) ? max : 10.0;
|
||||
if (i == offset and proc_vec.at(i).cpu_p > 30.0)
|
||||
offset++;
|
||||
else if (proc_vec.at(i).cpu_p > target) {
|
||||
rotate(proc_vec.begin() + offset, proc_vec.begin() + i, proc_vec.begin() + i + 1);
|
||||
if (++x > 10) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tree_sort(vector<tree_proc>& proc_vec, const string& sorting, const bool reverse, int& c_index, const int index_max, const bool collapsed) {
|
||||
if (proc_vec.size() > 1) {
|
||||
if (reverse) {
|
||||
switch (v_index(sort_vector, sorting)) {
|
||||
case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads < b.entry.get().threads; }); break;
|
||||
case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem < b.entry.get().mem; }); break;
|
||||
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p < b.entry.get().cpu_p; }); break;
|
||||
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c < b.entry.get().cpu_c; }); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (v_index(sort_vector, sorting)) {
|
||||
case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads > b.entry.get().threads; }); break;
|
||||
case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem > b.entry.get().mem; }); break;
|
||||
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p > b.entry.get().cpu_p; }); break;
|
||||
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c > b.entry.get().cpu_c; }); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& r : proc_vec) {
|
||||
r.entry.get().tree_index = (collapsed or r.entry.get().filtered ? index_max : c_index++);
|
||||
if (not r.children.empty()) {
|
||||
tree_sort(r.children, sorting, reverse, c_index, (collapsed or r.entry.get().collapsed or r.entry.get().tree_index == (size_t)index_max));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found, const bool no_update, const bool should_filter) {
|
||||
auto cur_pos = out_procs.size();
|
||||
bool filtering = false;
|
||||
|
||||
//? If filtering, include children of matching processes
|
||||
if (not found and (should_filter or not filter.empty())) {
|
||||
if (not s_contains(std::to_string(cur_proc.pid), filter)
|
||||
and not s_contains(cur_proc.name, filter)
|
||||
and not s_contains(cur_proc.cmd, filter)
|
||||
and not s_contains(cur_proc.user, filter)) {
|
||||
filtering = true;
|
||||
cur_proc.filtered = true;
|
||||
filter_found++;
|
||||
}
|
||||
else {
|
||||
found = true;
|
||||
cur_depth = 0;
|
||||
}
|
||||
}
|
||||
else if (cur_proc.filtered) cur_proc.filtered = false;
|
||||
|
||||
cur_proc.depth = cur_depth;
|
||||
|
||||
//? Set tree index position for process if not filtered out or currently in a collapsed sub-tree
|
||||
out_procs.push_back({ cur_proc, {} });
|
||||
if (not collapsed and not filtering) {
|
||||
cur_proc.tree_index = out_procs.size() - 1;
|
||||
|
||||
//? Try to find name of the binary file and append to program name if not the same
|
||||
if (cur_proc.short_cmd.empty() and not cur_proc.cmd.empty()) {
|
||||
std::string_view cmd_view = cur_proc.cmd;
|
||||
cmd_view = cmd_view.substr((size_t)0, std::min(cmd_view.find(' '), cmd_view.size()));
|
||||
cmd_view = cmd_view.substr(std::min(cmd_view.find_last_of('/') + 1, cmd_view.size()));
|
||||
cur_proc.short_cmd = (string)cmd_view;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cur_proc.tree_index = in_procs.size();
|
||||
}
|
||||
|
||||
//? Recursive iteration over all children
|
||||
int children = 0;
|
||||
for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) {
|
||||
if (collapsed and not filtering) {
|
||||
cur_proc.filtered = true;
|
||||
}
|
||||
children++;
|
||||
|
||||
_tree_gen(p, in_procs, out_procs.back().children, cur_depth + 1, (collapsed or cur_proc.collapsed), filter, found, no_update, should_filter);
|
||||
|
||||
if (not no_update and not filtering and (collapsed or cur_proc.collapsed)) {
|
||||
//auto& parent = cur_proc;
|
||||
cur_proc.cpu_p += p.cpu_p;
|
||||
cur_proc.cpu_c += p.cpu_c;
|
||||
cur_proc.mem += p.mem;
|
||||
cur_proc.threads += p.threads;
|
||||
filter_found++;
|
||||
p.filtered = true;
|
||||
}
|
||||
}
|
||||
if (collapsed or filtering) {
|
||||
return;
|
||||
}
|
||||
|
||||
//? Add tree terminator symbol if it's the last child in a sub-tree
|
||||
if (children > 0 and out_procs.back().children.back().entry.get().prefix.size() >= 8 and not out_procs.back().children.back().entry.get().prefix.ends_with("]─"))
|
||||
out_procs.back().children.back().entry.get().prefix.replace(out_procs.back().children.back().entry.get().prefix.size() - 8, 8, " └─ ");
|
||||
|
||||
//? Add collapse/expand symbols if process have any children
|
||||
out_procs.at(cur_pos).entry.get().prefix = " │ "s * cur_depth + (children > 0 ? (cur_proc.collapsed ? "[+]─" : "[-]─") : " ├─ ");
|
||||
}
|
||||
|
||||
}
|
|
@ -27,12 +27,15 @@ tab-size = 4
|
|||
#include <array>
|
||||
#include <ifaddrs.h>
|
||||
#include <tuple>
|
||||
#include <unistd.h>
|
||||
|
||||
using std::string, std::vector, std::deque, robin_hood::unordered_flat_map, std::atomic, std::array, std::tuple;
|
||||
|
||||
void term_resize(bool force=false);
|
||||
void banner_gen();
|
||||
|
||||
extern void clean_quit(int sig);
|
||||
|
||||
namespace Global {
|
||||
extern const vector<array<string, 2>> Banner_src;
|
||||
extern const string Version;
|
||||
|
@ -43,6 +46,7 @@ namespace Global {
|
|||
extern atomic<bool> resized;
|
||||
extern string overlay;
|
||||
extern string clock;
|
||||
extern uid_t real_uid, set_uid;
|
||||
}
|
||||
|
||||
namespace Runner {
|
||||
|
@ -70,8 +74,6 @@ namespace Shared {
|
|||
void init();
|
||||
|
||||
extern long coreCount, page_size, clk_tck;
|
||||
extern int totalMem_len;
|
||||
extern uint64_t totalMem;
|
||||
}
|
||||
|
||||
|
||||
|
@ -129,6 +131,7 @@ namespace Mem {
|
|||
struct disk_info {
|
||||
std::filesystem::path dev;
|
||||
string name;
|
||||
string fstype = "";
|
||||
std::filesystem::path stat = "";
|
||||
int64_t total = 0, used = 0, free = 0;
|
||||
int used_percent = 0, free_percent = 0;
|
||||
|
@ -149,11 +152,15 @@ namespace Mem {
|
|||
vector<string> disks_order;
|
||||
};
|
||||
|
||||
//?* Get total system memory
|
||||
uint64_t get_totalMem();
|
||||
|
||||
//* Collect mem & disks stats
|
||||
auto collect(const bool no_update=false) -> mem_info&;
|
||||
|
||||
//* Draw contents of mem box using <mem> as source
|
||||
string draw(const mem_info& mem, const bool force_redraw=false, const bool data_same=false);
|
||||
|
||||
}
|
||||
|
||||
namespace Net {
|
||||
|
@ -166,7 +173,7 @@ namespace Net {
|
|||
extern unordered_flat_map<string, uint64_t> graph_max;
|
||||
|
||||
struct net_stat {
|
||||
uint64_t speed = 0, top = 0, total = 0, last = 0, offset = 0;
|
||||
uint64_t speed = 0, top = 0, total = 0, last = 0, offset = 0, rollover = 0;
|
||||
};
|
||||
|
||||
struct net_info {
|
||||
|
@ -193,7 +200,7 @@ namespace Proc {
|
|||
extern bool shown, redraw;
|
||||
extern int select_max;
|
||||
extern atomic<int> detailed_pid;
|
||||
extern int selected_pid, start, selected, collapse, expand;
|
||||
extern int selected_pid, start, selected, collapse, expand, filter_found, selected_depth;
|
||||
extern string selected_name;
|
||||
|
||||
//? Contains the valid sorting options for processes
|
||||
|
@ -262,4 +269,18 @@ namespace Proc {
|
|||
|
||||
//* Draw contents of proc box using <plist> as data source
|
||||
string draw(const vector<proc_info>& plist, const bool force_redraw=false, const bool data_same=false);
|
||||
|
||||
struct tree_proc {
|
||||
std::reference_wrapper<proc_info> entry;
|
||||
vector<tree_proc> children;
|
||||
};
|
||||
|
||||
//* Sort vector of proc_info's
|
||||
void proc_sorter(vector<proc_info>& proc_vec, const string& sorting, const bool reverse, const bool tree = false);
|
||||
|
||||
//* Recursive sort of process tree
|
||||
void tree_sort(vector<tree_proc>& proc_vec, const string& sorting, const bool reverse, int& c_index, const int index_max, const bool collapsed = false);
|
||||
|
||||
//* Generate process tree list
|
||||
void _tree_gen(proc_info& cur_proc, vector<proc_info>& in_procs, vector<tree_proc>& out_procs, int cur_depth, const bool collapsed, const string& filter, bool found=false, const bool no_update=false, const bool should_filter=false);
|
||||
}
|
||||
|
|
|
@ -23,15 +23,17 @@ tab-size = 4
|
|||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <utility>
|
||||
#include <ranges>
|
||||
#include <robin_hood.h>
|
||||
#include <widechar_width.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <btop_shared.hpp>
|
||||
#include <btop_tools.hpp>
|
||||
#include <btop_config.hpp>
|
||||
|
||||
using std::string_view, std::max, std::floor, std::to_string, std::cin, std::cout, std::flush, robin_hood::unordered_flat_map;
|
||||
namespace fs = std::filesystem;
|
||||
|
@ -46,7 +48,6 @@ namespace Term {
|
|||
atomic<int> width = 0;
|
||||
atomic<int> height = 0;
|
||||
string current_tty;
|
||||
char* custombuf;
|
||||
|
||||
namespace {
|
||||
struct termios initial_settings;
|
||||
|
@ -73,12 +74,14 @@ namespace Term {
|
|||
}
|
||||
}
|
||||
|
||||
bool refresh() {
|
||||
bool refresh(bool only_check) {
|
||||
struct winsize w;
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) return false;
|
||||
if (width != w.ws_col or height != w.ws_row) {
|
||||
width = w.ws_col;
|
||||
height = w.ws_row;
|
||||
if (not only_check) {
|
||||
width = w.ws_col;
|
||||
height = w.ws_row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -120,9 +123,6 @@ namespace Term {
|
|||
linebuffered(false);
|
||||
refresh();
|
||||
|
||||
//? Set 1MB buffer for cout
|
||||
std::cout.rdbuf()->pubsetbuf(custombuf, 1048576);
|
||||
|
||||
cout << alt_screen << hide_cursor << mouse_on << flush;
|
||||
Global::resized = false;
|
||||
}
|
||||
|
@ -141,21 +141,85 @@ namespace Term {
|
|||
|
||||
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
||||
|
||||
// ! Dsiabled due to issue when compiling with musl, reverted back to using regex
|
||||
// namespace Fx {
|
||||
// string uncolor(const string& s) {
|
||||
// string out = s;
|
||||
// for (size_t offset = 0, start_pos = 0, end_pos = 0;;) {
|
||||
// start_pos = (offset == 0) ? out.find('\x1b') : offset;
|
||||
// if (start_pos == string::npos)
|
||||
// break;
|
||||
// offset = start_pos + 1;
|
||||
// end_pos = out.find('m', offset);
|
||||
// if (end_pos == string::npos)
|
||||
// break;
|
||||
// else if (auto next_pos = out.find('\x1b', offset); not isdigit(out[end_pos - 1]) or end_pos > next_pos) {
|
||||
// offset = next_pos;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// out.erase(start_pos, (end_pos - start_pos)+1);
|
||||
// offset = 0;
|
||||
// }
|
||||
// out.shrink_to_fit();
|
||||
// return out;
|
||||
// }
|
||||
// }
|
||||
|
||||
namespace Tools {
|
||||
|
||||
atomic<int> active_locks (0);
|
||||
size_t wide_ulen(const string& str) {
|
||||
unsigned int chars = 0;
|
||||
try {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str()));
|
||||
|
||||
for (auto c : w_str) {
|
||||
chars += utf8::wcwidth(c);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return ulen(str);
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
size_t wide_ulen(const std::wstring& w_str) {
|
||||
unsigned int chars = 0;
|
||||
|
||||
for (auto c : w_str) {
|
||||
chars += utf8::wcwidth(c);
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
string uresize(string str, const size_t len, const bool wide) {
|
||||
if (len < 1 or str.empty()) return "";
|
||||
for (size_t x = 0, i = 0; i < str.size(); i++) {
|
||||
if (wide and static_cast<unsigned char>(str.at(i)) > 0xef) x += 2;
|
||||
else if ((static_cast<unsigned char>(str.at(i)) & 0xC0) != 0x80) x++;
|
||||
if (x >= len + 1) {
|
||||
str.resize(i);
|
||||
str.shrink_to_fit();
|
||||
break;
|
||||
if (wide) {
|
||||
try {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
auto w_str = conv.from_bytes((str.size() > 10000 ? str.substr(0, 10000).c_str() : str.c_str()));
|
||||
while (wide_ulen(w_str) > len)
|
||||
w_str.pop_back();
|
||||
string n_str = conv.to_bytes(w_str);
|
||||
return n_str;
|
||||
}
|
||||
catch (...) {
|
||||
return uresize(str, len, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (size_t x = 0, i = 0; i < str.size(); i++) {
|
||||
if ((static_cast<unsigned char>(str.at(i)) & 0xC0) != 0x80) x++;
|
||||
if (x >= len + 1) {
|
||||
str.resize(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
str.shrink_to_fit();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -271,28 +335,45 @@ namespace Tools {
|
|||
string floating_humanizer(uint64_t value, const bool shorten, size_t start, const bool bit, const bool per_second) {
|
||||
string out;
|
||||
const size_t mult = (bit) ? 8 : 1;
|
||||
static const array<string, 11> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||
static const array<string, 11> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||
const auto& units = (bit) ? Units_bit : Units_byte;
|
||||
const bool mega = Config::getB("base_10_sizes");
|
||||
static const array<string, 11> mebiUnits_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||
static const array<string, 11> mebiUnits_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||
static const array<string, 11> megaUnits_bit = {"bit", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb", "Bb", "Gb"};
|
||||
static const array<string, 11> megaUnits_byte = {"Byte", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB", "GB"};
|
||||
const auto& units = (bit) ? ( mega ? megaUnits_bit : mebiUnits_bit) : ( mega ? megaUnits_byte : mebiUnits_byte);
|
||||
|
||||
value *= 100 * mult;
|
||||
|
||||
while (value >= 102400) {
|
||||
value >>= 10;
|
||||
if (value < 100) {
|
||||
out = to_string(value);
|
||||
break;
|
||||
if (mega) {
|
||||
while (value >= 100000) {
|
||||
value /= 1000;
|
||||
if (value < 100) {
|
||||
out = to_string(value);
|
||||
break;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (value >= 102400) {
|
||||
value >>= 10;
|
||||
if (value < 100) {
|
||||
out = to_string(value);
|
||||
break;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
if (out.empty()) {
|
||||
out = to_string(value);
|
||||
if (out.size() == 4 and start > 0) { out.pop_back(); out.insert(2, ".");}
|
||||
if (not mega and out.size() == 4 and start > 0) { out.pop_back(); out.insert(2, ".");}
|
||||
else if (out.size() == 3 and start > 0) out.insert(1, ".");
|
||||
else if (out.size() >= 2) out.resize(out.size() - 2);
|
||||
}
|
||||
if (shorten) {
|
||||
if (out.find('.') != string::npos) out = to_string((int)round(stof(out)));
|
||||
auto f_pos = out.find('.');
|
||||
if (f_pos == 1 and out.size() > 3) out = to_string(round(stof(out) * 10) / 10).substr(0,3);
|
||||
else if (f_pos != string::npos) out = to_string((int)round(stof(out)));
|
||||
if (out.size() > 3) { out = to_string((int)(out[0] - '0') + 1); start++;}
|
||||
out.push_back(units[start][0]);
|
||||
}
|
||||
|
@ -319,15 +400,22 @@ namespace Tools {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
atomic_lock::atomic_lock(atomic<bool>& atom) : atom(atom) {
|
||||
active_locks++;
|
||||
while (not this->atom.compare_exchange_strong(this->not_true, true));
|
||||
void atomic_wait(const atomic<bool>& atom, const bool old) noexcept {
|
||||
while (atom.load(std::memory_order_relaxed) == old ) busy_wait();
|
||||
}
|
||||
|
||||
void atomic_wait_for(const atomic<bool>& atom, const bool old, const uint64_t wait_ms) noexcept {
|
||||
const uint64_t start_time = time_ms();
|
||||
while (atom.load(std::memory_order_relaxed) == old and (time_ms() - start_time < wait_ms)) sleep_ms(1);
|
||||
}
|
||||
|
||||
atomic_lock::atomic_lock(atomic<bool>& atom, bool wait) : atom(atom) {
|
||||
if (wait) while (not this->atom.compare_exchange_strong(this->not_true, true));
|
||||
else this->atom.store(true);
|
||||
}
|
||||
|
||||
atomic_lock::~atomic_lock() {
|
||||
active_locks--;
|
||||
this->atom.store(false);
|
||||
atomic_notify(this->atom);
|
||||
}
|
||||
|
||||
string readfile(const std::filesystem::path& path, const string& fallback) {
|
||||
|
@ -338,7 +426,8 @@ namespace Tools {
|
|||
for (string readstr; getline(file, readstr); out += readstr);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("readfile() : Exception when reading " + (string)path + " : " + e.what());
|
||||
Logger::error("readfile() : Exception when reading " + (string)path + " : " + e.what());
|
||||
return fallback;
|
||||
}
|
||||
return (out.empty() ? fallback : out);
|
||||
}
|
||||
|
@ -371,22 +460,33 @@ namespace Tools {
|
|||
|
||||
namespace Logger {
|
||||
using namespace Tools;
|
||||
namespace {
|
||||
std::atomic<bool> busy (false);
|
||||
bool first = true;
|
||||
const string tdf = "%Y/%m/%d (%T) | ";
|
||||
}
|
||||
std::atomic<bool> busy (false);
|
||||
bool first = true;
|
||||
const string tdf = "%Y/%m/%d (%T) | ";
|
||||
|
||||
size_t loglevel;
|
||||
fs::path logfile;
|
||||
|
||||
//* Wrapper for lowering priviliges if using SUID bit and currently isn't using real userid
|
||||
class lose_priv {
|
||||
int status = -1;
|
||||
public:
|
||||
lose_priv() {
|
||||
if (geteuid() != Global::real_uid) this->status = seteuid(Global::real_uid);
|
||||
}
|
||||
~lose_priv() {
|
||||
if (status == 0) status = seteuid(Global::set_uid);
|
||||
}
|
||||
};
|
||||
|
||||
void set(const string& level) {
|
||||
loglevel = v_index(log_levels, level);
|
||||
}
|
||||
|
||||
void log_write(const size_t level, const string& msg) {
|
||||
if (loglevel < level or logfile.empty()) return;
|
||||
atomic_lock lck(busy);
|
||||
atomic_lock lck(busy, true);
|
||||
lose_priv neutered{};
|
||||
std::error_code ec;
|
||||
try {
|
||||
if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) {
|
||||
|
|
|
@ -21,16 +21,24 @@ tab-size = 4
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <regex>
|
||||
#include <atomic>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
#include <ranges>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
#ifndef HOST_NAME_MAX
|
||||
#ifdef __APPLE__
|
||||
#define HOST_NAME_MAX 255
|
||||
#else
|
||||
#define HOST_NAME_MAX 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using std::string, std::vector, std::atomic, std::to_string, std::regex, std::tuple, std::array;
|
||||
using std::string, std::vector, std::atomic, std::to_string, std::tuple, std::array;
|
||||
|
||||
|
||||
//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
|
||||
|
@ -58,13 +66,14 @@ namespace Fx {
|
|||
extern string reset;
|
||||
|
||||
//* Regex for matching color, style and cursor move escape sequences
|
||||
const regex escape_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m|f|s|u|C|D|A|B){1}");
|
||||
const std::regex escape_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m|f|s|u|C|D|A|B){1}");
|
||||
|
||||
//* Regex for matching only color and style escape sequences
|
||||
const regex color_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m){1}");
|
||||
const std::regex color_regex("\033\\[\\d+;?\\d?;?\\d*;?\\d*;?\\d*(m){1}");
|
||||
|
||||
//* Return a string with all colors and text styling removed
|
||||
inline string uncolor(const string& s) { return regex_replace(s, color_regex, ""); }
|
||||
inline string uncolor(const string& s) { return std::regex_replace(s, color_regex, ""); }
|
||||
// string uncolor(const string& s);
|
||||
|
||||
}
|
||||
|
||||
|
@ -107,14 +116,14 @@ namespace Term {
|
|||
const string clear_end = Fx::e + "0J";
|
||||
const string clear_begin = Fx::e + "1J";
|
||||
const string mouse_on = Fx::e + "?1002h" + Fx::e + "?1015h" + Fx::e + "?1006h"; //? Enable reporting of mouse position on click and release
|
||||
const string mouse_off = Fx::e + "?1002l";
|
||||
const string mouse_off = Fx::e + "?1002l" + Fx::e + "?1015l" + Fx::e + "?1006l";
|
||||
const string mouse_direct_on = Fx::e + "?1003h"; //? Enable reporting of mouse position at any movement
|
||||
const string mouse_direct_off = Fx::e + "?1003l";
|
||||
const string sync_start = Fx::e + "?2026h"; //? Start of terminal synchronized output
|
||||
const string sync_end = Fx::e + "?2026l"; //? End of terminal synchronized output
|
||||
|
||||
//* Returns true if terminal has been resized and updates width and height
|
||||
bool refresh();
|
||||
bool refresh(bool only_check=false);
|
||||
|
||||
//* Returns an array with the lowest possible width, height with current box config
|
||||
auto get_min_size(const string& boxes) -> array<int, 2>;
|
||||
|
@ -130,12 +139,13 @@ namespace Term {
|
|||
|
||||
namespace Tools {
|
||||
constexpr auto SSmax = std::numeric_limits<std::streamsize>::max();
|
||||
extern atomic<int> active_locks;
|
||||
|
||||
//* Return number of UTF8 characters in a string (wide=true counts UTF-8 characters with a width > 1 as 2 characters)
|
||||
size_t wide_ulen(const string& str);
|
||||
size_t wide_ulen(const std::wstring& w_str);
|
||||
|
||||
//* Return number of UTF8 characters in a string (wide=true for column size needed on terminal)
|
||||
inline size_t ulen(const string& str, const bool wide=false) {
|
||||
return std::ranges::count_if(str, [](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; })
|
||||
+ (wide ? std::ranges::count_if(str, [](char c) { return (static_cast<unsigned char>(c) > 0xef); }) : 0);
|
||||
return (wide ? wide_ulen(str) : std::ranges::count_if(str, [](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; }));
|
||||
}
|
||||
|
||||
//* Resize a string consisting of UTF8 characters (only reduces size)
|
||||
|
@ -177,6 +187,16 @@ namespace Tools {
|
|||
return str.find(find_val) != string::npos;
|
||||
}
|
||||
|
||||
//* Check if string <str> contains string <find_val>, while ignoring case
|
||||
inline bool s_contains_ic(const string& str, const string& find_val) {
|
||||
auto it = std::search(
|
||||
str.begin(), str.end(),
|
||||
find_val.begin(), find_val.end(),
|
||||
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }
|
||||
);
|
||||
return it != str.end();
|
||||
}
|
||||
|
||||
//* Return index of <find_val> from vector <vec>, returns size of <vec> if <find_val> is not present
|
||||
template <typename T>
|
||||
inline size_t v_index(const vector<T>& vec, const T& find_val) {
|
||||
|
@ -269,20 +289,28 @@ namespace Tools {
|
|||
string hostname();
|
||||
string username();
|
||||
|
||||
#if __GNUC__ < 11
|
||||
inline void atomic_wait(const atomic<bool>& atom, const bool old=true) noexcept { while (atom.load() == old) sleep_ms(1); }
|
||||
inline void atomic_notify(const atomic<bool>& atom) noexcept { (void)atom; }
|
||||
#else
|
||||
inline void atomic_wait(const atomic<bool>& atom, const bool old=true) noexcept { atom.wait(old); }
|
||||
inline void atomic_notify(const atomic<bool>& atom) noexcept { atom.notify_all(); }
|
||||
#endif
|
||||
static inline void busy_wait (void) {
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
__builtin_ia32_pause();
|
||||
#elif defined __ia64__
|
||||
__asm volatile("hint @pause" : : : "memory");
|
||||
#elif defined __sparc__ && (defined __arch64__ || defined __sparc_v9__)
|
||||
__asm volatile("membar #LoadLoad" : : : "memory");
|
||||
#else
|
||||
__asm volatile("" : : : "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
//* Waits for atomic<bool> to be false and sets it to true on construct, sets to false and notifies on destruct
|
||||
void atomic_wait(const atomic<bool>& atom, const bool old=true) noexcept;
|
||||
|
||||
void atomic_wait_for(const atomic<bool>& atom, const bool old=true, const uint64_t wait_ms=0) noexcept;
|
||||
|
||||
//* Sets atomic<bool> to true on construct, sets to false on destruct
|
||||
class atomic_lock {
|
||||
atomic<bool>& atom;
|
||||
bool not_true = false;
|
||||
public:
|
||||
atomic_lock(atomic<bool>& atom);
|
||||
atomic_lock(atomic<bool>& atom, bool wait=false);
|
||||
~atomic_lock();
|
||||
};
|
||||
|
||||
|
|
1319
src/freebsd/btop_collect.cpp
Normal file
1319
src/freebsd/btop_collect.cpp
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1367
src/osx/btop_collect.cpp
Normal file
1367
src/osx/btop_collect.cpp
Normal file
File diff suppressed because it is too large
Load diff
111
src/osx/sensors.cpp
Normal file
111
src/osx/sensors.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
#include "sensors.hpp"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
|
||||
#include <string>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
typedef struct __IOHIDEvent *IOHIDEventRef;
|
||||
typedef struct __IOHIDServiceClient *IOHIDServiceClientRef;
|
||||
#ifdef __LP64__
|
||||
typedef double IOHIDFloat;
|
||||
#else
|
||||
typedef float IOHIDFloat;
|
||||
#endif
|
||||
|
||||
#define IOHIDEventFieldBase(type) (type << 16)
|
||||
#define kIOHIDEventTypeTemperature 15
|
||||
|
||||
IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef allocator);
|
||||
int IOHIDEventSystemClientSetMatching(IOHIDEventSystemClientRef client, CFDictionaryRef match);
|
||||
int IOHIDEventSystemClientSetMatchingMultiple(IOHIDEventSystemClientRef client, CFArrayRef match);
|
||||
IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t, int32_t, int64_t);
|
||||
CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property);
|
||||
IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field);
|
||||
|
||||
// create a dict ref, like for temperature sensor {"PrimaryUsagePage":0xff00, "PrimaryUsage":0x5}
|
||||
CFDictionaryRef matching(int page, int usage) {
|
||||
CFNumberRef nums[2];
|
||||
CFStringRef keys[2];
|
||||
|
||||
keys[0] = CFStringCreateWithCString(0, "PrimaryUsagePage", 0);
|
||||
keys[1] = CFStringCreateWithCString(0, "PrimaryUsage", 0);
|
||||
nums[0] = CFNumberCreate(0, kCFNumberSInt32Type, &page);
|
||||
nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage);
|
||||
|
||||
CFDictionaryRef dict = CFDictionaryCreate(0, (const void **)keys, (const void **)nums, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
CFRelease(keys[0]);
|
||||
CFRelease(keys[1]);
|
||||
return dict;
|
||||
}
|
||||
|
||||
double getValue(IOHIDServiceClientRef sc) {
|
||||
IOHIDEventRef event = IOHIDServiceClientCopyEvent(sc, kIOHIDEventTypeTemperature, 0, 0); // here we use ...CopyEvent
|
||||
IOHIDFloat temp = 0.0;
|
||||
if (event != 0) {
|
||||
temp = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(kIOHIDEventTypeTemperature));
|
||||
CFRelease(event);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
} // extern C
|
||||
|
||||
long long Cpu::ThermalSensors::getSensors() {
|
||||
CFDictionaryRef thermalSensors = matching(0xff00, 5); // 65280_10 = FF00_16
|
||||
// thermalSensors's PrimaryUsagePage should be 0xff00 for M1 chip, instead of 0xff05
|
||||
// can be checked by ioreg -lfx
|
||||
IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
|
||||
IOHIDEventSystemClientSetMatching(system, thermalSensors);
|
||||
CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system);
|
||||
std::vector<double> temps;
|
||||
if (matchingsrvs) {
|
||||
long count = CFArrayGetCount(matchingsrvs);
|
||||
for (int i = 0; i < count; i++) {
|
||||
IOHIDServiceClientRef sc = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(matchingsrvs, i);
|
||||
if (sc) {
|
||||
CFStringRef name = IOHIDServiceClientCopyProperty(sc, CFSTR("Product")); // here we use ...CopyProperty
|
||||
if (name) {
|
||||
char buf[200];
|
||||
CFStringGetCString(name, buf, 200, kCFStringEncodingASCII);
|
||||
std::string n(buf);
|
||||
// this is just a guess, nobody knows which sensors mean what
|
||||
// on my system PMU tdie 3 and 9 are missing...
|
||||
// there is also PMU tdev1-8 but it has negative values??
|
||||
// there is also eACC for efficiency package but it only has 2 entries
|
||||
// and pACC for performance but it has 7 entries (2 - 9) WTF
|
||||
if (n.starts_with("eACC") or n.starts_with("pACC")) {
|
||||
temps.push_back(getValue(sc));
|
||||
}
|
||||
CFRelease(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease(matchingsrvs);
|
||||
}
|
||||
CFRelease(system);
|
||||
CFRelease(thermalSensors);
|
||||
if (temps.empty()) return 0ll;
|
||||
return round(std::accumulate(temps.begin(), temps.end(), 0ll) / temps.size());
|
||||
}
|
24
src/osx/sensors.hpp
Normal file
24
src/osx/sensors.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
namespace Cpu {
|
||||
class ThermalSensors {
|
||||
public:
|
||||
long long getSensors();
|
||||
};
|
||||
} // namespace Cpu
|
150
src/osx/smc.cpp
Normal file
150
src/osx/smc.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
#include "smc.hpp"
|
||||
|
||||
static UInt32 _strtoul(char *str, int size, int base) {
|
||||
UInt32 total = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (base == 16) {
|
||||
total += str[i] << (size - 1 - i) * 8;
|
||||
} else {
|
||||
total += (unsigned char)(str[i] << (size - 1 - i) * 8);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
static void _ultostr(char *str, UInt32 val) {
|
||||
str[0] = '\0';
|
||||
sprintf(str, "%c%c%c%c",
|
||||
(unsigned int)val >> 24,
|
||||
(unsigned int)val >> 16,
|
||||
(unsigned int)val >> 8,
|
||||
(unsigned int)val);
|
||||
}
|
||||
|
||||
namespace Cpu {
|
||||
|
||||
SMCConnection::SMCConnection() {
|
||||
IOMasterPort(kIOMasterPortDefault, &masterPort);
|
||||
|
||||
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
|
||||
result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
|
||||
if (result != kIOReturnSuccess) {
|
||||
throw std::runtime_error("failed to get AppleSMC");
|
||||
}
|
||||
|
||||
device = IOIteratorNext(iterator);
|
||||
IOObjectRelease(iterator);
|
||||
if (device == 0) {
|
||||
throw std::runtime_error("failed to get SMC device");
|
||||
}
|
||||
|
||||
result = IOServiceOpen(device, mach_task_self(), 0, &conn);
|
||||
IOObjectRelease(device);
|
||||
if (result != kIOReturnSuccess) {
|
||||
throw std::runtime_error("failed to get SMC connection");
|
||||
}
|
||||
}
|
||||
SMCConnection::~SMCConnection() {
|
||||
IOServiceClose(conn);
|
||||
}
|
||||
|
||||
long long SMCConnection::getSMCTemp(char *key) {
|
||||
SMCVal_t val;
|
||||
kern_return_t result;
|
||||
result = SMCReadKey(key, &val);
|
||||
if (result == kIOReturnSuccess) {
|
||||
if (val.dataSize > 0) {
|
||||
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
|
||||
// convert sp78 value to temperature
|
||||
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
|
||||
return static_cast<long long>(intValue / 256.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// core means physical core in SMC, while in core map it's cpu threads :-/ Only an issue on hackintosh?
|
||||
// this means we can only get the T per physical core
|
||||
// another issue with the SMC API is that the key is always 4 chars -> what with systems with more than 9 physical cores?
|
||||
// no Mac models with more than 18 threads are released, so no problem so far
|
||||
// according to VirtualSMC docs (hackintosh fake SMC) the enumeration follows with alphabetic chars - not implemented yet here (nor in VirtualSMC)
|
||||
long long SMCConnection::getTemp(int core) {
|
||||
char key[] = SMC_KEY_CPU_TEMP;
|
||||
if (core >= 0) {
|
||||
snprintf(key, 5, "TC%1dc", core);
|
||||
}
|
||||
long long result = getSMCTemp(key);
|
||||
if (result == -1) {
|
||||
// try again with C
|
||||
snprintf(key, 5, "TC%1dC", core);
|
||||
result = getSMCTemp(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
kern_return_t SMCConnection::SMCReadKey(UInt32Char_t key, SMCVal_t *val) {
|
||||
kern_return_t result;
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
|
||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(val, 0, sizeof(SMCVal_t));
|
||||
|
||||
inputStructure.key = _strtoul(key, 4, 16);
|
||||
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
||||
|
||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
|
||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
||||
inputStructure.data8 = SMC_CMD_READ_BYTES;
|
||||
|
||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
|
||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
kern_return_t SMCConnection::SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure) {
|
||||
size_t structureInputSize;
|
||||
size_t structureOutputSize;
|
||||
|
||||
structureInputSize = sizeof(SMCKeyData_t);
|
||||
structureOutputSize = sizeof(SMCKeyData_t);
|
||||
|
||||
return IOConnectCallStructMethod(conn, index,
|
||||
// inputStructure
|
||||
inputStructure, structureInputSize,
|
||||
// ouputStructure
|
||||
outputStructure, &structureOutputSize);
|
||||
}
|
||||
|
||||
} // namespace Cpu
|
117
src/osx/smc.hpp
Normal file
117
src/osx/smc.hpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
indent = tab
|
||||
tab-size = 4
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#define VERSION "0.01"
|
||||
|
||||
#define KERNEL_INDEX_SMC 2
|
||||
|
||||
#define SMC_CMD_READ_BYTES 5
|
||||
#define SMC_CMD_WRITE_BYTES 6
|
||||
#define SMC_CMD_READ_INDEX 8
|
||||
#define SMC_CMD_READ_KEYINFO 9
|
||||
#define SMC_CMD_READ_PLIMIT 11
|
||||
#define SMC_CMD_READ_VERS 12
|
||||
|
||||
#define DATATYPE_FPE2 "fpe2"
|
||||
#define DATATYPE_UINT8 "ui8 "
|
||||
#define DATATYPE_UINT16 "ui16"
|
||||
#define DATATYPE_UINT32 "ui32"
|
||||
#define DATATYPE_SP78 "sp78"
|
||||
|
||||
// key values
|
||||
#define SMC_KEY_CPU_TEMP "TC0P" // proximity temp?
|
||||
#define SMC_KEY_CPU_DIODE_TEMP "TC0D" // diode temp?
|
||||
#define SMC_KEY_CPU_DIE_TEMP "TC0F" // die temp?
|
||||
#define SMC_KEY_CPU1_TEMP "TC1C"
|
||||
#define SMC_KEY_CPU2_TEMP "TC2C" // etc
|
||||
#define SMC_KEY_FAN0_RPM_CUR "F0Ac"
|
||||
|
||||
typedef struct {
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
UInt16 release;
|
||||
} SMCKeyData_vers_t;
|
||||
|
||||
typedef struct {
|
||||
UInt16 version;
|
||||
UInt16 length;
|
||||
UInt32 cpuPLimit;
|
||||
UInt32 gpuPLimit;
|
||||
UInt32 memPLimit;
|
||||
} SMCKeyData_pLimitData_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 dataSize;
|
||||
UInt32 dataType;
|
||||
char dataAttributes;
|
||||
} SMCKeyData_keyInfo_t;
|
||||
|
||||
typedef char SMCBytes_t[32];
|
||||
|
||||
typedef struct {
|
||||
UInt32 key;
|
||||
SMCKeyData_vers_t vers;
|
||||
SMCKeyData_pLimitData_t pLimitData;
|
||||
SMCKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
UInt32 data32;
|
||||
SMCBytes_t bytes;
|
||||
} SMCKeyData_t;
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
|
||||
typedef struct {
|
||||
UInt32Char_t key;
|
||||
UInt32 dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SMCBytes_t bytes;
|
||||
} SMCVal_t;
|
||||
|
||||
namespace Cpu {
|
||||
class SMCConnection {
|
||||
public:
|
||||
SMCConnection();
|
||||
virtual ~SMCConnection();
|
||||
|
||||
long long getTemp(int core);
|
||||
|
||||
private:
|
||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val);
|
||||
long long getSMCTemp(char *key);
|
||||
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure);
|
||||
|
||||
io_connect_t conn;
|
||||
kern_return_t result;
|
||||
mach_port_t masterPort;
|
||||
io_iterator_t iterator;
|
||||
io_object_t device;
|
||||
};
|
||||
} // namespace Cpu
|
94
themes/HotPurpleTrafficLight.theme
Normal file
94
themes/HotPurpleTrafficLight.theme
Normal file
|
@ -0,0 +1,94 @@
|
|||
#HotPurpleTrafficLight
|
||||
#by Pete Allebone - mess with the best... you know the rest. <catch me at: peter at allebone dot org>
|
||||
#Designed to flash up bright red with danger when loads are high and attention is needed.
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#000000"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#d1d1e0"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#d1d1e0"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#9933ff"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#6666ff"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#d1d1e0"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#9999ff"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#9933ff"
|
||||
|
||||
# Background color of the percentage meters
|
||||
theme[meter_bg]="#4d4dff"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#9933ff"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#a64dff"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#a64dff"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#a64dff"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#a64dff"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#4d4dff"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#00ff00"
|
||||
theme[temp_mid]="#ff9933"
|
||||
theme[temp_end]="#ff0000"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#00ff00"
|
||||
theme[cpu_mid]="#ccff66"
|
||||
theme[cpu_end]="#ff0000"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_end]="#00ff00"
|
||||
theme[free_mid]="#ccff66"
|
||||
theme[free_start]="#ff0000"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#00ff00"
|
||||
theme[cached_mid]="#ccff66"
|
||||
theme[cached_end]="#ff0000"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#ff0000"
|
||||
theme[available_mid]="#ccff66"
|
||||
theme[available_end]="#00ff00"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#00ff00"
|
||||
theme[used_mid]="#ccff66"
|
||||
theme[used_end]="#ff0000"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#00ff00"
|
||||
theme[download_mid]="#ff9933"
|
||||
theme[download_end]="#ff0000"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#00ff00"
|
||||
theme[upload_mid]="#ff9933"
|
||||
theme[upload_end]="#ff0000"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#9999ff"
|
||||
theme[process_mid]="#4d4dff"
|
||||
theme[process_end]="#a64dff"
|
||||
|
89
themes/ayu.theme
Normal file
89
themes/ayu.theme
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#0B0E14"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#BFBDB6"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#BFBDB6"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#E6B450"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#E6B450"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#f8f8f2"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#565B66"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#BFBDB6"
|
||||
|
||||
# Background color of the percentage meters
|
||||
theme[meter_bg]="#565B66"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#DFBFFF"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#DFBFFF"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#95E6CB"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#F28779"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#E6B673"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#565B66"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#DFBFFF"
|
||||
theme[temp_mid]="#D2A6FF"
|
||||
theme[temp_end]="#A37ACC"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#DFBFFF"
|
||||
theme[cpu_mid]="#D2A6FF"
|
||||
theme[cpu_end]="#A37ACC"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#95E6CB"
|
||||
theme[free_mid]="#95E6CB"
|
||||
theme[free_end]="#4CBF99"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#95E6CB"
|
||||
theme[cached_mid]="#95E6CB"
|
||||
theme[cached_end]="#4CBF99"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#95E6CB"
|
||||
theme[available_mid]="#95E6CB"
|
||||
theme[available_end]="#4CBF99"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#95E6CB"
|
||||
theme[used_mid]="#95E6CB"
|
||||
theme[used_end]="#4CBF99"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#F28779"
|
||||
theme[download_mid]="#F07178"
|
||||
theme[download_end]="#F07171"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#73D0FF"
|
||||
theme[upload_mid]="#59C2FF"
|
||||
theme[upload_end]="#399EE6"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#FFCC66"
|
||||
theme[process_mid]="#E6B450"
|
||||
theme[process_end]="#FFAA33"
|
93
themes/everforest-dark-hard.theme
Normal file
93
themes/everforest-dark-hard.theme
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Btop everforest dark hard theme by u/archontop.
|
||||
|
||||
# All graphs and meters can be gradients
|
||||
# For single color graphs leave "mid" and "end" variable empty.
|
||||
# Use "start" and "end" variables for two color gradient
|
||||
# Use "start", "mid" and "end" for three color gradient
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#2b3339"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#d3c6aa"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#d3c6aa"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#e67e80"
|
||||
|
||||
# Background color of selected items
|
||||
theme[selected_bg]="#4b565c"
|
||||
|
||||
# Foreground color of selected items
|
||||
theme[selected_fg]="#dbbc7f"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#2b3339"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#d3c6aa"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#a7c080"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#4b565c"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#4b565c"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#4b565c"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#4b565c"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#4b565c"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#a7c080"
|
||||
theme[temp_mid]="#dbbc7f"
|
||||
theme[temp_end]="#f85552"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#a7c080"
|
||||
theme[cpu_mid]="#dbbc7f"
|
||||
theme[cpu_end]="#f85552"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#f85552"
|
||||
theme[free_mid]="#dbbc7f"
|
||||
theme[free_end]="#a7c080"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#7fbbb3"
|
||||
theme[cached_mid]="#83c092"
|
||||
theme[cached_end]="#a7c080"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#f85552"
|
||||
theme[available_mid]="#dbbc7f"
|
||||
theme[available_end]="#a7c080"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#a7c080"
|
||||
theme[used_mid]="#dbbc7f"
|
||||
theme[used_end]="#f85552"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#8da101"
|
||||
theme[download_mid]="#83c092"
|
||||
theme[download_end]="#a7c080"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#f85552"
|
||||
theme[upload_mid]="#dbbc7f"
|
||||
theme[upload_end]="#a7c080"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#a7c080"
|
||||
theme[process_mid]="#f85552"
|
||||
theme[process_end]="#CC241D"
|
98
themes/gruvbox_dark_v2.theme
Normal file
98
themes/gruvbox_dark_v2.theme
Normal file
|
@ -0,0 +1,98 @@
|
|||
# Bashtop gruvbox (https://github.com/morhetz/gruvbox) theme
|
||||
# First version created By BachoSeven
|
||||
# Adjustments to proper colors by Pietryszak (https://github.com/pietryszak/)
|
||||
|
||||
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
|
||||
# example for white: "#FFFFFF", "#ff" or "255 255 255".
|
||||
|
||||
# All graphs and meters can be gradients
|
||||
# For single color graphs leave "mid" and "end" variable empty.
|
||||
# Use "start" and "end" variables for two color gradient
|
||||
# Use "start", "mid" and "end" for three color gradient
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#282828"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#EBDBB2"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#EBDBB2"
|
||||
|
||||
# Highlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#CC241D"
|
||||
|
||||
# Background color of selected items
|
||||
theme[selected_bg]="#32302F"
|
||||
|
||||
# Foreground color of selected items
|
||||
theme[selected_fg]="#D3869B"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#3C3836"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#A89984"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#98971A"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#A89984"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#A89984"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#A89984"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#A89984"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#A89984"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#98971A"
|
||||
theme[temp_mid]=""
|
||||
theme[temp_end]="#CC241D"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#8EC07C"
|
||||
theme[cpu_mid]="#D79921"
|
||||
theme[cpu_end]="#CC241D"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#CC241D"
|
||||
theme[free_mid]="#D79921"
|
||||
theme[free_end]="#8EC07C"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#458588"
|
||||
theme[cached_mid]="#83A598"
|
||||
theme[cached_end]="#8EC07C"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#CC241D"
|
||||
theme[available_mid]="#D65D0E"
|
||||
theme[available_end]="#FABD2F"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#8EC07C"
|
||||
theme[used_mid]="#D65D0E"
|
||||
theme[used_end]="#CC241D"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#98971A"
|
||||
theme[download_mid]="#689d6A"
|
||||
theme[download_end]="#B8BB26"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#CC241D"
|
||||
theme[upload_mid]="#D65d0E"
|
||||
theme[upload_end]="#FABF2F"
|
||||
|
||||
# Process box color gradient for threads, mem and cpu usage
|
||||
theme[process_start]="#8EC07C"
|
||||
theme[process_mid]="#FE8019"
|
||||
theme[process_end]="#CC241D"
|
92
themes/gruvbox_material_dark.theme
Normal file
92
themes/gruvbox_material_dark.theme
Normal file
|
@ -0,0 +1,92 @@
|
|||
# Btop gruvbox material dark (https://github.com/sainnhe/gruvbox-material) theme
|
||||
# by Marco Radocchia
|
||||
|
||||
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
|
||||
# example for white: "#FFFFFF", "#ff" or "255 255 255".
|
||||
|
||||
# All graphs and meters can be gradients
|
||||
# For single color graphs leave "mid" and "end" variable empty.
|
||||
# Use "start" and "end" variables for two color gradient
|
||||
# Use "start", "mid" and "end" for three color gradient
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#282828"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#d4be98"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#d4be98"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#ea6962"
|
||||
|
||||
# Background color of selected items
|
||||
theme[selected_bg]="#d8a657"
|
||||
|
||||
# Foreground color of selected items
|
||||
theme[selected_fg]="#282828"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#282828"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#665c54"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#a9b665"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#7c6f64"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#7c6f64"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#7c6f64"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#7c6f64"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#7c6f64"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#7daea3"
|
||||
theme[temp_mid]="#e78a4e"
|
||||
theme[temp_end]="#ea6962"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#a9b665"
|
||||
theme[cpu_mid]="#d8a657"
|
||||
theme[cpu_end]="#ea6962"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#89b482"
|
||||
theme[free_mid]=""
|
||||
theme[free_end]=""
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#7daea3"
|
||||
theme[cached_mid]=""
|
||||
theme[cached_end]=""
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#d8a657"
|
||||
theme[available_mid]=""
|
||||
theme[available_end]=""
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#ea6962"
|
||||
theme[used_mid]=""
|
||||
theme[used_end]=""
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#e78a4e"
|
||||
theme[download_mid]=""
|
||||
theme[download_end]=""
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#d3869b"
|
||||
theme[upload_mid]=""
|
||||
theme[upload_end]=""
|
92
themes/night-owl.theme
Normal file
92
themes/night-owl.theme
Normal file
|
@ -0,0 +1,92 @@
|
|||
#Bashtop theme with night-owl colors
|
||||
#by zkourouma
|
||||
|
||||
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
|
||||
# example for white: "#ffffff", "#ff" or "255 255 255".
|
||||
|
||||
# All graphs and meters can be gradients
|
||||
# For single color graphs leave "mid" and "end" variable empty.
|
||||
# Use "start" and "end" variables for two color gradient
|
||||
# Use "start", "mid" and "end" for three color gradient
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#011627"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#d6deeb"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#ffffff"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#addb67"
|
||||
|
||||
# Background color of selected items
|
||||
theme[selected_bg]="#000000"
|
||||
|
||||
# Foreground color of selected items
|
||||
theme[selected_fg]="#ffeb95"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#575656"
|
||||
|
||||
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
|
||||
theme[graph_text]="#585858"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#22da6e"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#ffffff"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#ffffff"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#ffffff"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#ffffff"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#ffffff"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#82aaff"
|
||||
theme[temp_mid]="#c792ea"
|
||||
theme[temp_end]="#fb4394"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#22da6e"
|
||||
theme[cpu_mid]="#addb67"
|
||||
theme[cpu_end]="#ef5350"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#4e5900"
|
||||
theme[free_mid]=""
|
||||
theme[free_end]="#22da6e"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#82aaff"
|
||||
theme[cached_mid]=""
|
||||
theme[cached_end]="#82aaff"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#addb67"
|
||||
theme[available_mid]=""
|
||||
theme[available_end]="#ffeb95"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#ef5350"
|
||||
theme[used_mid]=""
|
||||
theme[used_end]="#ef5350"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#3d4070"
|
||||
theme[download_mid]="#6c71c4"
|
||||
theme[download_end]="#a3a8f7"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#701c45"
|
||||
theme[upload_mid]="#c792ea"
|
||||
theme[upload_end]="#c792ea"
|
81
themes/onedark.theme
Normal file
81
themes/onedark.theme
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Theme: OneDark
|
||||
# By: Vitor Melo
|
||||
|
||||
# Main bg
|
||||
theme[main_bg]="#282c34"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#abb2bf"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#abb2bf"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#61afef"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#2c313c"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#abb2bf"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#5c6370"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#61afef"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#5c6370"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#5c6370"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#5c6370"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#5c6370"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#5c6370"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#98c379"
|
||||
theme[temp_mid]="#e5c07b"
|
||||
theme[temp_end]="#e06c75"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#98c379"
|
||||
theme[cpu_mid]="#e5c07b"
|
||||
theme[cpu_end]="#e06c75"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#98c379"
|
||||
theme[free_mid]="#e5c07b"
|
||||
theme[free_end]="#e06c75"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#98c379"
|
||||
theme[cached_mid]="#e5c07b"
|
||||
theme[cached_end]="#e06c75"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#98c379"
|
||||
theme[available_mid]="#e5c07b"
|
||||
theme[available_end]="#e06c75"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#98c379"
|
||||
theme[used_mid]="#e5c07b"
|
||||
theme[used_end]="#e06c75"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#98c379"
|
||||
theme[download_mid]="#e5c07b"
|
||||
theme[download_end]="#e06c75"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#98c379"
|
||||
theme[upload_mid]="#e5c07b"
|
||||
theme[upload_end]="#e06c75"
|
81
themes/tokyo-night.theme
Normal file
81
themes/tokyo-night.theme
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Theme: tokyo-night
|
||||
# By: Pascal Jaeger
|
||||
|
||||
# Main bg
|
||||
theme[main_bg]="#1a1b26"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#cfc9c2"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#cfc9c2"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#7dcfff"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#414868"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#cfc9c2"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#565f89"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#7dcfff"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#565f89"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#565f89"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#565f89"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#565f89"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#565f89"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#9ece6a"
|
||||
theme[temp_mid]="#e0af68"
|
||||
theme[temp_end]="#f7768e"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#9ece6a"
|
||||
theme[cpu_mid]="#e0af68"
|
||||
theme[cpu_end]="#f7768e"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#9ece6a"
|
||||
theme[free_mid]="#e0af68"
|
||||
theme[free_end]="#f7768e"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#9ece6a"
|
||||
theme[cached_mid]="#e0af68"
|
||||
theme[cached_end]="#f7768e"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#9ece6a"
|
||||
theme[available_mid]="#e0af68"
|
||||
theme[available_end]="#f7768e"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#9ece6a"
|
||||
theme[used_mid]="#e0af68"
|
||||
theme[used_end]="#f7768e"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#9ece6a"
|
||||
theme[download_mid]="#e0af68"
|
||||
theme[download_end]="#f7768e"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#9ece6a"
|
||||
theme[upload_mid]="#e0af68"
|
||||
theme[upload_end]="#f7768e"
|
81
themes/tokyo-storm.theme
Normal file
81
themes/tokyo-storm.theme
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Theme: tokyo-storm
|
||||
# By: Pascal Jaeger
|
||||
|
||||
# Main bg
|
||||
theme[main_bg]="#24283b"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#cfc9c2"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#cfc9c2"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#7dcfff"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#414868"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#cfc9c2"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#565f89"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#7dcfff"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#565f89"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#565f89"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#565f89"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#565f89"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#565f89"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#9ece6a"
|
||||
theme[temp_mid]="#e0af68"
|
||||
theme[temp_end]="#f7768e"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#9ece6a"
|
||||
theme[cpu_mid]="#e0af68"
|
||||
theme[cpu_end]="#f7768e"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#9ece6a"
|
||||
theme[free_mid]="#e0af68"
|
||||
theme[free_end]="#f7768e"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#9ece6a"
|
||||
theme[cached_mid]="#e0af68"
|
||||
theme[cached_end]="#f7768e"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#9ece6a"
|
||||
theme[available_mid]="#e0af68"
|
||||
theme[available_end]="#f7768e"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#9ece6a"
|
||||
theme[used_mid]="#e0af68"
|
||||
theme[used_end]="#f7768e"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#9ece6a"
|
||||
theme[download_mid]="#e0af68"
|
||||
theme[download_end]="#f7768e"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#9ece6a"
|
||||
theme[upload_mid]="#e0af68"
|
||||
theme[upload_end]="#f7768e"
|
89
themes/tomorrow-night.theme
Normal file
89
themes/tomorrow-night.theme
Normal file
|
@ -0,0 +1,89 @@
|
|||
#Nord theme but using the Tomorrow Night palette
|
||||
#by Appuchia <contact@appu.ltd>
|
||||
|
||||
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
|
||||
# example for white: "#ffffff", "#ff" or "255 255 255".
|
||||
|
||||
# All graphs and meters can be gradients
|
||||
# For single color graphs leave "mid" and "end" variable empty.
|
||||
# Use "start" and "end" variables for two color gradient
|
||||
# Use "start", "mid" and "end" for three color gradient
|
||||
|
||||
# Main background, empty for terminal default, need to be empty if you want transparent background
|
||||
theme[main_bg]="#1d1f21"
|
||||
|
||||
# Main text color
|
||||
theme[main_fg]="#c5c8c6"
|
||||
|
||||
# Title color for boxes
|
||||
theme[title]="#c5c8c6"
|
||||
|
||||
# Higlight color for keyboard shortcuts
|
||||
theme[hi_fg]="#81beb7"
|
||||
|
||||
# Background color of selected item in processes box
|
||||
theme[selected_bg]="#282a2e"
|
||||
|
||||
# Foreground color of selected item in processes box
|
||||
theme[selected_fg]="#c5c8c6"
|
||||
|
||||
# Color of inactive/disabled text
|
||||
theme[inactive_fg]="#373b41"
|
||||
|
||||
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
|
||||
theme[proc_misc]="#969896"
|
||||
|
||||
# Cpu box outline color
|
||||
theme[cpu_box]="#81a2be"
|
||||
|
||||
# Memory/disks box outline color
|
||||
theme[mem_box]="#81a2be"
|
||||
|
||||
# Net up/down box outline color
|
||||
theme[net_box]="#81a2be"
|
||||
|
||||
# Processes box outline color
|
||||
theme[proc_box]="#81a2be"
|
||||
|
||||
# Box divider line and small boxes line color
|
||||
theme[div_line]="#81a2be"
|
||||
|
||||
# Temperature graph colors
|
||||
theme[temp_start]="#b5bd68"
|
||||
theme[temp_mid]="#f0c674"
|
||||
theme[temp_end]="#cc6666"
|
||||
|
||||
# CPU graph colors
|
||||
theme[cpu_start]="#b5bd68"
|
||||
theme[cpu_mid]="#f0c674"
|
||||
theme[cpu_end]="#cc6666"
|
||||
|
||||
# Mem/Disk free meter
|
||||
theme[free_start]="#b5bd68"
|
||||
theme[free_mid]="#f0c674"
|
||||
theme[free_end]="#cc6666"
|
||||
|
||||
# Mem/Disk cached meter
|
||||
theme[cached_start]="#b5bd68"
|
||||
theme[cached_mid]="#f0c674"
|
||||
theme[cached_end]="#cc6666"
|
||||
|
||||
# Mem/Disk available meter
|
||||
theme[available_start]="#b5bd68"
|
||||
theme[available_mid]="#f0c674"
|
||||
theme[available_end]="#cc6666"
|
||||
|
||||
# Mem/Disk used meter
|
||||
theme[used_start]="#b5bd68"
|
||||
theme[used_mid]="#f0c674"
|
||||
theme[used_end]="#cc6666"
|
||||
|
||||
# Download graph colors
|
||||
theme[download_start]="#b5bd68"
|
||||
theme[download_mid]="#f0c674"
|
||||
theme[download_end]="#cc6666"
|
||||
|
||||
# Upload graph colors
|
||||
theme[upload_start]="#b5bd68"
|
||||
theme[upload_mid]="#f0c674"
|
||||
theme[upload_end]="#cc6666"
|
Loading…
Reference in a new issue