diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-07-15 17:34:08 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-07-15 17:34:08 +0300 |
commit | 80bd48f44c1ba6c5010f7d50fd9387b1c4424464 (patch) | |
tree | 94381a10bea6990ca5d017bb9067749f17ce614c /src | |
parent | 0f3eeccc4403ddf27ad4e7cdffb8033dcab5f9cf (diff) | |
download | jt2-80bd48f44c1ba6c5010f7d50fd9387b1c4424464.tar.gz |
feat: add command to list current drafts
Sponsored-by: author
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/jt2.rs | 1 | ||||
-rw-r--r-- | src/cmd.rs | 11 | ||||
-rw-r--r-- | src/error.rs | 8 | ||||
-rw-r--r-- | src/journal.rs | 30 | ||||
-rw-r--r-- | src/opt.rs | 3 |
5 files changed, 53 insertions, 0 deletions
diff --git a/src/bin/jt2.rs b/src/bin/jt2.rs index c37b799..1574f2e 100644 --- a/src/bin/jt2.rs +++ b/src/bin/jt2.rs @@ -20,6 +20,7 @@ fn do_work() -> anyhow::Result<()> { SubCommand::IsJournal(x) => x.run(&config)?, SubCommand::New(x) => x.run(&config)?, SubCommand::NewTopic(x) => x.run(&config)?, + SubCommand::List(x) => x.run(&config)?, SubCommand::Edit(x) => x.run(&config)?, SubCommand::Finish(x) => x.run(&config)?, } @@ -62,6 +62,17 @@ impl New { } #[derive(Debug, StructOpt)] +pub struct List {} + +impl List { + pub fn run(&self, config: &Configuration) -> Result<(), JournalError> { + let journal = Journal::new(&config.dirname, &config.entries)?; + journal.list_drafts()?; + Ok(()) + } +} + +#[derive(Debug, StructOpt)] pub struct NewTopic { #[structopt(help = "Path to topic page in journal")] path: PathBuf, diff --git a/src/error.rs b/src/error.rs index 8db0991..36d8f07 100644 --- a/src/error.rs +++ b/src/error.rs @@ -97,4 +97,12 @@ pub enum JournalError { /// Failed to make a path relative to a directory. #[error("failed to make {0} relative to {1}: {2}")] RelativePath(PathBuf, PathBuf, std::path::StripPrefixError), + + /// Problem with glob pattern. + #[error("Error in glob pattern {0}: {1}")] + PatternError(String, #[source] glob::PatternError), + + /// Problem when matching glob pattern on actual files. + #[error("Failed to match glob pattern {0}: {1}")] + GlobError(String, #[source] glob::GlobError), } diff --git a/src/journal.rs b/src/journal.rs index 8042f83..ad8b4af 100644 --- a/src/journal.rs +++ b/src/journal.rs @@ -2,6 +2,8 @@ use crate::error::JournalError; use crate::git; use crate::template::Templates; use chrono::{DateTime, Local}; +use glob::glob; +use regex::Regex; use std::path::{Path, PathBuf}; use std::process::Command; use tera::Context; @@ -121,6 +123,21 @@ impl Journal { } } + pub fn list_drafts(&self) -> Result<(), JournalError> { + let prefix = format!("{}/", self.drafts().display()); + let pattern = format!("{}*.md", prefix); + let entries = + glob(&pattern).map_err(|err| JournalError::PatternError(pattern.to_string(), err))?; + for entry in entries { + let entry = entry.map_err(|err| JournalError::GlobError(pattern.to_string(), err))?; + let title = get_title(&entry)?; + let entry = entry.file_stem().unwrap().to_string_lossy(); + let entry = entry.strip_prefix(&prefix).unwrap_or(&entry); + println!("{} {}", entry, title); + } + Ok(()) + } + fn edit(&self, editor: &str, filename: &Path) -> Result<(), JournalError> { if editor == "none" { return Ok(()); @@ -209,3 +226,16 @@ fn current_timestamp() -> String { let now: DateTime<Local> = Local::now(); now.to_rfc2822() } + +fn get_title(filename: &Path) -> Result<String, JournalError> { + let text = std::fs::read(filename) + .map_err(|err| JournalError::ReadDraft(filename.to_path_buf(), err))?; + let text = String::from_utf8_lossy(&text); + let pat = Regex::new(r#"^\[\[!meta title="(?P<title>.*)"\]\]"#).unwrap(); + if let Some(caps) = pat.captures(&text) { + if let Some(m) = caps.name("title") { + return Ok(m.as_str().to_string()); + } + } + Ok("(untitled)".to_string()) +} @@ -58,6 +58,9 @@ pub enum SubCommand { /// Create draft for a new journal entry. New(cmd::New), + /// List current drafts. + List(cmd::List), + /// Create topic page. NewTopic(cmd::NewTopic), |