use crossterm::style::Color;
use yuru_core::Candidate;
const DEFAULT_SELECTED_ROW_BG: Color = Color::Rgb {
r: 52,
g: 58,
b: 70,
};
#[derive(Clone, Debug)]
pub struct TuiOptions {
pub initial_query: String,
pub prompt: String,
pub header: Option<String>,
pub footer: Option<String>,
pub expect_keys: Vec<String>,
pub bindings: Vec<KeyBinding>,
pub height: Option<usize>,
pub layout: TuiLayout,
pub preview: Option<PreviewCommand>,
pub preview_shell: Option<String>,
pub preview_image_protocol: Option<ImagePreviewProtocol>,
pub style: TuiStyle,
pub highlight_line: bool,
pub cycle: bool,
pub multi: bool,
pub multi_limit: Option<usize>,
pub no_input: bool,
pub pointer: String,
pub marker: String,
pub ellipsis: String,
}
impl Default for TuiOptions {
fn default() -> Self {
Self {
initial_query: String::new(),
prompt: "> ".to_string(),
header: None,
footer: None,
expect_keys: Vec::new(),
bindings: Vec::new(),
height: None,
layout: TuiLayout::default(),
preview: None,
preview_shell: None,
preview_image_protocol: None,
style: TuiStyle::default(),
highlight_line: true,
cycle: false,
multi: false,
multi_limit: None,
no_input: false,
pointer: ">".to_string(),
marker: "*".to_string(),
ellipsis: "..".to_string(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PreviewCommand {
Shell(String),
Builtin {
text_extensions: Vec<String>,
},
}
impl PreviewCommand {
pub(crate) fn cache_key(&self) -> String {
match self {
Self::Shell(command) => format!("shell:{command}"),
Self::Builtin { text_extensions } => {
format!("builtin:{}", text_extensions.join(","))
}
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ImagePreviewProtocol {
Halfblocks,
Sixel,
Kitty,
Iterm2,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum TuiLayout {
#[default]
Default,
Reverse,
ReverseList,
}
impl TuiLayout {
pub(crate) fn prompt_at_bottom(self) -> bool {
matches!(self, Self::Default | Self::ReverseList)
}
pub(crate) fn list_bottom_up(self) -> bool {
matches!(self, Self::Default)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TuiRgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl From<TuiRgb> for Color {
fn from(color: TuiRgb) -> Self {
Self::Rgb {
r: color.r,
g: color.g,
b: color.b,
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct TuiStyle {
pub pointer: Option<TuiRgb>,
pub highlight: Option<TuiRgb>,
pub highlight_selected: Option<TuiRgb>,
pub selected_fg: Option<TuiRgb>,
pub selected_bg: Option<TuiRgb>,
}
impl TuiStyle {
pub(crate) fn pointer_color(&self) -> Option<Color> {
self.pointer.map(Color::from)
}
pub(crate) fn highlight_color(&self, selected: bool) -> Color {
if selected {
self.highlight_selected
.or(self.highlight)
.map(Color::from)
.unwrap_or(Color::Yellow)
} else {
self.highlight.map(Color::from).unwrap_or(Color::Yellow)
}
}
pub(crate) fn selected_bg_color(&self) -> Color {
self.selected_bg
.map(Color::from)
.unwrap_or(DEFAULT_SELECTED_ROW_BG)
}
pub(crate) fn selected_fg_color(&self) -> Option<Color> {
self.selected_fg.map(Color::from)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyBinding {
pub key: String,
pub action: BindingAction,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BindingAction {
Accept,
Abort,
ClearQuery,
MoveSelectionUp,
MoveSelectionDown,
MoveSelectionFirst,
MoveSelectionLast,
PageUp,
PageDown,
ToggleMark,
ToggleMarkAndDown,
ToggleMarkAndUp,
MoveCursorStart,
MoveCursorEnd,
MoveCursorLeft,
MoveCursorRight,
Backspace,
Delete,
PreviewUp,
PreviewDown,
PreviewPageUp,
PreviewPageDown,
PreviewTop,
PreviewBottom,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum TuiOutcome {
Accepted {
ids: Vec<usize>,
query: String,
expect: Option<String>,
},
NoSelection,
Aborted,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CandidateStreamMessage {
Candidate(Candidate),
Finished,
Error(String),
}