use std::path::Path;
use crate::{config::Config, utils::home_dir};
use requestty::{prompt::Backend, question::Completions, Answers};
use rust_search::SearchBuilder;
use super::{full_path, replace_tilde_with_home_dir, to_post_path, PostProperties};
#[logfn_inputs(Info)]
pub fn is_new_post(config: &'static Config) -> impl Fn(&Answers) -> bool {
move |answers| {
answers.get("action").unwrap().as_list_item().unwrap().text
== config.select_action.new_post_choice
}
}
#[logfn_inputs(Info)]
pub fn autocomplete_files<'a>(
dir: Option<&'a str>,
ext: Option<&'a str>,
file_name: bool,
) -> impl FnMut(String, &Answers) -> Completions<String> + 'a {
move |prefix, _| {
let prefix = replace_tilde_with_home_dir(&prefix);
let search_location = dir.map(Into::into).unwrap_or_else(home_dir);
let mut files = SearchBuilder::default()
.location(search_location)
.ignore_case();
if let Some(ext) = ext {
files = files.ext(ext);
}
let files: Vec<_> = files.build().collect();
let files = files.as_slice();
if files.is_empty() {
Completions::from([prefix])
} else if file_name && ext.is_some() {
let ext = format!(".{}", ext.unwrap());
Completions::from(
files
.iter()
.map(|f| f.strip_suffix(&ext).unwrap_or(f).to_owned())
.map(|f| {
Path::new(&f)
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_owned()
})
.collect::<Vec<_>>(),
)
} else {
Completions::from(files)
}
}
}
#[logfn_inputs(Info)]
pub fn is_modify_post(config: &'static Config) -> impl Fn(&Answers) -> bool {
move |answers| {
answers.get("action").unwrap().as_list_item().unwrap().text
== config.select_action.update_existing_post
}
}
#[logfn_inputs(Info)]
pub fn is_show_all_action(config: &'static Config) -> impl Fn(&Answers) -> bool {
move |answers| {
answers.get("modify_action").map_or_else(
|| false,
|action| {
action
.as_list_items()
.unwrap()
.iter()
.all(|item| item.text == config.modify_post_settings.show_all_question)
},
)
}
}
pub fn full_path_transform() -> impl FnMut(&str, &Answers, &mut dyn Backend) -> std::io::Result<()>
{
move |str_path, _, backend| {
write!(
backend,
"{}",
full_path(&replace_tilde_with_home_dir(str_path))
)
}
}
pub fn tags_transform(
config: &'static Config,
) -> impl FnMut(&str, &Answers, &mut dyn Backend) -> std::io::Result<()> {
move |str_tags, _, backend| {
write!(
backend,
"{}",
super::tags_updater(str_tags, config.create_post_settings.separated_tags_by)
.join(&config.create_post_settings.separated_tags_by.to_string())
)
}
}
pub fn get_str_length(str_text: &str) -> usize {
str_text.trim().chars().count()
}
pub fn get_modifing_post(config: &'static Config, answers: &Answers) -> Option<String> {
is_modify_post(config)(answers).then(|| {
let slug = answers.get("post_file").unwrap().as_string().unwrap();
to_post_path(config, slug)
})
}
pub fn default_value_transform(
config: &'static Config,
propertie: PostProperties,
) -> impl FnMut(&str, &Answers, &mut dyn Backend) -> Option<std::io::Result<()>> {
move |value, answers, backend| {
(value == config.modify_post_settings.keep_old_value_message
&& is_show_all_action(config)(answers))
.then(|| {
write!(
backend,
"{}",
propertie
.from_file(
&get_modifing_post(config, answers)
.expect("Verified that action is show_all")
)
.unwrap_or_else(|_| panic!("Cannot get default value of `{propertie:?}`"))
)
})
}
}
pub fn join_str_validators<'a>(
mut left: impl FnMut(&str, &Answers) -> Result<(), String> + 'a,
mut right: impl FnMut(&str, &Answers) -> Result<(), String> + 'a,
) -> impl FnMut(&str, &Answers) -> Result<(), String> + 'a {
move |str_value: &str, answers: &Answers| {
left(str_value, answers).and_then(|_| right(str_value, answers))
}
}
pub fn join_on_key_validator<'a>(
mut left: impl FnMut(&str, &Answers) -> bool + 'a,
mut right: impl FnMut(&str, &Answers) -> bool + 'a,
) -> impl FnMut(&str, &Answers) -> bool + 'a {
move |str_value, answers| left(str_value, answers) && right(str_value, answers)
}
pub fn join_transform(
mut left: impl FnMut(&str, &Answers, &mut dyn Backend) -> Option<std::io::Result<()>>,
mut right: impl FnMut(&str, &Answers, &mut dyn Backend) -> std::io::Result<()>,
) -> impl FnMut(&str, &Answers, &mut dyn Backend) -> std::io::Result<()> {
move |text, answers, backend| {
left(text, answers, backend).unwrap_or_else(|| right(text, answers, backend))
}
}