mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-26 15:14:13 +02:00
Fix dialog box height and scroll label (#71)
* Fixes search with small mode by changing the prompt based on size. * Minor fixes for search - Remove ignore unused var lint - Add a bit more spacing to deal with large unicode - Add on-right movement on type * Add contributor's list and bug/req section * Check for div by zero * Fix for dd in terms of sizing. * Added (temporary) fix for help box. Scrolling is the ideal solution but will leave that for another time.
This commit is contained in:
parent
e16eb832fc
commit
132a5a2170
10
README.md
10
README.md
@ -210,12 +210,22 @@ Note that `q` is disabled while in the search widget.
|
|||||||
|
|
||||||
- Scrolling with the mouse will scroll through the currently selected list if the widget is a scrollable table.
|
- Scrolling with the mouse will scroll through the currently selected list if the widget is a scrollable table.
|
||||||
|
|
||||||
|
## Bugs and Requests
|
||||||
|
|
||||||
|
Spot an bug? Have an idea? Leave an issue that explains what you want in detail and I'll try to take a look.
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
Contribution is welcome! Just submit a PR. Note that I develop and test on stable Rust.
|
Contribution is welcome! Just submit a PR. Note that I develop and test on stable Rust.
|
||||||
|
|
||||||
If you spot any issue with nobody assigned to it, or it seems like no work has started on it, feel free to try and do it!
|
If you spot any issue with nobody assigned to it, or it seems like no work has started on it, feel free to try and do it!
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Thanks to those who have contributed:
|
||||||
|
|
||||||
|
- [shilangyu](https://github.com/shilangyu)
|
||||||
|
|
||||||
## Thanks, kudos, and all the like
|
## Thanks, kudos, and all the like
|
||||||
|
|
||||||
- This project is very much inspired by both [gotop](https://github.com/cjbassi/gotop) and [gtop](https://github.com/aksakalli/gtop).
|
- This project is very much inspired by both [gotop](https://github.com/cjbassi/gotop) and [gtop](https://github.com/aksakalli/gtop).
|
||||||
|
@ -945,6 +945,8 @@ impl App {
|
|||||||
|
|
||||||
self.update_regex();
|
self.update_regex();
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
|
self.process_search_state.search_state.cursor_direction =
|
||||||
|
CursorDirection::RIGHT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match caught_char {
|
match caught_char {
|
||||||
|
@ -45,8 +45,14 @@ pub async fn get_network_data(
|
|||||||
|
|
||||||
let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64();
|
let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64();
|
||||||
|
|
||||||
let rx = ((total_rx - *prev_net_rx) as f64 / elapsed_time) as u64;
|
let (rx, tx) = if elapsed_time == 0.0 {
|
||||||
let tx = ((total_tx - *prev_net_tx) as f64 / elapsed_time) as u64;
|
(0, 0)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
((total_rx - *prev_net_rx) as f64 / elapsed_time) as u64,
|
||||||
|
((total_tx - *prev_net_tx) as f64 / elapsed_time) as u64,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
*prev_net_rx = total_rx;
|
*prev_net_rx = total_rx;
|
||||||
*prev_net_tx = total_tx;
|
*prev_net_tx = total_tx;
|
||||||
|
147
src/canvas.rs
147
src/canvas.rs
@ -187,16 +187,21 @@ impl Painter {
|
|||||||
|
|
||||||
terminal.autoresize()?;
|
terminal.autoresize()?;
|
||||||
terminal.draw(|mut f| {
|
terminal.draw(|mut f| {
|
||||||
|
debug!("{:?}", f.size());
|
||||||
if app_state.help_dialog_state.is_showing_help {
|
if app_state.help_dialog_state.is_showing_help {
|
||||||
// Only for the help
|
// Only for the help
|
||||||
|
|
||||||
|
// TODO: [RESIZE] Scrolling dialog boxes is ideal. This is currently VERY temporary!
|
||||||
|
// The width is currently not good and can wrap... causing this to not go so well!
|
||||||
|
let gen_help_len = GENERAL_HELP_TEXT.len() as u16 + 3;
|
||||||
|
let border_len = (max(0, f.size().height as i64 - gen_help_len as i64)) as u16 / 2;
|
||||||
let vertical_dialog_chunk = Layout::default()
|
let vertical_dialog_chunk = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.margin(1)
|
|
||||||
.constraints(
|
.constraints(
|
||||||
[
|
[
|
||||||
Constraint::Percentage(20),
|
Constraint::Length(border_len),
|
||||||
Constraint::Percentage(60),
|
Constraint::Length(gen_help_len),
|
||||||
Constraint::Percentage(20),
|
Constraint::Length(border_len),
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
@ -204,13 +209,21 @@ impl Painter {
|
|||||||
|
|
||||||
let middle_dialog_chunk = Layout::default()
|
let middle_dialog_chunk = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.margin(0)
|
|
||||||
.constraints(
|
.constraints(
|
||||||
|
if f.size().width < 100 {
|
||||||
|
// TODO: [REFACTOR] The point we start changing size at currently hard-coded in.
|
||||||
|
[
|
||||||
|
Constraint::Percentage(0),
|
||||||
|
Constraint::Percentage(100),
|
||||||
|
Constraint::Percentage(0),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
[
|
[
|
||||||
Constraint::Percentage(20),
|
Constraint::Percentage(20),
|
||||||
Constraint::Percentage(60),
|
Constraint::Percentage(60),
|
||||||
Constraint::Percentage(20),
|
Constraint::Percentage(20),
|
||||||
]
|
]
|
||||||
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
.split(vertical_dialog_chunk[1]);
|
.split(vertical_dialog_chunk[1]);
|
||||||
@ -247,14 +260,14 @@ impl Painter {
|
|||||||
.wrap(true)
|
.wrap(true)
|
||||||
.render(&mut f, middle_dialog_chunk[1]);
|
.render(&mut f, middle_dialog_chunk[1]);
|
||||||
} else if app_state.delete_dialog_state.is_showing_dd {
|
} else if app_state.delete_dialog_state.is_showing_dd {
|
||||||
|
let bordering = (max(0, f.size().height as i64 - 7) as u16) / 2;
|
||||||
let vertical_dialog_chunk = Layout::default()
|
let vertical_dialog_chunk = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.margin(1)
|
|
||||||
.constraints(
|
.constraints(
|
||||||
[
|
[
|
||||||
Constraint::Percentage(35),
|
Constraint::Length(bordering),
|
||||||
Constraint::Percentage(30),
|
Constraint::Length(7),
|
||||||
Constraint::Percentage(35),
|
Constraint::Length(bordering),
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
@ -262,13 +275,21 @@ impl Painter {
|
|||||||
|
|
||||||
let middle_dialog_chunk = Layout::default()
|
let middle_dialog_chunk = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.margin(0)
|
|
||||||
.constraints(
|
.constraints(
|
||||||
|
if f.size().width < 100 {
|
||||||
|
// TODO: [REFACTOR] The point we start changing size at currently hard-coded in.
|
||||||
[
|
[
|
||||||
Constraint::Percentage(25),
|
Constraint::Percentage(5),
|
||||||
Constraint::Percentage(50),
|
Constraint::Percentage(90),
|
||||||
Constraint::Percentage(25),
|
Constraint::Percentage(5),
|
||||||
]
|
]
|
||||||
|
} else {
|
||||||
|
[
|
||||||
|
Constraint::Percentage(30),
|
||||||
|
Constraint::Percentage(40),
|
||||||
|
Constraint::Percentage(30),
|
||||||
|
]
|
||||||
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
.split(vertical_dialog_chunk[1]);
|
.split(vertical_dialog_chunk[1]);
|
||||||
@ -306,22 +327,24 @@ impl Painter {
|
|||||||
if app_state.is_grouped() {
|
if app_state.is_grouped() {
|
||||||
if to_kill_processes.1.len() != 1 {
|
if to_kill_processes.1.len() != 1 {
|
||||||
Text::raw(format!(
|
Text::raw(format!(
|
||||||
"\nAre you sure you want to kill {} processes with the name {}?",
|
"\nKill {} processes with the name {}?",
|
||||||
to_kill_processes.1.len(), to_kill_processes.0
|
to_kill_processes.1.len(),
|
||||||
|
to_kill_processes.0
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Text::raw(format!(
|
Text::raw(format!(
|
||||||
"\nAre you sure you want to kill {} process with the name {}?",
|
"\nKill {} process with the name {}?",
|
||||||
to_kill_processes.1.len(), to_kill_processes.0
|
to_kill_processes.1.len(),
|
||||||
|
to_kill_processes.0
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Text::raw(format!(
|
Text::raw(format!(
|
||||||
"\nAre you sure you want to kill process {} with PID {}?",
|
"\nKill process {} with PID {}?",
|
||||||
to_kill_processes.0, first_pid
|
to_kill_processes.0, first_pid
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
Text::raw("\nNote that if bottom is frozen, it must be unfrozen for changes to be shown.\n\n\n"),
|
Text::raw("\n\n"),
|
||||||
if app_state.delete_dialog_state.is_on_yes {
|
if app_state.delete_dialog_state.is_on_yes {
|
||||||
Text::styled("Yes", self.colours.currently_selected_text_style)
|
Text::styled("Yes", self.colours.currently_selected_text_style)
|
||||||
} else {
|
} else {
|
||||||
@ -339,7 +362,8 @@ impl Painter {
|
|||||||
let repeat_num = max(
|
let repeat_num = max(
|
||||||
0,
|
0,
|
||||||
middle_dialog_chunk[1].width as i32
|
middle_dialog_chunk[1].width as i32
|
||||||
- DD_BASE.chars().count() as i32 - 2,
|
- DD_BASE.chars().count() as i32
|
||||||
|
- 2,
|
||||||
);
|
);
|
||||||
let dd_title = format!(
|
let dd_title = format!(
|
||||||
" Confirm Kill Process ─{}─ Esc to close ",
|
" Confirm Kill Process ─{}─ Esc to close ",
|
||||||
@ -424,39 +448,49 @@ impl Painter {
|
|||||||
// the same info.
|
// the same info.
|
||||||
|
|
||||||
let cpu_height = (app_state.canvas_data.cpu_data.len() / 4) as u16
|
let cpu_height = (app_state.canvas_data.cpu_data.len() / 4) as u16
|
||||||
+ (
|
+ (if app_state.canvas_data.cpu_data.len() % 4 == 0 {
|
||||||
if app_state.canvas_data.cpu_data.len() % 4 == 0 {
|
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
}
|
});
|
||||||
);
|
|
||||||
let vertical_chunks = Layout::default()
|
let vertical_chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints([
|
.constraints(
|
||||||
|
[
|
||||||
Constraint::Length(cpu_height),
|
Constraint::Length(cpu_height),
|
||||||
Constraint::Length(1),
|
Constraint::Length(1),
|
||||||
Constraint::Length(2),
|
Constraint::Length(2),
|
||||||
Constraint::Length(2),
|
Constraint::Length(2),
|
||||||
Constraint::Min(5),
|
Constraint::Min(5),
|
||||||
].as_ref())
|
]
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
.split(f.size());
|
.split(f.size());
|
||||||
|
|
||||||
let middle_chunks = Layout::default()
|
let middle_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
Constraint::Percentage(50),
|
|
||||||
Constraint::Percentage(50),
|
|
||||||
].as_ref())
|
|
||||||
.split(vertical_chunks[2]);
|
.split(vertical_chunks[2]);
|
||||||
self.draw_basic_cpu(&mut f, app_state, vertical_chunks[0]);
|
self.draw_basic_cpu(&mut f, app_state, vertical_chunks[0]);
|
||||||
self.draw_basic_memory(&mut f, app_state, middle_chunks[0]);
|
self.draw_basic_memory(&mut f, app_state, middle_chunks[0]);
|
||||||
self.draw_basic_network(&mut f, app_state, middle_chunks[1]);
|
self.draw_basic_network(&mut f, app_state, middle_chunks[1]);
|
||||||
self.draw_basic_table_arrows(&mut f, app_state, vertical_chunks[3]);
|
self.draw_basic_table_arrows(&mut f, app_state, vertical_chunks[3]);
|
||||||
if app_state.current_widget_selected.is_widget_table() {
|
if app_state.current_widget_selected.is_widget_table() {
|
||||||
self.draw_specific_table(&mut f, app_state, vertical_chunks[4], false, app_state.current_widget_selected);
|
self.draw_specific_table(
|
||||||
|
&mut f,
|
||||||
|
app_state,
|
||||||
|
vertical_chunks[4],
|
||||||
|
false,
|
||||||
|
app_state.current_widget_selected,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.draw_specific_table(&mut f, app_state, vertical_chunks[4], false, app_state.previous_basic_table_selected);
|
self.draw_specific_table(
|
||||||
|
&mut f,
|
||||||
|
app_state,
|
||||||
|
vertical_chunks[4],
|
||||||
|
false,
|
||||||
|
app_state.previous_basic_table_selected,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases
|
// TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases
|
||||||
@ -1247,15 +1281,39 @@ impl Painter {
|
|||||||
fn draw_search_field<B: Backend>(
|
fn draw_search_field<B: Backend>(
|
||||||
&self, f: &mut Frame<'_, B>, app_state: &mut app::App, draw_loc: Rect, draw_border: bool,
|
&self, f: &mut Frame<'_, B>, app_state: &mut app::App, draw_loc: Rect, draw_border: bool,
|
||||||
) {
|
) {
|
||||||
let width = max(0, draw_loc.width as i64 - 34) as u64; // TODO: [REFACTOR] Hard coding this is terrible.
|
let pid_search_text = "Search by PID (Tab for Name): ";
|
||||||
|
let name_search_text = "Search by Name (Tab for PID): ";
|
||||||
|
let grouped_search_text = "Search by Name: ";
|
||||||
|
let num_columns = draw_loc.width as usize;
|
||||||
|
|
||||||
|
let chosen_text = if app_state.is_grouped() {
|
||||||
|
grouped_search_text
|
||||||
|
} else if app_state.process_search_state.is_searching_with_pid {
|
||||||
|
pid_search_text
|
||||||
|
} else {
|
||||||
|
name_search_text
|
||||||
|
};
|
||||||
|
|
||||||
|
let search_title: &str = if chosen_text.len() == min(num_columns / 2, chosen_text.len()) {
|
||||||
|
chosen_text
|
||||||
|
} else if chosen_text.is_empty() {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
"> "
|
||||||
|
};
|
||||||
|
|
||||||
|
let num_chars_for_text = search_title.len();
|
||||||
|
|
||||||
|
let mut search_text = vec![Text::styled(search_title, self.colours.table_header_style)];
|
||||||
|
|
||||||
let cursor_position = app_state.get_cursor_position();
|
let cursor_position = app_state.get_cursor_position();
|
||||||
let char_cursor_position = app_state.get_char_cursor_position();
|
let current_cursor_position = app_state.get_char_cursor_position();
|
||||||
|
|
||||||
let start_position: usize = get_search_start_position(
|
let start_position: usize = get_search_start_position(
|
||||||
width as usize,
|
num_columns - num_chars_for_text - 5,
|
||||||
&app_state.process_search_state.search_state.cursor_direction,
|
&app_state.process_search_state.search_state.cursor_direction,
|
||||||
&mut app_state.process_search_state.search_state.cursor_bar,
|
&mut app_state.process_search_state.search_state.cursor_bar,
|
||||||
char_cursor_position,
|
current_cursor_position,
|
||||||
app_state.is_resized,
|
app_state.is_resized,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1305,20 +1363,6 @@ impl Painter {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut search_text = vec![if app_state.is_grouped() {
|
|
||||||
Text::styled("Search by Name: ", self.colours.table_header_style)
|
|
||||||
} else if app_state.process_search_state.is_searching_with_pid {
|
|
||||||
Text::styled(
|
|
||||||
"Search by PID (Tab for Name): ",
|
|
||||||
self.colours.table_header_style,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Text::styled(
|
|
||||||
"Search by Name (Tab for PID): ",
|
|
||||||
self.colours.table_header_style,
|
|
||||||
)
|
|
||||||
}];
|
|
||||||
|
|
||||||
// Text options shamelessly stolen from VS Code.
|
// Text options shamelessly stolen from VS Code.
|
||||||
let mut option_text = vec![];
|
let mut option_text = vec![];
|
||||||
let case_style = if !app_state.process_search_state.is_ignoring_case {
|
let case_style = if !app_state.process_search_state.is_ignoring_case {
|
||||||
@ -1658,7 +1702,8 @@ impl Painter {
|
|||||||
let margin_space = 2;
|
let margin_space = 2;
|
||||||
let remaining_width = max(
|
let remaining_width = max(
|
||||||
0,
|
0,
|
||||||
draw_loc.width as i64 - ((9 + margin_space) * REQUIRED_COLUMNS) as i64,
|
draw_loc.width as i64
|
||||||
|
- ((9 + margin_space) * REQUIRED_COLUMNS - margin_space) as i64,
|
||||||
) as usize;
|
) as usize;
|
||||||
|
|
||||||
let bar_length = remaining_width / REQUIRED_COLUMNS;
|
let bar_length = remaining_width / REQUIRED_COLUMNS;
|
||||||
|
@ -70,7 +70,6 @@ pub fn get_variable_intrinsic_widths(
|
|||||||
(resulting_widths, last_index)
|
(resulting_widths, last_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code, unused_variables)]
|
|
||||||
pub fn get_search_start_position(
|
pub fn get_search_start_position(
|
||||||
num_columns: usize, cursor_direction: &app::CursorDirection, cursor_bar: &mut usize,
|
num_columns: usize, cursor_direction: &app::CursorDirection, cursor_bar: &mut usize,
|
||||||
current_cursor_position: usize, is_resized: bool,
|
current_cursor_position: usize, is_resized: bool,
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
pub const STALE_MAX_MILLISECONDS: u128 = 60 * 1000;
|
|
||||||
// How long to store data.
|
// How long to store data.
|
||||||
|
pub const STALE_MAX_MILLISECONDS: u128 = 60 * 1000;
|
||||||
pub const TIME_STARTS_FROM: u64 = 60 * 1000;
|
pub const TIME_STARTS_FROM: u64 = 60 * 1000;
|
||||||
pub const TICK_RATE_IN_MILLISECONDS: u64 = 200;
|
pub const TICK_RATE_IN_MILLISECONDS: u64 = 200;
|
||||||
// How fast the screen refreshes
|
// How fast the screen refreshes
|
||||||
pub const DEFAULT_REFRESH_RATE_IN_MILLISECONDS: u128 = 1000;
|
pub const DEFAULT_REFRESH_RATE_IN_MILLISECONDS: u128 = 1000;
|
||||||
pub const MAX_KEY_TIMEOUT_IN_MILLISECONDS: u128 = 1000;
|
pub const MAX_KEY_TIMEOUT_IN_MILLISECONDS: u128 = 1000;
|
||||||
|
// Number of colours to generate for the CPU chart/table
|
||||||
pub const NUM_COLOURS: i32 = 256;
|
pub const NUM_COLOURS: i32 = 256;
|
||||||
|
|
||||||
// Config and flags
|
|
||||||
pub const DEFAULT_UNIX_CONFIG_FILE_PATH: &str = ".config/bottom/bottom.toml";
|
|
||||||
pub const DEFAULT_WINDOWS_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";
|
|
||||||
|
|
||||||
// Help text
|
// Help text
|
||||||
pub const GENERAL_HELP_TEXT: [&str; 15] = [
|
pub const GENERAL_HELP_TEXT: [&str; 15] = [
|
||||||
"General Keybindings\n\n",
|
"General Keybindings\n\n",
|
||||||
@ -18,9 +15,9 @@ pub const GENERAL_HELP_TEXT: [&str; 15] = [
|
|||||||
"Esc Close filters, dialog boxes, etc.\n",
|
"Esc Close filters, dialog boxes, etc.\n",
|
||||||
"Ctrl-r Reset all data\n",
|
"Ctrl-r Reset all data\n",
|
||||||
"f Freeze display\n",
|
"f Freeze display\n",
|
||||||
"Ctrl-Arrow Move currently selected widget\n",
|
"Ctrl-Arrow Change your selected widget\n",
|
||||||
"Shift-Arrow Move currently selected widget\n",
|
"Shift-Arrow Change your selected widget\n",
|
||||||
"H/J/K/L Move currently selected widget up/down/left/right\n",
|
"H/J/K/L Change your selected widget up/down/left/right\n",
|
||||||
"Up, k Move cursor up\n",
|
"Up, k Move cursor up\n",
|
||||||
"Down, j Move cursor down\n",
|
"Down, j Move cursor down\n",
|
||||||
"? Open the help screen\n",
|
"? Open the help screen\n",
|
||||||
@ -57,6 +54,11 @@ pub const SEARCH_HELP_TEXT: [&str; 13] = [
|
|||||||
"Alt-r/F3 Toggle whether to use regex\n",
|
"Alt-r/F3 Toggle whether to use regex\n",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Config and flags
|
||||||
|
pub const DEFAULT_UNIX_CONFIG_FILE_PATH: &str = ".config/bottom/bottom.toml";
|
||||||
|
pub const DEFAULT_WINDOWS_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";
|
||||||
|
|
||||||
|
// Default config file
|
||||||
pub const DEFAULT_CONFIG_CONTENT: &str = r##"
|
pub const DEFAULT_CONFIG_CONTENT: &str = r##"
|
||||||
# This is a default config file for bottom. All of the settings are commented
|
# This is a default config file for bottom. All of the settings are commented
|
||||||
# out by default; if you wish to change them uncomment and modify as you see
|
# out by default; if you wish to change them uncomment and modify as you see
|
||||||
|
Loading…
x
Reference in New Issue
Block a user