other: mention memory/network alias in deprecation warnings (#2102)

This commit is contained in:
Clement Tsang
2026-06-22 02:25:54 -04:00
committed by GitHub
parent 9332d46b40
commit b3694fc3f4
5 changed files with 74 additions and 23 deletions
+3 -2
View File
@@ -20,11 +20,12 @@ That said, these are more guidelines rather than hard rules, though the project
---
## 0.14.1 - 2026-06-21
## 0.14.1 - 2026-06-22
### Bug Fixes
### Other
- [#2096](https://github.com/ClementTsang/bottom/pull/2096): Fix documentation suggestions around `memory_graph`.
- [#2102](https://github.com/ClementTsang/bottom/pull/2102): Mention memory/network alias in deprecation warnings.
## 0.14.0 - 2026-06-20
@@ -50,8 +50,8 @@ each time:
| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. |
| `unnormalized_cpu` | Boolean | Deprecated - use `processes.unnormalized_cpu`. Show process CPU% without normalizing over the number of cores. |
| `expanded` | Boolean | Expand the default widget upon starting the app. |
| `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Deprecated - use `memory_graph.legend_position`. Where to place the legend for the memory widget. |
| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Deprecated - use `network_graph.legend_position`. Where to place the legend for the network widget. |
| `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Deprecated - use `memory_graph.legend_position` or `memory.legend_position`; where to place the legend for the memory widget. |
| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Deprecated - use `network_graph.legend_position` or `network.legend_position`; where to place the legend for the network widget. |
| `average_cpu_row` | Boolean | Deprecated - use `cpu.basic_average_cpu_row`. Moves the average CPU usage entry to its own row when using basic mode. |
| `tree_collapse` | Boolean | Deprecated - use `processes.tree_collapse`. Collapse process tree by default. |
| `autohide_time` | Boolean | Temporarily shows the time scale in graphs. |
+2 -2
View File
@@ -147,11 +147,11 @@
# How much data is stored at once in terms of time.
#retention = "10m"
# Deprecated - use memory_graph.legend_position.
# Deprecated - use memory_graph.legend_position or memory.legend_position.
# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
#memory_legend = "top-right"
# Deprecated - use network_graph.legend_position.
# Deprecated - use network_graph.legend_position or network.legend_position.
# Where to place the legend for the network widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
#network_legend = "top-right"
+2 -2
View File
@@ -396,11 +396,11 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott
# How much data is stored at once in terms of time.
#retention = "10m"
# Deprecated - use memory_graph.legend_position.
# Deprecated - use memory_graph.legend_position or memory.legend_position.
# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
#memory_legend = "top-right"
# Deprecated - use network_graph.legend_position.
# Deprecated - use network_graph.legend_position or network.legend_position.
# Where to place the legend for the network widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
#network_legend = "top-right"
+65 -15
View File
@@ -95,6 +95,26 @@ macro_rules! enabled_option_with_deprecated {
false
}
};
($arg:expr, $config:expr, $section:ident . $field:ident, $flags:ident . $deprecated_flag:ident, $alias:literal $(,)?) => {
if $arg {
true
} else if let Some(section) = &$config.$section {
section.$field.unwrap_or(false)
} else if let Some(flags) = &$config.flags {
flags
.$deprecated_flag
.inspect(|_| {
deprecated_warning_with_alias(
stringify!($deprecated_flag),
stringify!($section.$field),
$alias,
)
})
.unwrap_or(false)
} else {
false
}
};
}
/// Get the value of a field for a specific section in the config file if set. If not set, the default is used.
@@ -283,6 +303,7 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
config,
memory_graph.free_arc,
flags.free_arc,
"memory.free_arc",
);
// For processes
@@ -381,6 +402,7 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
config,
network_graph.use_binary_prefix,
flags.network_use_binary_prefix,
"network.use_binary_prefix",
);
let network_show_packets =
is_flag_enabled_in!(show_packets, args.network, config.network_graph);
@@ -418,6 +440,9 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
.and_then(|cfg| cfg.include_unmounted)
.unwrap_or(false);
let enable_cache_memory = get_enable_cache_memory(args, config);
let enable_gpu = get_enable_gpu(args, config);
// TODO: Can probably just reuse the options struct.
let app_config_fields = AppConfigFields {
update_rate: get_update_rate(args, config)?,
@@ -454,9 +479,9 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
table_gap: config_or_default!(config, flags.table_gap),
disable_click: is_flag_enabled!(disable_click, args.general, config),
disable_keys: is_flag_enabled!(disable_keys, args.general, config),
enable_gpu: get_enable_gpu(args, config),
enable_gpu,
short_gpu_names: get_short_gpu_names(args, config),
enable_cache_memory: get_enable_cache_memory(args, config),
enable_cache_memory,
show_table_scroll_position: is_flag_enabled!(
show_table_scroll_position,
args.general,
@@ -710,8 +735,8 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
let used_widgets = UsedWidgets {
use_cpu: used_widget_set.contains(&Cpu) || used_widget_set.contains(&BasicCpu),
use_mem,
use_cache: use_mem && get_enable_cache_memory(args, config),
use_gpu: get_enable_gpu(args, config),
use_cache: use_mem && enable_cache_memory,
use_gpu: enable_gpu,
use_net: used_widget_set.contains(&Net) || used_widget_set.contains(&BasicNet),
use_proc: used_widget_set.contains(&Proc),
use_disk: used_widget_set.contains(&Disk),
@@ -953,6 +978,14 @@ fn deprecated_warning(deprecated_field: &str, new_field: &str) {
);
}
/// Mark a config option field as deprecated, and what to use instead with an alias.
#[inline]
fn deprecated_warning_with_alias(deprecated_field: &str, new_field: &str, alias: &str) {
eprintln!(
"Warning: The config option '{deprecated_field}' is deprecated and will eventually be removed. Please use '{new_field}' or '{alias}' instead.",
);
}
/// How quickly we update data.
#[inline]
fn get_update_rate(args: &BottomArgs, config: &Config) -> OptionResult<u64> {
@@ -1166,6 +1199,7 @@ fn get_enable_cache_memory(args: &BottomArgs, config: &Config) -> bool {
config,
memory_graph.cache_memory,
flags.enable_cache_memory,
"memory.cache_memory",
)
}
@@ -1220,7 +1254,11 @@ fn get_network_unit_type(args: &BottomArgs, config: &Config) -> DataUnit {
} else if let Some(flags) = &config.flags
&& let Some(network_use_bytes) = flags.network_use_bytes
{
deprecated_warning("network_use_bytes", "network_graph.use_bytes");
deprecated_warning_with_alias(
"network_use_bytes",
"network_graph.use_bytes",
"network.use_bytes",
);
if network_use_bytes {
return DataUnit::Byte;
@@ -1240,7 +1278,11 @@ fn get_network_scale_type(args: &BottomArgs, config: &Config) -> AxisScaling {
} else if let Some(flags) = &config.flags
&& let Some(network_use_log) = flags.network_use_log
{
deprecated_warning("network_use_log", "network_graph.use_log");
deprecated_warning_with_alias(
"network_use_log",
"network_graph.use_log",
"network.use_log",
);
if network_use_log {
return AxisScaling::Log;
@@ -1269,7 +1311,7 @@ fn get_retention(args: &BottomArgs, config: &Config) -> OptionResult<u64> {
#[inline]
fn parse_legend_position(
arg: Option<&String>, cfg: Option<&String>, deprecated_cfg: Option<(&String, &'static str)>,
setting: &'static str,
setting: &'static str, alias: Option<&'static str>,
) -> OptionResult<Option<LegendPosition>> {
#[inline]
fn parse_position_or_err<F: FnOnce(&'static str) -> OptionError>(
@@ -1287,7 +1329,11 @@ fn parse_legend_position(
parse_position_or_err(s, setting, OptionError::invalid_config_value)
} else if let Some((s, name)) = deprecated_cfg {
// Remove the deprecated args/code paths and copy back to the function above later.
deprecated_warning(name, setting);
if let Some(alias) = alias {
deprecated_warning_with_alias(name, setting, alias);
} else {
deprecated_warning(name, setting);
}
parse_position_or_err(s, setting, OptionError::invalid_config_value)
} else {
Ok(Some(LegendPosition::default()))
@@ -1309,6 +1355,7 @@ fn get_network_legend_position(
.and_then(|flags| flags.network_legend.as_ref())
.map(|s| (s, "network_legend")),
"network_graph.legend_position",
Some("network.legend_position"),
)
}
@@ -1327,6 +1374,7 @@ fn get_memory_legend_position(
.and_then(|flags| flags.memory_legend.as_ref())
.map(|s| (s, "memory_legend")),
"memory_graph.legend_position",
Some("memory.legend_position"),
)
}
@@ -1339,6 +1387,7 @@ fn get_temperature_legend_position(config: &Config) -> OptionResult<Option<Legen
.and_then(|settings| settings.legend_position.as_ref()),
None,
"legend_position",
None,
)
}
@@ -1351,6 +1400,7 @@ fn get_disk_io_legend_position(config: &Config) -> OptionResult<Option<LegendPos
.and_then(|settings| settings.legend_position.as_ref()),
None,
"disk_io_graph.legend_position",
None,
)
}
@@ -1394,7 +1444,7 @@ mod test {
// No arg, no config.
assert_eq!(
parse_legend_position(None, None, None, setting),
parse_legend_position(None, None, None, setting, None),
Ok(Some(LegendPosition::default()))
);
@@ -1402,40 +1452,40 @@ mod test {
let arg = " ToP-lEfT ".to_string();
let cfg = "bottom-right".to_string();
assert_eq!(
parse_legend_position(Some(&arg), Some(&cfg), None, setting),
parse_legend_position(Some(&arg), Some(&cfg), None, setting, None),
Ok(Some(LegendPosition::TopLeft))
);
// "none" disables the legend, from either source.
let none_arg = "None".to_string();
assert_eq!(
parse_legend_position(Some(&none_arg), None, None, setting),
parse_legend_position(Some(&none_arg), None, None, setting, None),
Ok(None)
);
let none_cfg = "none".to_string();
assert_eq!(
parse_legend_position(None, Some(&none_cfg), None, setting),
parse_legend_position(None, Some(&none_cfg), None, setting, None),
Ok(None)
);
// Config value is used when no arg is provided.
let cfg_only = "left".to_string();
assert_eq!(
parse_legend_position(None, Some(&cfg_only), None, setting),
parse_legend_position(None, Some(&cfg_only), None, setting, None),
Ok(Some(LegendPosition::Left))
);
// Invalid arg value.
let bad_arg = "bad".to_string();
assert_eq!(
parse_legend_position(Some(&bad_arg), None, None, setting),
parse_legend_position(Some(&bad_arg), None, None, setting, None),
Err(OptionError::invalid_arg_value(setting))
);
// Invalid config value.
let bad_cfg = "bad".to_string();
assert_eq!(
parse_legend_position(None, Some(&bad_cfg), None, setting),
parse_legend_position(None, Some(&bad_cfg), None, setting, None),
Err(OptionError::invalid_config_value(setting))
);
}