use crate::config::ARGS;
use crate::config::CFG;
use crate::config::CLIPBOARD;
use crate::config::LAUNCH_EDITOR;
use crate::config::LAUNCH_VIEWER;
#[cfg(feature = "read-clipboard")]
use crate::config::RUNS_ON_CONSOLE;
use crate::config::STDIN;
use crate::error::NoteError;
use crate::error::WorkflowError;
use crate::file_editor::launch_editor;
use crate::filename;
use crate::filename::MarkupLanguage;
use crate::note::Note;
use crate::note::TMPL_VAR_FM_;
use crate::note::TMPL_VAR_FM_NO_FILENAME_SYNC;
#[cfg(feature = "viewer")]
use crate::viewer::launch_viewer_thread;
use crate::AUTHOR;
use crate::VERSION;
#[cfg(feature = "read-clipboard")]
use clipboard::ClipboardContext;
#[cfg(feature = "read-clipboard")]
use clipboard::ClipboardProvider;
use std::env;
use std::fs;
#[cfg(not(target_family = "windows"))]
use std::matches;
use std::path::Path;
use std::path::PathBuf;
use std::process;
use tera::Value;
fn synchronize_filename(path: &Path) -> Result<PathBuf, WorkflowError> {
let mut n = match Note::from_existing_note(&path) {
Ok(n) => n,
Err(e) if matches!(e, NoteError::MissingFrontMatter { .. }) => {
return Err(WorkflowError::MissingFrontMatter { source: e })
}
Err(e) if matches!(e, NoteError::MissingFrontMatterField { .. }) => {
return Err(WorkflowError::MissingFrontMatterField { source: e })
}
Err(e) => return Err(e.into()),
};
let no_filename_sync = match n.context.get(TMPL_VAR_FM_NO_FILENAME_SYNC) {
None => false,
Some(Value::Bool(nsync)) => *nsync,
Some(_) => true,
};
if no_filename_sync {
log::trace!(
"Filename synchronisation disabled with the front matter field: `{}: {}`",
TMPL_VAR_FM_NO_FILENAME_SYNC.trim_start_matches(TMPL_VAR_FM_),
no_filename_sync
);
}
if ARGS.no_filename_sync {
log::trace!("Filename synchronisation disabled with the flag: `--no-filename-sync`",);
}
if CFG.no_filename_sync_arg_default {
log::trace!(
"Filename synchronisation disabled with the configuration file \
variable: `no_filename_sync_arg_default = true`",
);
}
let new_file_path =
if !no_filename_sync && !CFG.no_filename_sync_arg_default && !ARGS.no_filename_sync {
log::trace!("Applying template `tmpl_sync_filename`.");
let new_file_path = n.render_filename(&CFG.tmpl_sync_filename).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_sync_filename".to_string(),
source: e,
}
})?;
if !filename::exclude_copy_counter_eq(&path, &new_file_path) {
let new_file_path = filename::find_unused(new_file_path)?;
fs::rename(&path, &new_file_path)?;
log::trace!("File renamed to {:?}", new_file_path);
new_file_path
} else {
path.to_path_buf()
}
} else {
path.to_path_buf()
};
if let Some(dir) = &ARGS.export {
n.render_and_write_content(&new_file_path, &CFG.exporter_rendition_tmpl, &dir)
.map_err(|e| WorkflowError::Template {
tmpl_name: "exporter_rendition_tmpl".to_string(),
source: e,
})?;
}
Ok(new_file_path)
}
#[inline]
fn create_new_note_or_synchronize_filename(path: &Path) -> Result<PathBuf, WorkflowError> {
if path.is_dir() {
let (n, new_file_path) = if STDIN.is_empty() && CLIPBOARD.is_empty() {
log::trace!("Applying templates `tmpl_new_content` and `tmpl_new_filename`.");
let n = Note::from_content_template(&path, &CFG.tmpl_new_content).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_new_content".to_string(),
source: e,
}
})?;
let new_file_path =
n.render_filename(&CFG.tmpl_new_filename)
.map_err(|e| WorkflowError::Template {
tmpl_name: "tmpl_new_filename".to_string(),
source: e,
})?;
(n, new_file_path)
} else if !STDIN.borrow_dependent().header.is_empty()
|| !CLIPBOARD.borrow_dependent().header.is_empty()
{
log::trace!("Applying templates: `tmpl_copy_content`, `tmpl_copy_filename`");
let n = Note::from_content_template(&path, &CFG.tmpl_copy_content).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_copy_content".to_string(),
source: e,
}
})?;
let new_file_path = n.render_filename(&CFG.tmpl_copy_filename).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_copy_filename".to_string(),
source: e,
}
})?;
(n, new_file_path)
} else {
log::trace!("Applying templates: `tmpl_clipboard_content`, `tmpl_clipboard_filename`");
let n =
Note::from_content_template(&path, &CFG.tmpl_clipboard_content).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_clipboard_content".to_string(),
source: e,
}
})?;
let new_file_path = n
.render_filename(&CFG.tmpl_clipboard_filename)
.map_err(|e| WorkflowError::Template {
tmpl_name: "tmpl_clipboard_filename".to_string(),
source: e,
})?;
(n, new_file_path)
};
let new_file_path = filename::find_unused(new_file_path)?;
n.content.write_to_disk(&new_file_path)?;
Ok(new_file_path)
} else {
let extension_is_known = !matches!(
MarkupLanguage::from(
None,
path.extension()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
),
MarkupLanguage::None
);
if extension_is_known {
Ok(synchronize_filename(path)?)
} else {
log::trace!("Applying templates `tmpl_annotate_content` and `tmpl_annotate_filename`.");
let n =
Note::from_content_template(&path, &CFG.tmpl_annotate_content).map_err(|e| {
WorkflowError::Template {
tmpl_name: "tmpl_annotate_content".to_string(),
source: e,
}
})?;
let new_file_path = n
.render_filename(&CFG.tmpl_annotate_filename)
.map_err(|e| WorkflowError::Template {
tmpl_name: "tmpl_annotate_filename".to_string(),
source: e,
})?;
let new_file_path = filename::find_unused(new_file_path)?;
n.content.write_to_disk(&new_file_path)?;
Ok(new_file_path)
}
}
}
#[inline]
pub fn run() -> Result<PathBuf, WorkflowError> {
if ARGS.version {
print!("Version {}, {}, ", VERSION.unwrap_or("unknown"), AUTHOR);
print!("compiled-in features: [");
#[cfg(feature = "message-box")]
print!("message-box, ");
#[cfg(feature = "viewer")]
print!("viewer, ");
#[cfg(feature = "renderer")]
print!("renderer, ");
#[cfg(feature = "clipboard")]
print!("clipboard, ");
println!("]");
process::exit(0);
};
let mut path = if let Some(p) = &ARGS.path {
p.canonicalize()?
} else {
env::current_dir()?
};
if ARGS.export.is_some() && !path.is_file() {
return Err(WorkflowError::ExportsNeedsNoteFile);
};
let mut missing_header;
match create_new_note_or_synchronize_filename(&path) {
Ok(p) => {
path = p;
#[cfg(feature = "viewer")]
{
missing_header = false;
}
}
Err(e) => {
if path.is_file() && !matches!(e, WorkflowError::Template { .. }) && !ARGS.batch {
missing_header = matches!(e, WorkflowError::MissingFrontMatter { .. })
|| matches!(e, WorkflowError::MissingFrontMatterField { .. });
if *LAUNCH_VIEWER || (missing_header && CFG.silently_ignore_missing_header) {
log::warn!(
"{}\n\
\n\
Please correct the front matter if this is supposed \
to be a Tp-Note file. Ignore otherwise.",
e,
);
} else {
log::error!(
"{}\n\
\n\
Please correct the error.",
e,
);
};
} else {
return Err(e);
}
}
};
#[cfg(feature = "viewer")]
let viewer_join_handle = if *LAUNCH_VIEWER
&& !(missing_header && CFG.viewer_missing_header_disables && !ARGS.view)
{
Some(launch_viewer_thread(&path))
} else {
None
};
if *LAUNCH_EDITOR {
launch_editor(&path)?;
};
if *LAUNCH_EDITOR {
match synchronize_filename(&path) {
Ok(p) => path = p,
Err(e) => {
missing_header = matches!(e, WorkflowError::MissingFrontMatter { .. })
|| matches!(e, WorkflowError::MissingFrontMatterField { .. });
if missing_header && CFG.silently_ignore_missing_header {
log::warn!(
"{}\n\
\n\
Please correct the front matter if this is supposed \
to be a Tp-Note file. Ignore otherwise.",
e,
);
} else {
return Err(e);
}
}
};
#[cfg(feature = "read-clipboard")]
if CFG.clipboard_read_enabled && CFG.clipboard_empty_enabled && !*RUNS_ON_CONSOLE {
let ctx: Option<ClipboardContext> = ClipboardProvider::new().ok();
if let Some(mut ctx) = ctx {
ctx.set_contents("".to_owned()).unwrap_or_default();
};
}
} else {
#[cfg(feature = "viewer")]
if let Some(jh) = viewer_join_handle {
let _ = jh.join();
};
};
Ok(path)
}