mirror of
https://github.com/atuinsh/atuin.git
synced 2024-11-22 08:13:57 +01:00
feat: show preview auto (#1804)
* feat: show preview auto * refactor: preview_auto
This commit is contained in:
parent
2fba4aae93
commit
176eae02f7
@ -73,6 +73,11 @@
|
||||
## useful when the command is longer than the terminal width and is cut off
|
||||
# show_preview = false
|
||||
|
||||
## enable or disable automatic preview. It shows a preview, if the command is
|
||||
## longer than the width of the terminal. It respects max_preview_height.
|
||||
## (default: true)
|
||||
# show_preview_auto = true
|
||||
|
||||
## what to do when the escape key is pressed when searching
|
||||
## possible values: return-original, return-query
|
||||
# exit_mode = "return-original"
|
||||
|
@ -358,6 +358,7 @@ pub struct Settings {
|
||||
pub inline_height: u16,
|
||||
pub invert: bool,
|
||||
pub show_preview: bool,
|
||||
pub show_preview_auto: bool,
|
||||
pub max_preview_height: u16,
|
||||
pub show_help: bool,
|
||||
pub show_tabs: bool,
|
||||
@ -615,6 +616,7 @@ impl Settings {
|
||||
.set_default("style", "auto")?
|
||||
.set_default("inline_height", 0)?
|
||||
.set_default("show_preview", false)?
|
||||
.set_default("show_preview_auto", true)?
|
||||
.set_default("max_preview_height", 4)?
|
||||
.set_default("show_help", true)?
|
||||
.set_default("show_tabs", true)?
|
||||
|
@ -533,6 +533,52 @@ impl State {
|
||||
self.results_state.select(i.min(self.results_len - 1));
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[allow(clippy::bool_to_int_with_if)]
|
||||
fn calc_preview_height(
|
||||
settings: &Settings,
|
||||
results: &[History],
|
||||
selected: usize,
|
||||
tab_index: usize,
|
||||
compact: bool,
|
||||
border_size: u16,
|
||||
preview_width: u16,
|
||||
) -> u16 {
|
||||
if settings.show_preview_auto && tab_index == 0 && !results.is_empty() {
|
||||
let length_current_cmd = results[selected].command.len() as u16;
|
||||
// The '- 19' takes the characters before the command (duration and time) into account
|
||||
if length_current_cmd > preview_width - 19 {
|
||||
std::cmp::min(
|
||||
settings.max_preview_height,
|
||||
(length_current_cmd + preview_width - 1 - border_size)
|
||||
/ (preview_width - border_size),
|
||||
) + border_size * 2
|
||||
} else {
|
||||
1
|
||||
}
|
||||
} else if settings.show_preview && !settings.show_preview_auto && tab_index == 0 {
|
||||
let longest_command = results
|
||||
.iter()
|
||||
.max_by(|h1, h2| h1.command.len().cmp(&h2.command.len()));
|
||||
longest_command.map_or(0, |v| {
|
||||
std::cmp::min(
|
||||
settings.max_preview_height,
|
||||
v.command
|
||||
.split('\n')
|
||||
.map(|line| {
|
||||
(line.len() as u16 + preview_width - 1 - border_size)
|
||||
/ (preview_width - border_size)
|
||||
})
|
||||
.sum(),
|
||||
)
|
||||
}) + border_size * 2
|
||||
} else if compact || tab_index == 1 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[allow(clippy::bool_to_int_with_if)]
|
||||
#[allow(clippy::too_many_lines)]
|
||||
@ -551,27 +597,15 @@ impl State {
|
||||
let invert = settings.invert;
|
||||
let border_size = if compact { 0 } else { 1 };
|
||||
let preview_width = f.size().width - 2;
|
||||
let preview_height = if settings.show_preview && self.tab_index == 0 {
|
||||
let longest_command = results
|
||||
.iter()
|
||||
.max_by(|h1, h2| h1.command.len().cmp(&h2.command.len()));
|
||||
longest_command.map_or(0, |v| {
|
||||
std::cmp::min(
|
||||
settings.max_preview_height,
|
||||
v.command
|
||||
.split('\n')
|
||||
.map(|line| {
|
||||
(line.len() as u16 + preview_width - 1 - border_size)
|
||||
/ (preview_width - border_size)
|
||||
})
|
||||
.sum(),
|
||||
)
|
||||
}) + border_size * 2
|
||||
} else if compact || self.tab_index == 1 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let preview_height = Self::calc_preview_height(
|
||||
settings,
|
||||
results,
|
||||
self.results_state.selected(),
|
||||
self.tab_index,
|
||||
compact,
|
||||
border_size,
|
||||
preview_width,
|
||||
);
|
||||
let show_help = settings.show_help && (!compact || f.size().height > 1);
|
||||
let show_tabs = settings.show_tabs;
|
||||
let chunks = Layout::default()
|
||||
@ -1141,3 +1175,135 @@ fn set_clipboard(s: String) {
|
||||
any(target_os = "windows", target_os = "macos", target_os = "linux")
|
||||
)))]
|
||||
fn set_clipboard(_s: String) {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use atuin_client::history::History;
|
||||
use atuin_client::settings::Settings;
|
||||
|
||||
use super::State;
|
||||
|
||||
#[test]
|
||||
fn calc_preview_height_test() {
|
||||
let settings_preview_auto = Settings {
|
||||
show_preview_auto: true,
|
||||
..Settings::utc()
|
||||
};
|
||||
|
||||
let settings_preview_auto_h2 = Settings {
|
||||
show_preview_auto: true,
|
||||
max_preview_height: 2,
|
||||
..Settings::utc()
|
||||
};
|
||||
|
||||
let settings_preview_h4 = Settings {
|
||||
show_preview_auto: false,
|
||||
show_preview: true,
|
||||
max_preview_height: 4,
|
||||
..Settings::utc()
|
||||
};
|
||||
|
||||
let cmd_60: History = History::capture()
|
||||
.timestamp(time::OffsetDateTime::now_utc())
|
||||
.command("for i in $(seq -w 10); do echo \"item number $i - abcd\"; done")
|
||||
.cwd("/")
|
||||
.build()
|
||||
.into();
|
||||
|
||||
let cmd_124: History = History::capture()
|
||||
.timestamp(time::OffsetDateTime::now_utc())
|
||||
.command("echo 'Aurea prima sata est aetas, quae vindice nullo, sponte sua, sine lege fidem rectumque colebat. Poena metusque aberant'")
|
||||
.cwd("/")
|
||||
.build()
|
||||
.into();
|
||||
|
||||
let cmd_200: History = History::capture()
|
||||
.timestamp(time::OffsetDateTime::now_utc())
|
||||
.command("CREATE USER atuin WITH ENCRYPTED PASSWORD 'supersecretpassword'; CREATE DATABASE atuin WITH OWNER = atuin; \\c atuin; REVOKE ALL PRIVILEGES ON SCHEMA public FROM PUBLIC; echo 'All done. 200 characters'")
|
||||
.cwd("/")
|
||||
.build()
|
||||
.into();
|
||||
|
||||
let results: Vec<History> = vec![cmd_60, cmd_124, cmd_200];
|
||||
|
||||
// the selected command does not require a preview
|
||||
let no_preview = State::calc_preview_height(
|
||||
&settings_preview_auto,
|
||||
&results,
|
||||
0 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
80,
|
||||
);
|
||||
// the selected command requires 2 lines
|
||||
let preview_h2 = State::calc_preview_height(
|
||||
&settings_preview_auto,
|
||||
&results,
|
||||
1 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
80,
|
||||
);
|
||||
// the selected command requires 3 lines
|
||||
let preview_h3 = State::calc_preview_height(
|
||||
&settings_preview_auto,
|
||||
&results,
|
||||
2 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
80,
|
||||
);
|
||||
// the selected command requires a preview of 1 line (happens when the command is between preview_width-19 and preview_width)
|
||||
let preview_one_line = State::calc_preview_height(
|
||||
&settings_preview_auto,
|
||||
&results,
|
||||
0 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
66,
|
||||
);
|
||||
// the selected command requires 3 lines, but we have a max preview height limit of 2
|
||||
let preview_limit_at_2 = State::calc_preview_height(
|
||||
&settings_preview_auto_h2,
|
||||
&results,
|
||||
2 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
80,
|
||||
);
|
||||
// the longest command requires 3 lines
|
||||
let preview_static_h3 = State::calc_preview_height(
|
||||
&settings_preview_h4,
|
||||
&results,
|
||||
1 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
80,
|
||||
);
|
||||
// the longest command requires 10 lines, but we have a max preview height limit of 4
|
||||
let preview_static_limit_at_4 = State::calc_preview_height(
|
||||
&settings_preview_h4,
|
||||
&results,
|
||||
1 as usize,
|
||||
0 as usize,
|
||||
false,
|
||||
1,
|
||||
20,
|
||||
);
|
||||
|
||||
assert_eq!(no_preview, 1);
|
||||
// 1*2 is the space for the border
|
||||
assert_eq!(preview_h2, 2 + 1 * 2);
|
||||
assert_eq!(preview_h3, 3 + 1 * 2);
|
||||
assert_eq!(preview_one_line, 1 + 1 * 2);
|
||||
assert_eq!(preview_limit_at_2, 2 + 1 * 2);
|
||||
assert_eq!(preview_static_h3, 3 + 1 * 2);
|
||||
assert_eq!(preview_static_limit_at_4, 4 + 1 * 2);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user