extern crate anyhow;
extern crate lazy_static;
extern crate log;
use cursive::align::HAlign;
use cursive::theme::*;
use cursive::traits::*;
use cursive::view::Resizable;
use cursive::views::*;
use cursive::Cursive;
use std::fs;
use std::io::Write;
use crate::wiki::search::SearchResult;
pub mod cli;
pub mod config;
pub mod error;
pub mod logging;
pub mod ui;
pub mod wiki;
pub const LOGO: &str = "
_ __ (_) / /__ (_) / /_ __ __ (_)
| | /| / / / / / //_/ / / ______ / __/ / / / / / /
| |/ |/ / / / / ,< / / /_____// /_ / /_/ / / /
|__/|__/ /_/ /_/|_| /_/ \\__/ \\__,_/ /_/
";
fn main() {
error::create_hook(|path, data| {
if let Some(path) = path {
let mut fs = fs::File::create(path).unwrap();
fs.write_all(data.as_bytes())
.expect("Unable to generate report");
};
});
initialize();
start_application();
}
fn initialize() {
println!("{}", LOGO);
logging::Logger::new().initialize();
}
fn start_application() {
let mut siv = cursive::default();
siv.add_global_callback('q', Cursive::quit);
let theme = Theme {
palette: get_color_palette(),
..Default::default()
};
siv.set_theme(theme);
let search_bar = EditView::new()
.on_submit(|s, q| ui::search::on_search(s, q.to_string()))
.style({
if let Some(search_theme) = &config::CONFIG.theme.search_bar {
if search_theme.background == search_theme.secondary {
ColorStyle::new(search_theme.background, search_theme.text)
} else {
ColorStyle::secondary()
}
} else {
ColorStyle::secondary()
}
})
.with_name("search_bar")
.full_width();
let search_layout = view_with_theme!(
config::CONFIG.theme.search_bar,
Dialog::around(LinearLayout::horizontal().child(search_bar))
.title("Search")
.title_position(cursive::align::HAlign::Left)
);
let logo_view = TextView::new(LOGO)
.h_align(HAlign::Center)
.with_name("logo_view")
.full_screen();
let article_layout = LinearLayout::horizontal()
.child(Dialog::around(logo_view))
.with_name("article_layout");
siv.add_fullscreen_layer(
Dialog::around(
LinearLayout::vertical()
.child(search_layout)
.child(article_layout),
)
.title("wiki-tui")
.button("Quit", Cursive::quit)
.full_screen(),
);
let argument_callback = handle_arguments();
if let Err(error) = siv.cb_sink().send(argument_callback) {
log::error!("{:?}", error);
}
let siv_box = std::sync::Mutex::new(siv);
if std::panic::catch_unwind(|| siv_box.lock().unwrap().run()).is_err() {
error::print_panic();
}
}
fn handle_arguments() -> Box<dyn FnOnce(&mut Cursive) + Send> {
if let Some(search_query) = config::CONFIG.get_args().search_query.as_ref() {
log::info!("searching for the article: {}", search_query);
return Box::new(move |siv: &mut Cursive| {
ui::search::on_search(siv, search_query.to_string());
});
} else if let Some(article_id) = config::CONFIG.get_args().article_id {
log::info!("opening the article: {}", article_id);
return Box::new(move |siv: &mut Cursive| {
ui::article::on_article_submit(
siv,
&SearchResult::new(
String::new(),
0,
article_id,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
),
);
});
}
Box::new(|_: &mut Cursive| {})
}
fn get_color_palette() -> Palette {
let mut custom_palette = Palette::default();
custom_palette.set_color("View", config::CONFIG.theme.background);
custom_palette.set_color("Primary", config::CONFIG.theme.text);
custom_palette.set_color("TitlePrimary", config::CONFIG.theme.title);
custom_palette.set_color("Highlight", config::CONFIG.theme.highlight);
custom_palette.set_color("HighlightInactive", config::CONFIG.theme.highlight_inactive);
custom_palette.set_color("HighlightText", config::CONFIG.theme.highlight_text);
custom_palette
}