1use crate::envelope;
11use crate::error::{Error, Result};
12use crate::google::docs::DocumentRef;
13use crate::orgfile;
14use crate::sexp::Sexp;
15
16#[derive(Debug, Clone)]
18pub struct OpenOutcome {
19 pub document_id: String,
21 pub url: String,
24}
25
26pub fn open(content: &str) -> Result<OpenOutcome> {
32 let document_id = orgfile::read_keyword(content, "GDOC_ID").ok_or(Error::NotLinked)?;
33 let url = orgfile::read_keyword(content, "GDOC_URL")
34 .unwrap_or_else(|| DocumentRef::from_id(document_id.clone()).url);
35 Ok(OpenOutcome { document_id, url })
36}
37
38#[must_use]
40pub fn envelope(outcome: &OpenOutcome) -> Sexp {
41 envelope::ok(
42 "open",
43 vec![
44 ("document-id", Sexp::string(outcome.document_id.clone())),
45 ("url", Sexp::string(outcome.url.clone())),
46 ],
47 )
48}
49
50#[cfg(test)]
51mod tests {
52 use super::open;
53 use crate::error::Error;
54
55 #[test]
56 fn open_prefers_the_stored_url() {
57 let content =
58 "#+GDOC_ID: DOC1\n#+GDOC_URL: https://docs.google.com/document/d/DOC1/edit\n* Intro\n";
59 let outcome = open(content).expect("open succeeds");
60 assert_eq!(outcome.document_id, "DOC1");
61 assert_eq!(outcome.url, "https://docs.google.com/document/d/DOC1/edit");
62 }
63
64 #[test]
65 fn open_derives_url_when_only_id_is_present() {
66 let content = "#+GDOC_ID: ABC123\n* Intro\nbody\n";
67 let outcome = open(content).expect("open succeeds");
68 assert_eq!(
69 outcome.url,
70 "https://docs.google.com/document/d/ABC123/edit"
71 );
72 }
73
74 #[test]
75 fn open_without_a_linked_doc_is_not_linked_error() {
76 let content = "* Intro\nNo link here.\n";
77 assert!(matches!(open(content), Err(Error::NotLinked)));
78 }
79}