diff --git a/src/compare/compare.rs b/src/compare/compare.rs index 02242675..9168155d 100644 --- a/src/compare/compare.rs +++ b/src/compare/compare.rs @@ -8,6 +8,7 @@ use crate::compare::parse::get_org_mode_version; use crate::compare::sexp::sexp; use crate::context::GlobalSettings; use crate::context::LocalFileAccessInterface; +use crate::parser::parse_file_with_settings; use crate::parser::parse_with_settings; pub fn run_anonymous_compare>( @@ -70,7 +71,7 @@ pub fn run_compare_on_file_with_settings>( global_settings.file_access = &file_access_interface; global_settings }; - let rust_parsed = parse_with_settings(org_contents, &global_settings)?; + let rust_parsed = parse_file_with_settings(org_contents, &global_settings, Some(org_path))?; let org_sexp = emacs_parse_file_org_document(org_path, &global_settings)?; let (_remaining, parsed_sexp) = sexp(org_sexp.as_str()).map_err(|e| e.to_string())?; diff --git a/src/compare/parse.rs b/src/compare/parse.rs index cfa3e176..3b6e0a3b 100644 --- a/src/compare/parse.rs +++ b/src/compare/parse.rs @@ -76,11 +76,17 @@ where r#"(progn (require 'org) (defun org-table-align () t) + (setq vc-handled-backends nil) {global_settings} + (find-file-read-only "{file_path}") (org-mode) (message "%s" (pp-to-string (org-element-parse-buffer))) )"#, - global_settings = global_settings_elisp(global_settings) + global_settings = global_settings_elisp(global_settings), + file_path = file_path + .as_os_str() + .to_str() + .expect("File name should be valid utf-8.") ); let mut cmd = Command::new("emacs"); let cmd = cmd @@ -89,8 +95,6 @@ where .arg("--no-site-file") .arg("--no-splash") .arg("--batch") - .arg("--insert") - .arg(file_path.as_os_str()) .arg("--eval") .arg(elisp_script); let out = cmd.output()?; diff --git a/src/lib.rs b/src/lib.rs index b8a8d108..da35ff75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(exit_status_error)] #![feature(trait_alias)] +#![feature(path_file_prefix)] // TODO: #![warn(missing_docs)] #[cfg(feature = "compare")] diff --git a/src/parser/document.rs b/src/parser/document.rs index 31878d5e..a9442388 100644 --- a/src/parser/document.rs +++ b/src/parser/document.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use nom::combinator::all_consuming; use nom::combinator::opt; use nom::multi::many0; @@ -25,30 +27,71 @@ use crate::types::Object; /// Parse a full org-mode document. /// -/// This is the main entry point for Organic. It will parse the full contents of the input string as an org-mode document. +/// This is a main entry point for Organic. It will parse the full contents of the input string as an org-mode document without an underlying file attached. #[allow(dead_code)] pub fn parse<'s>(input: &'s str) -> Result, Box> { - parse_with_settings(input, &GlobalSettings::default()) + parse_file_with_settings::<&Path>(input, &GlobalSettings::default(), None) +} + +/// Parse a full org-mode document. +/// +/// This is a main entry point for Organic. It will parse the full contents of the input string as an org-mode document at the file_path. +/// +/// file_path is not used for reading the file contents. It is only used for determining the document category and filling in the path attribute on the Document. +#[allow(dead_code)] +pub fn parse_file<'s, P: AsRef>( + input: &'s str, + file_path: Option

, +) -> Result, Box> { + parse_file_with_settings(input, &GlobalSettings::default(), file_path) } /// Parse a full org-mode document with starting settings. /// -/// This is the secondary entry point for Organic. It will parse the full contents of the input string as an org-mode document starting with the settings you supplied. +/// This is a secondary entry point for Organic. It will parse the full contents of the input string as an org-mode document starting with the settings you supplied without an underlying file attached. /// /// This will not prevent additional settings from being learned during parsing, for example when encountering a "#+TODO". #[allow(dead_code)] pub fn parse_with_settings<'g, 's>( input: &'s str, global_settings: &'g GlobalSettings<'g, 's>, +) -> Result, Box> { + parse_file_with_settings::<&Path>(input, global_settings, None) +} + +/// Parse a full org-mode document with starting settings. +/// +/// This is the secondary entry point for Organic. It will parse the full contents of the input string as an org-mode document at the file_path starting with the settings you supplied. +/// +/// This will not prevent additional settings from being learned during parsing, for example when encountering a "#+TODO". +/// +/// file_path is not used for reading the file contents. It is only used for determining the document category and filling in the path attribute on the Document. +#[allow(dead_code)] +pub fn parse_file_with_settings<'g, 's, P: AsRef>( + input: &'s str, + global_settings: &'g GlobalSettings<'g, 's>, + file_path: Option

, ) -> Result, Box> { let initial_context = ContextElement::document_context(); let initial_context = Context::new(global_settings, List::new(&initial_context)); let wrapped_input = OrgSource::new(input); - let ret = + let mut doc = all_consuming(parser_with_context!(document_org_source)(&initial_context))(wrapped_input) .map_err(|err| err.to_string()) - .map(|(_remaining, parsed_document)| parsed_document); - Ok(ret?) + .map(|(_remaining, parsed_document)| parsed_document)?; + if let Some(file_path) = file_path { + let full_path = file_path.as_ref().canonicalize()?; + if doc.category.is_none() { + let category = full_path + .file_prefix() + .expect("File should have a name.") + .to_str() + .expect("File name should be valid utf-8."); + doc.category = Some(category.to_owned()); + } + doc.path = Some(full_path); + } + Ok(doc) } /// Parse a full org-mode document. diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8729294e..b3e27101 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -45,5 +45,7 @@ mod text_markup; mod timestamp; mod util; pub use document::parse; +pub use document::parse_file; +pub use document::parse_file_with_settings; pub use document::parse_with_settings; pub(crate) use org_source::OrgSource;