extern crate clap;
use clap::{Arg, App, SubCommand};
extern crate rusty_x;
use rusty_x::{start_operation, edit_snippet, Error, OpCode, Project, ProjectOperation};
use std::path;
use std::io::BufRead;
use std::env;
extern crate syntect;
use syntect::parsing::SyntaxSet;
use syntect::easy::HighlightFile;
use syntect::highlighting::{ThemeSet, Style};
use syntect::util::as_24_bit_terminal_escaped;
extern crate skim;
use skim::{Skim, SkimOptions};
use std::default::Default;
use std::io::Cursor;
fn display_snippet(full_path: &path::Path) {
let ss = SyntaxSet::load_defaults_newlines();
let ts = ThemeSet::load_defaults();
let theme = ts.themes.get("base16-eighties.dark");
let mut highlighter = HighlightFile::new(full_path, &ss, theme.unwrap()).unwrap();
let mut line = String::new();
while highlighter.reader.read_line(&mut line).unwrap() > 0 {
{
let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line);
print!("{}", as_24_bit_terminal_escaped(®ions[..], true));
}
line.clear();
}
println!("\x1b[0m");
}
fn show_multiple_results(selections: &Vec<String>) -> Vec<usize> {
let options: SkimOptions = SkimOptions::default().height("50%").multi(true);
let joined = selections.iter().fold(String::new(), |acc, s| acc + s + "\n");
let selected_items = Skim::run_with(&options, Some(Box::new(Cursor::new(joined))))
.map(|out| out.selected_items)
.unwrap_or_else(|| Vec::new());
selected_items.iter().map(|item| item.get_index()).collect()
}
fn main() -> Result<(), Error> {
let matches = App::new("Rusty X")
.version("0.1")
.author("Tim de Jager <tdejager89@gmail.com>")
.about("Rusty snippet manager")
.arg(Arg::with_name("KEYWORDS")
.help("Keywords to search for")
.required(true)
.multiple(true))
.subcommand(SubCommand::with_name("add")
.about("Add a snippet")
.arg(Arg::with_name("filename")
.help("Snippet file name")
.required(true)))
.subcommand(SubCommand::with_name("edit"))
.about("Edit a snippet")
.get_matches();
let add = matches.subcommand_matches("add");
let edit = matches.subcommand_matches("edit");
let (op_code, filename) = if let Some(matches) = add {
(OpCode::AddSnippet, matches.value_of("filename").unwrap())
} else if let Some(matches) = edit {
(OpCode::ListSnippets(true), "")
} else {
(OpCode::ListSnippets(false), "")
};
let project_operation = Project::default_project()?;
let project = match project_operation {
ProjectOperation::NotExist(project) =>
{
let home = String::from(env::home_dir()
.expect("Cannot find the home dir")
.to_str().unwrap());
project.write(home.as_ref())?;
project
}
ProjectOperation::Exist(project) => { project }
};
for location in &project.locations {
location.create_if_not_exists()?;
}
let keywords: Vec<String> = matches.values_of("KEYWORDS").unwrap().map(|s| s.to_string()).collect();
let res = start_operation(&op_code, &project, keywords, filename);
match res {
Err(err) =>
{
Err(err)
}
Ok(snippets) =>
{
let intermediate : Vec<String> = snippets.iter().map(|s| s.tags.iter().fold(String::new(), |s, val| { (s + "|" + val).to_owned()})).collect();
if intermediate.len() > 1 {
let to_show = show_multiple_results(&intermediate);
for i in to_show {
let snip = &snippets[i];
let full_path = path::Path::new(&snip.name);
if let OpCode::ListSnippets(true) = op_code
{
edit_snippet("vim", full_path);
} else {
display_snippet(&full_path);
}
}
} else if intermediate.len() == 1 {
let snip = &snippets[0];
let full_path = path::Path::new(&snip.name);
display_snippet(&full_path);
}
Ok(())
}
}
}