docs: update docs on filter (#1519)

Updates some outdated docs on filtering, and adds some tests as well. In particular, this also adds a cfg_attr on tests to try and catch unknown fields; we'll be more lenient in prod builds though and allow them.
This commit is contained in:
Clement Tsang 2024-07-31 06:41:30 +00:00 committed by GitHub
parent 2c0fb2a723
commit a6e1ea3bd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 59 additions and 12 deletions

View File

@ -4,7 +4,7 @@
This section is in progress, and is just copied from the old documentation. This section is in progress, and is just copied from the old documentation.
You can hide specific disks, temperature sensors, and networks by name in the config file via `disk_filter` and `mount_filter`, `temp_filter`, and `net_filter` respectively. Regex (`regex = true`), case-sensitivity (`case_sensitive = true`), and matching only if the entire word matches (`whole_word = true`) are supported, but are off by default. Filters default to denying entries that match and can be toggled by setting `is_list_ignored` to `false` in the config file. You can hide specific disks, temperature sensors, and networks by name in the config file via `disk.name_filter` and `disk.mount_filter`, `temperature.sensor_filter`, and `network.interface_filter` respectively. Regex (`regex = true`), case-sensitivity (`case_sensitive = true`), and matching only if the entire word matches (`whole_word = true`) are supported, but are off by default. Filters default to denying entries that match and can be toggled by setting `is_list_ignored` to `false` in the config file.
For example, here's the disk widget with no filter: For example, here's the disk widget with no filter:
@ -13,7 +13,7 @@ For example, here's the disk widget with no filter:
The following in the config file would filter out some entries by disk name: The following in the config file would filter out some entries by disk name:
```toml ```toml
[disk_filter] [disk.name_filter]
is_list_ignored = true is_list_ignored = true
list = ["/dev/sda"] list = ["/dev/sda"]
regex = true regex = true
@ -26,14 +26,14 @@ whole_word = false
If there are two potentially conflicting filters (i.e. when you are using both a disk and mount filter), the filter that explicitly allows an entry takes precedence over a filter that explicitly denies one. So for example, let's say we set a disk filter accepting anything with `/dev/sda`, but deny anything with `/mnt/.*` or `/`. So to do so, we write in the config file: If there are two potentially conflicting filters (i.e. when you are using both a disk and mount filter), the filter that explicitly allows an entry takes precedence over a filter that explicitly denies one. So for example, let's say we set a disk filter accepting anything with `/dev/sda`, but deny anything with `/mnt/.*` or `/`. So to do so, we write in the config file:
```toml ```toml
[disk_filter] [disk.name_filter]
is_list_ignored = false is_list_ignored = false
list = ["/dev/sda"] list = ["/dev/sda"]
regex = true regex = true
case_sensitive = false case_sensitive = false
whole_word = false whole_word = false
[mount_filter] [disk.mount_filter]
is_list_ignored = true is_list_ignored = true
list = ["/mnt/.*", "/"] list = ["/mnt/.*", "/"]
regex = true regex = true

View File

@ -93,14 +93,14 @@
# Disk widget configuration # Disk widget configuration
#[disk] #[disk]
#[disk.name_filter] #[name_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["/dev/sda\\d+", "/dev/nvme0n1p2"] #list = ["/dev/sda\\d+", "/dev/nvme0n1p2"]
#regex = true #regex = true
#case_sensitive = false #case_sensitive = false
#whole_word = false #whole_word = false
#[disk.mount_filter] #[mount_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["/mnt/.*", "/boot"] #list = ["/mnt/.*", "/boot"]
#regex = true #regex = true
@ -109,7 +109,7 @@
# Temperature widget configuration # Temperature widget configuration
#[temperature] #[temperature]
#[temperature.sensor_filter] #[sensor_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["cpu", "wifi"] #list = ["cpu", "wifi"]
#regex = false #regex = false
@ -118,7 +118,7 @@
# Network widget configuration # Network widget configuration
#[network] #[network]
#[network.interface_filter] #[interface_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["virbr0.*"] #list = ["virbr0.*"]
#regex = true #regex = true

View File

@ -357,14 +357,14 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al
# Disk widget configuration # Disk widget configuration
#[disk] #[disk]
#[disk.name_filter] #[name_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["/dev/sda\\d+", "/dev/nvme0n1p2"] #list = ["/dev/sda\\d+", "/dev/nvme0n1p2"]
#regex = true #regex = true
#case_sensitive = false #case_sensitive = false
#whole_word = false #whole_word = false
#[disk.mount_filter] #[mount_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["/mnt/.*", "/boot"] #list = ["/mnt/.*", "/boot"]
#regex = true #regex = true
@ -373,7 +373,7 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al
# Temperature widget configuration # Temperature widget configuration
#[temperature] #[temperature]
#[temperature.sensor_filter] #[sensor_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["cpu", "wifi"] #list = ["cpu", "wifi"]
#regex = false #regex = false
@ -382,7 +382,7 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al
# Network widget configuration # Network widget configuration
#[network] #[network]
#[network.interface_filter] #[interface_filter]
#is_list_ignored = true #is_list_ignored = true
#list = ["virbr0.*"] #list = ["virbr0.*"]
#regex = true #regex = true

View File

@ -24,6 +24,7 @@ use self::{cpu::CpuConfig, layout::Row, process::ProcessesConfig};
derive(schemars::JsonSchema), derive(schemars::JsonSchema),
schemars(title = "Schema for bottom's configs (nightly)") schemars(title = "Schema for bottom's configs (nightly)")
)] )]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct Config { pub struct Config {
pub(crate) flags: Option<FlagConfig>, pub(crate) flags: Option<FlagConfig>,
pub(crate) styles: Option<StyleConfig>, pub(crate) styles: Option<StyleConfig>,

View File

@ -15,6 +15,7 @@ pub enum CpuDefault {
/// CPU column settings. /// CPU column settings.
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct CpuConfig { pub struct CpuConfig {
#[serde(default)] #[serde(default)]
pub default: CpuDefault, pub default: CpuDefault,

View File

@ -5,6 +5,7 @@ use super::IgnoreList;
/// Disk configuration. /// Disk configuration.
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct DiskConfig { pub struct DiskConfig {
/// A filter over the disk names. /// A filter over the disk names.
pub name_filter: Option<IgnoreList>, pub name_filter: Option<IgnoreList>,

View File

@ -4,6 +4,7 @@ use super::StringOrNum;
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub(crate) struct FlagConfig { pub(crate) struct FlagConfig {
pub(crate) hide_avg_cpu: Option<bool>, pub(crate) hide_avg_cpu: Option<bool>,
pub(crate) dot_marker: Option<bool>, pub(crate) dot_marker: Option<bool>,

View File

@ -7,6 +7,7 @@ fn default_as_true() -> bool {
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct IgnoreList { pub struct IgnoreList {
#[serde(default = "default_as_true")] #[serde(default = "default_as_true")]
// TODO: Deprecate and/or rename, current name sounds awful. // TODO: Deprecate and/or rename, current name sounds awful.

View File

@ -6,6 +6,7 @@ use crate::{app::layout_manager::*, options::OptionResult};
/// of children. /// of children.
#[derive(Clone, Deserialize, Debug, Serialize)] #[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
#[serde(rename = "row")] #[serde(rename = "row")]
pub struct Row { pub struct Row {
pub ratio: Option<u32>, pub ratio: Option<u32>,
@ -217,6 +218,7 @@ impl Row {
#[derive(Clone, Deserialize, Debug, Serialize)] #[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub enum RowChildren { pub enum RowChildren {
Widget(FinalWidget), Widget(FinalWidget),
Col { Col {
@ -228,6 +230,7 @@ pub enum RowChildren {
/// Represents a widget. /// Represents a widget.
#[derive(Clone, Deserialize, Debug, Serialize)] #[derive(Clone, Deserialize, Debug, Serialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct FinalWidget { pub struct FinalWidget {
pub ratio: Option<u32>, pub ratio: Option<u32>,
#[serde(rename = "type")] #[serde(rename = "type")]

View File

@ -5,6 +5,7 @@ use super::IgnoreList;
/// Network configuration. /// Network configuration.
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct NetworkConfig { pub struct NetworkConfig {
/// A filter over the network interface names. /// A filter over the network interface names.
pub interface_filter: Option<IgnoreList>, pub interface_filter: Option<IgnoreList>,

View File

@ -5,6 +5,7 @@ use crate::widgets::ProcWidgetColumn;
/// Process configuration. /// Process configuration.
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct ProcessesConfig { pub struct ProcessesConfig {
/// A list of process widget columns. /// A list of process widget columns.
#[serde(default)] #[serde(default)]

View File

@ -35,6 +35,7 @@ pub(crate) struct ColorStr(Cow<'static, str>);
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub(crate) enum TextStyleConfig { pub(crate) enum TextStyleConfig {
Colour(ColorStr), Colour(ColorStr),
TextStyle { TextStyle {

View File

@ -5,6 +5,7 @@ use super::IgnoreList;
/// Temperature configuration. /// Temperature configuration.
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
#[cfg_attr(test, serde(deny_unknown_fields))]
pub struct TempConfig { pub struct TempConfig {
/// A filter over the sensor names. /// A filter over the sensor names.
pub sensor_filter: Option<IgnoreList>, pub sensor_filter: Option<IgnoreList>,

View File

@ -82,3 +82,8 @@ fn test_styling_sanity_check() {
fn test_styling_sanity_check_2() { fn test_styling_sanity_check_2() {
run_and_kill(&["-C", "./tests/valid_configs/styling_2.toml"]); run_and_kill(&["-C", "./tests/valid_configs/styling_2.toml"]);
} }
#[test]
fn test_filtering() {
run_and_kill(&["-C", "./tests/valid_configs/filtering.toml"]);
}

View File

@ -0,0 +1,30 @@
[disk]
[name_filter]
is_list_ignored = true
list = ["/dev/sda\\d+", "/dev/nvme0n1p2"]
regex = true
case_sensitive = false
whole_word = false
[mount_filter]
is_list_ignored = true
list = ["/mnt/.*", "/boot"]
regex = true
case_sensitive = false
whole_word = false
[temperature]
[sensor_filter]
is_list_ignored = true
list = ["cpu", "wifi"]
regex = false
case_sensitive = false
whole_word = false
[network]
[interface_filter]
is_list_ignored = true
list = ["virbr0.*"]
regex = true
case_sensitive = false
whole_word = false