diff options
| author | ottjk <joshott16@gmail.com> | 2024-01-20 01:56:41 -0500 |
|---|---|---|
| committer | ottjk <joshott16@gmail.com> | 2024-01-20 01:56:41 -0500 |
| commit | eb99d622a8190e105e490185690b540c5ef1c97f (patch) | |
| tree | 17f4040f570bd2e2aef855a79c01bda38d25c96b /src | |
| download | xoppdog-master.tar.gz xoppdog-master.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands/mod.rs | 122 | ||||
| -rw-r--r-- | src/commands/sit.rs | 73 | ||||
| -rw-r--r-- | src/main.rs | 74 |
3 files changed, 269 insertions, 0 deletions
diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..3aee90f --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,122 @@ +use std::{ + path::PathBuf, + process::{Command, Stdio}, + collections::HashMap, + io::Write, + fs, +}; +use indoc::formatdoc; + +mod sit; +pub use sit::start_sit; + +fn open_xournal(path: &PathBuf) { + let _ = Command::new("xournalpp") + .arg(path.as_os_str()) + .arg("--name=xoppdoggin") + .arg("--disable-audio") + .stderr(Stdio::null()) + .spawn() + .expect("Unable to launch xournal!"); +} + +fn latex_template(name: &String, path: &PathBuf) -> String { + formatdoc! {r" + \begin{{figure}}[ht] + \centering + \incfig{{{}}} + \caption{{{name}}} + \label{{fig:{name}}} + \end{{figure}} + ", + path.with_extension("").file_name().unwrap().to_string_lossy() + } +} + +pub fn shake_figure(name: String, root: PathBuf) { + let template_path = dirs::config_dir() + .expect("Could not resolve config directory.") + .join("xoppdog/template.xopp"); + + if !template_path.try_exists().unwrap() { + panic!("Please make a template at {}!", template_path.to_str().unwrap()); + } + + if !root.try_exists().unwrap() { + fs::create_dir_all(&root).unwrap(); + } + + let filename = name.trim().replace(" ", "-"); + let target = root.join(filename).with_extension("xopp"); + + fs::copy(template_path, &target).expect("Could not copy template to target file."); + + open_xournal(&target); + print!("{}", latex_template(&name, &target)); +} + +pub fn fetch_figure(root: PathBuf) { + let figures = find_figures(&root); + let figure_path = pick_figure(&figures); + + open_xournal(&figure_path); +} + +fn find_figures(root: &PathBuf) -> HashMap<String, PathBuf> { + if !root.is_dir() { + panic!("Root path not a directory!"); + } + + let directory = fs::read_dir(root) + .expect("Can't sniff out the given figures directory."); + + let mut figures = HashMap::new(); + + for entry in directory { + match entry { + Ok(entry) => { + if entry.path().extension().unwrap() == "xopp" { + let name = entry.path() + .with_extension("") + .file_name() + .unwrap().to_string_lossy() + .replace("-", " ").replace("_", " "); + figures.insert(name, entry.path()); + } + }, + Err(error) => { + eprintln!("Error reading file in figures directory: {:?}", error); + continue; + }, + } + } + + return figures; +} + +fn pick_figure<'a>(figures: &'a HashMap<String, PathBuf>) -> &'a PathBuf{ + let mut options = String::new(); + for key in figures.keys() { + options.push_str(key); + options.push_str("\n"); + } + + let mut rofi = Command::new("rofi") + .arg("-dmenu") + .args(["-p", "Figures"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn().expect("Rofi failed to launch."); + + rofi.stdin.as_mut().unwrap().write(options.trim().as_bytes()) + .expect("Could not send input to Rofi process."); + + let rofi_output = rofi.wait_with_output() + .expect("Waiting on Rofi failed."); + let choice = String::from_utf8(rofi_output.stdout) + .expect("Couldn't make sense of Rofi output."); + let choice_path = figures.get(choice.trim()) + .expect("Somehow Rofi output didn't match with a figure."); + + return choice_path; +} diff --git a/src/commands/sit.rs b/src/commands/sit.rs new file mode 100644 index 0000000..84f2f9e --- /dev/null +++ b/src/commands/sit.rs @@ -0,0 +1,73 @@ +use notify::{ + Watcher, + RecursiveMode, + event::{Event, EventKind, ModifyKind}, +}; +use std::{ + path::PathBuf, + io::{self, Error}, + process::Command, + fs +}; + +pub fn start_sit(root: PathBuf) { + let mut watcher = notify::recommended_watcher(|res| { + match res { + Ok(event) => handle_event(event), + Err(e) => println!("watch error: {:?}", e), + } + }).unwrap(); + + if !root.try_exists().unwrap() { + fs::create_dir_all(&root).unwrap(); + } + + watcher.watch(&root, RecursiveMode::NonRecursive).unwrap(); + + let mut input = String::new(); + io::stdin() + .read_line(&mut input) + .expect("Failed to read user input."); +} + +fn handle_event(event: Event) { + let _event_result = match event.kind { + EventKind::Modify(ModifyKind::Data(_)) => compile(event), + EventKind::Create(_) => compile(event), + _ => Ok(()), + }; +} + +fn compile(event: Event) -> io::Result<()> { + let path = &event.paths[0]; + if path.extension().unwrap() == "xopp" { + let pdf_path = path.with_extension("pdf"); + let pdf_path_str = pdf_path.to_str().unwrap(); + + let xournal_status = Command::new("xournalpp") + .arg(path.as_os_str()) + .args(["-p", pdf_path_str]) + .arg("--export-no-background") + .arg("--export-no-ruling") + .status()?; + + match xournal_status.success() { + true => println!("exported to {}", pdf_path_str), + false => return Err(Error::other("couldn't export xopp to pdf.")), + } + + let inkscape_status = Command::new("inkscape") + .arg(pdf_path_str) + .arg("--export-type=pdf") + .arg("--export-latex") + .arg(format!("--export-filename={}", pdf_path_str)) + .status()?; + + match inkscape_status.success() { + true => println!("created pdf_tex from {}", pdf_path_str), + false => return Err(Error::other("couldn't export pdf to pdf_tex.")), + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..665822e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,74 @@ +use std::path::PathBuf; +use clap::{Parser, Subcommand, Args}; + +mod commands; +use commands::{ + start_sit, + shake_figure, + fetch_figure, +}; + +#[derive(Parser)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Start watching for file modifications and update tex files + Sit(SitArgs), + + /// Modify a tracked xopp + Fetch(FetchArgs), + + /// Create a tracked xopp + Shake(ShakeArgs), +} + +#[derive(Args)] +struct SitArgs { + /// Figure directory + root: PathBuf, +} + +#[derive(Args)] +struct FetchArgs { + /// Figure directory + root: PathBuf, +} + +#[derive(Args)] +struct ShakeArgs { + /// Name of figure + name: String, + + /// Figure directory + root: PathBuf, +} + +fn sit_command(args: SitArgs) { + let root = args.root; + start_sit(root); +} + +fn fetch_command(args: FetchArgs) { + let root = args.root; + fetch_figure(root); +} + +fn shake_command(args: ShakeArgs) { + let name = args.name; + let root = args.root; + shake_figure(name, root); +} + +fn main() { + let cli = Cli::parse(); + + match cli.command { + Commands::Sit(args) => sit_command(args), + Commands::Shake(args) => shake_command(args), + Commands::Fetch(args) => fetch_command(args), + }; +} |