From 80bd48f44c1ba6c5010f7d50fd9387b1c4424464 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Thu, 15 Jul 2021 17:34:08 +0300 Subject: feat: add command to list current drafts Sponsored-by: author --- Cargo.lock | 25 +++++++++++++++++-------- Cargo.toml | 3 ++- jt.md | 3 +++ src/bin/jt2.rs | 1 + src/cmd.rs | 11 +++++++++++ src/error.rs | 8 ++++++++ src/journal.rs | 30 ++++++++++++++++++++++++++++++ src/opt.rs | 3 +++ 8 files changed, 75 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6a7e11..9ea5edc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -215,6 +217,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "globset" version = "0.4.6" @@ -297,6 +305,7 @@ dependencies = [ "anyhow", "chrono", "directories-next", + "glob", "log", "pretty_env_logger", "regex", @@ -342,9 +351,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "num-integer" @@ -499,9 +508,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.5" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", @@ -510,9 +519,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.23" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "ryu" diff --git a/Cargo.toml b/Cargo.toml index 6bbe649..98ec949 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,10 @@ edition = "2018" anyhow = "1" chrono = "0.4" directories-next = "2.0.0" +glob = "0.3.0" log = "0.4" pretty_env_logger = "0.4" -regex = "1" +regex = "1.5.4" serde = { version = "1", features = ["derive"] } serde_yaml = "0.8" structopt = "0.3" diff --git a/jt.md b/jt.md index 0a945ea..f2729ff 100644 --- a/jt.md +++ b/jt.md @@ -158,6 +158,9 @@ and there is one draft in jrnl and draft 0 in jrnl contains "Abracadabra" and draft 0 in jrnl contains "!meta date=" +when I run jt2 --dirname=jrnl list +then stdout matches regex ^0 Abracadabra$ + given an executable script append.sh when I run jt2 --editor=./append.sh --dirname=jrnl edit 0 then command is successful 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)?, } diff --git a/src/cmd.rs b/src/cmd.rs index da917ee..2f2f626 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -61,6 +61,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")] 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::now(); now.to_rfc2822() } + +fn get_title(filename: &Path) -> Result { + 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.*)"\]\]"#).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()) +} diff --git a/src/opt.rs b/src/opt.rs index 7d3dcda..7530f54 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -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), -- cgit v1.2.1