From ced4b9e5ff28016f500c5bfea91a3b33297f65d1 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 3 Apr 2021 11:04:40 +0300 Subject: feat: allow setting name of directory where new entries go Also, some refactoring that happened along the way. --- jt.md | 1 + src/bin/jt2.rs | 41 +++++++++++++++++++++++------------------ src/config.rs | 29 ++++++++++++++++++++++------- src/journal.rs | 39 ++++++++++++++++++++++++++------------- src/opt.rs | 4 ++++ subplot/jt.py | 6 ++++++ subplot/jt.yaml | 3 +++ 7 files changed, 85 insertions(+), 38 deletions(-) diff --git a/jt.md b/jt.md index ad40b35..9ee4d1d 100644 --- a/jt.md +++ b/jt.md @@ -164,6 +164,7 @@ and draft 0 in jrnl contains "Open sesame!" when I run jt2 --dirname=jrnl finish 0 abra then command is successful and there is one journal entry in jrnl, at FILE +and file name ends with .mdwn and journal entry contains "Abracadabra" and journal entry contains "Open sesame!" and there are no drafts in jrnl diff --git a/src/bin/jt2.rs b/src/bin/jt2.rs index 3d85229..25a3a13 100644 --- a/src/bin/jt2.rs +++ b/src/bin/jt2.rs @@ -15,42 +15,47 @@ fn main() -> anyhow::Result<()> { SubCommand::Init { journalname, description, - } => init(&config.dirname, &journalname, &description)?, - SubCommand::IsJournal => is_journal(&config.dirname)?, - SubCommand::New { title } => new_draft(&title, &config.dirname, &config.editor)?, - SubCommand::Edit { draft } => edit_draft(&config.dirname, &config.editor, &draft)?, - SubCommand::Finish { draft, basename } => finish_draft(&config.dirname, &draft, &basename)?, + } => init(&config.dirname, &journalname, &description, &config)?, + SubCommand::IsJournal => is_journal(&config)?, + SubCommand::New { title } => new_draft(&title, &config)?, + SubCommand::Edit { draft } => edit_draft(&draft, &config)?, + SubCommand::Finish { draft, basename } => finish_draft(&draft, &basename, &config)?, } Ok(()) } -fn init(dirname: &Path, _journalname: &str, _description: &str) -> anyhow::Result<()> { - Journal::init(dirname)?; +fn init( + dirname: &Path, + _journalname: &str, + _description: &str, + config: &Configuration, +) -> anyhow::Result<()> { + Journal::init(dirname, &config.entries)?; Ok(()) } -fn is_journal(dirname: &Path) -> anyhow::Result<()> { - if !Journal::is_journal(dirname) { - return Err(JournalError::NotAJournal(dirname.display().to_string()).into()); +fn is_journal(config: &Configuration) -> anyhow::Result<()> { + if !Journal::is_journal(&config.dirname, &config.entries) { + return Err(JournalError::NotAJournal(config.dirname.display().to_string()).into()); } Ok(()) } -fn new_draft(title: &str, dirname: &Path, editor: &str) -> anyhow::Result<()> { - let journal = Journal::new(dirname)?; - journal.new_draft(title, editor)?; +fn new_draft(title: &str, config: &Configuration) -> anyhow::Result<()> { + let journal = Journal::new(&config.dirname, &config.entries)?; + journal.new_draft(title, &config.editor)?; Ok(()) } -fn edit_draft(dirname: &Path, editor: &str, draft: &str) -> anyhow::Result<()> { - let journal = Journal::new(dirname)?; +fn edit_draft(draft: &str, config: &Configuration) -> anyhow::Result<()> { + let journal = Journal::new(&config.dirname, &config.entries)?; let filename = journal.pick_draft(draft)?; - journal.edit_draft(editor, &filename)?; + journal.edit_draft(&config.editor, &filename)?; Ok(()) } -fn finish_draft(dirname: &Path, draft: &str, basename: &str) -> anyhow::Result<()> { - let journal = Journal::new(dirname)?; +fn finish_draft(draft: &str, basename: &str, config: &Configuration) -> anyhow::Result<()> { + let journal = Journal::new(&config.dirname, &config.entries)?; let filename = journal.pick_draft(draft)?; journal.finish_draft(&filename, basename)?; Ok(()) diff --git a/src/config.rs b/src/config.rs index 3acfd90..e40c35f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ const APP: &str = "jt2"; struct InputConfiguration { dirname: Option, editor: Option, + entries: Option, } impl InputConfiguration { @@ -43,6 +44,11 @@ pub struct Configuration { /// The editor to open for editing journal entry drafts. pub editor: String, + + /// The directory where new entries are put. + /// + /// This is the full path name, not relative to `dirname`. + pub entries: PathBuf, } impl Configuration { @@ -74,14 +80,16 @@ impl Configuration { InputConfiguration::default() }; + let dirname = if let Some(path) = &opt.global.dirname { + path.to_path_buf() + } else if let Some(path) = &input.dirname { + expand_tilde(path) + } else { + proj_dirs.data_dir().to_path_buf() + }; + Ok(Self { - dirname: if let Some(path) = &opt.global.dirname { - path.to_path_buf() - } else if let Some(path) = &input.dirname { - expand_tilde(path) - } else { - proj_dirs.data_dir().to_path_buf() - }, + dirname: dirname.clone(), editor: if let Some(name) = &opt.global.editor { name.to_string() } else if let Some(name) = &input.editor { @@ -89,6 +97,13 @@ impl Configuration { } else { "/usr/bin/editor".to_string() }, + entries: if let Some(entries) = &opt.global.entries { + dirname.join(entries) + } else if let Some(entries) = &input.entries { + dirname.join(entries) + } else { + dirname.join("entries") + }, }) } diff --git a/src/journal.rs b/src/journal.rs index 2adb48d..c3bb1eb 100644 --- a/src/journal.rs +++ b/src/journal.rs @@ -7,31 +7,32 @@ const MAX_DRAFT_COUNT: usize = 1000; pub struct Journal { dirname: PathBuf, + entries: PathBuf, } impl Journal { - pub fn is_journal(path: &Path) -> bool { - if let Ok(meta) = std::fs::symlink_metadata(path) { - meta.is_dir() - } else { - false - } + pub fn is_journal(path: &Path, entries: &Path) -> bool { + is_dir(path) && is_dir(entries) } - pub fn init(path: &Path) -> Result { + pub fn init(path: &Path, entries: &Path) -> Result { std::fs::create_dir(path) .map_err(|err| JournalError::CreateDirectory(path.to_path_buf(), err))?; + std::fs::create_dir(entries) + .map_err(|err| JournalError::CreateDirectory(entries.to_path_buf(), err))?; Ok(Self { dirname: path.to_path_buf(), + entries: entries.to_path_buf(), }) } - pub fn new(path: &Path) -> Result { - let dirname = path.to_path_buf(); - if dirname.exists() { - Ok(Self { dirname }) + pub fn new(path: &Path, entries: &Path) -> Result { + if Self::is_journal(path, entries) { + let dirname = path.to_path_buf(); + let entries = entries.to_path_buf(); + Ok(Self { dirname, entries }) } else { - Err(JournalError::NotAJournal(dirname.display().to_string())) + Err(JournalError::NotAJournal(path.display().to_string())) } } @@ -44,7 +45,7 @@ impl Journal { } fn entries(&self) -> PathBuf { - self.dirname().join("entries") + self.entries.clone() } pub fn new_draft(&self, title: &str, editor: &str) -> anyhow::Result<()> { @@ -85,6 +86,9 @@ impl Journal { } fn edit(&self, editor: &str, filename: &Path) -> Result<(), JournalError> { + if editor == "none" { + return Ok(()); + } match Command::new(editor).arg(filename).output() { Err(err) => Err(JournalError::SpawnEditor(filename.to_path_buf(), err)), Ok(output) => { @@ -115,8 +119,17 @@ impl Journal { let subdir = entries.join(Local::today().format("%Y/%m/%d").to_string()); std::fs::create_dir_all(&subdir)?; + let basename = PathBuf::from(format!("{}.mdwn", basename)); let entry = subdir.join(basename); std::fs::rename(filename, entry)?; Ok(()) } } + +fn is_dir(path: &Path) -> bool { + if let Ok(meta) = std::fs::symlink_metadata(path) { + meta.is_dir() + } else { + false + } +} diff --git a/src/opt.rs b/src/opt.rs index df83659..5455777 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -29,6 +29,10 @@ pub struct GlobalOptions { #[structopt(short, long, help = "Directory where journal should be stored")] pub dirname: Option, + /// Sub-directory in journal where new entries are put. + #[structopt(long)] + pub entries: Option, + /// Which editor to invoke for editing journal entry drafts. #[structopt( long, diff --git a/subplot/jt.py b/subplot/jt.py index 312a22a..6ce75b0 100644 --- a/subplot/jt.py +++ b/subplot/jt.py @@ -153,3 +153,9 @@ def file_contains(ctx, variable=None, pattern=None): data = f.read() logging.debug(f"file content: {data!r}") assert pattern in data + + +def file_name_has_suffix(ctx, varname=None, suffix=None): + variables = ctx.get("variables", {}) + filename = variables[varname] + assert filename.endswith(suffix) diff --git a/subplot/jt.yaml b/subplot/jt.yaml index 187f436..65bf90e 100644 --- a/subplot/jt.yaml +++ b/subplot/jt.yaml @@ -54,3 +54,6 @@ - then: journal entry <{variable}> contains "{pattern:text}" function: file_contains + +- then: file name <{varname}> ends with {suffix} + function: file_name_has_suffix -- cgit v1.2.1