use crate::{
io::{DataSource, reader::FwfToDataFrame},
tui::{
pickers::text_picker::TextPicker,
popups::{
importers::{
dismiss_overlay_and_load_data_frame,
import_source_picker::{ImportSource, ImportSourcePicker},
},
multi_step_overlay::OverlayStep,
path_picker::PathPicker,
url_picker::UrlPicker,
yes_no_picker::YesNoPicker,
},
widgets::input::InputType,
},
};
#[derive(Debug)]
pub enum State {
PickSource {
picker: ImportSourcePicker,
},
PickPath {
picker: PathPicker,
},
PickUrl {
picker: UrlPicker,
},
PickWidths {
source: DataSource,
picker: TextPicker,
},
PickHeader {
widths: Vec<usize>,
source: DataSource,
picker: YesNoPicker,
},
PickSeparatorLength {
has_header: bool,
widths: Vec<usize>,
source: DataSource,
picker: TextPicker,
},
PickFlexibleWidth {
separator_length: usize,
has_header: bool,
widths: Vec<usize>,
source: DataSource,
picker: YesNoPicker,
},
}
impl OverlayStep for State {
fn next(self) -> Self {
match self {
State::PickSource { picker } => match picker.value() {
Some(ImportSource::File) => State::PickPath {
picker: PathPicker::default(),
},
Some(ImportSource::Stdin) => State::PickWidths {
source: DataSource::Stdin,
picker: TextPicker::default()
.with_input_type(InputType::MultiNumeric)
.with_title("Widths")
.with_hint("4 8 12 or leave empty to auto detect"),
},
Some(ImportSource::Url) => State::PickUrl {
picker: UrlPicker::default(),
},
None => State::PickSource { picker },
},
State::PickPath { picker } => State::PickWidths {
source: DataSource::File(picker.path()),
picker: TextPicker::default()
.with_input_type(InputType::MultiNumeric)
.with_title("Widths")
.with_hint("4 8 12 or leave empty to auto detect"),
},
State::PickUrl { picker } => State::PickWidths {
source: DataSource::Url(picker.url()),
picker: TextPicker::default()
.with_input_type(InputType::MultiNumeric)
.with_title("Widths")
.with_hint("4 8 12 or leave empty to auto detect"),
},
State::PickWidths { source, picker } => {
let widths = picker
.value()
.split(' ')
.map(|s| s.parse())
.collect::<Result<_, _>>()
.unwrap_or_default();
State::PickHeader {
widths,
source,
picker: YesNoPicker::default().with_title("Has Header"),
}
}
State::PickHeader {
widths,
source,
picker,
} => match picker.value() {
Some(has_header) => State::PickSeparatorLength {
has_header,
widths,
source,
picker: TextPicker::default()
.with_input_type(InputType::Numeric)
.with_title("Separator Legnth"),
},
None => State::PickHeader {
widths,
source,
picker,
},
},
State::PickSeparatorLength {
has_header,
widths,
source,
picker,
} => {
let separator_length = picker.value().parse().unwrap_or(0);
State::PickFlexibleWidth {
separator_length,
has_header,
widths,
source,
picker: YesNoPicker::default().with_title("Flexible Width"),
}
}
State::PickFlexibleWidth {
separator_length,
has_header,
widths,
source,
picker,
} => {
let flexible_width = picker.value().unwrap_or(true);
let rtdf = FwfToDataFrame::default()
.with_flexible_width(flexible_width)
.with_has_header(has_header)
.with_separator_length(separator_length)
.with_widths(widths);
dismiss_overlay_and_load_data_frame(source, rtdf);
Default::default()
}
}
}
fn responder(&mut self) -> &mut dyn crate::tui::component::Component {
match self {
State::PickSource { picker } => picker,
State::PickPath { picker } => picker,
State::PickWidths { source: _, picker } => picker,
State::PickHeader {
widths: _,
source: _,
picker,
} => picker,
State::PickSeparatorLength {
has_header: _,
widths: _,
source: _,
picker,
} => picker,
State::PickFlexibleWidth {
separator_length: _,
has_header: _,
widths: _,
source: _,
picker,
} => picker,
State::PickUrl { picker } => picker,
}
}
}
impl Default for State {
fn default() -> Self {
Self::PickSource {
picker: Default::default(),
}
}
}