summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/feed.rs7
-rw-r--r--src/lib.rs17
-rw-r--r--src/main.rs23
-rw-r--r--src/manager.rs25
4 files changed, 41 insertions, 31 deletions
diff --git a/src/feed.rs b/src/feed.rs
index f9a7893..77f1a45 100644
--- a/src/feed.rs
+++ b/src/feed.rs
@@ -104,6 +104,7 @@ impl Feed {
104 104
105 // update entries 105 // update entries
106 self.entries = entries.into_iter().map(Result::unwrap).collect(); 106 self.entries = entries.into_iter().map(Result::unwrap).collect();
107 self.entries.sort_by(|a, b| b.published.cmp(&a.published));
107 108
108 Ok(pull_status) 109 Ok(pull_status)
109 } 110 }
@@ -166,16 +167,16 @@ impl fmt::Display for Entry {
166 f, 167 f,
167 "{} {} {}", 168 "{} {} {}",
168 self.published.format(crate::DATE_FMT), 169 self.published.format(crate::DATE_FMT),
170 Style::new().dimmed().paint(self.title.to_ascii_lowercase()),
169 Style::new().fg(Color::Cyan).paint( 171 Style::new().fg(Color::Cyan).paint(
170 self.link 172 self.link
171 .as_str() 173 .as_str()
172 .trim_end_matches('/') 174 .trim_end_matches('/')
173 .trim_start_matches("http://")
174 .trim_start_matches("https://")
175 .trim_start_matches("http://www.") 175 .trim_start_matches("http://www.")
176 .trim_start_matches("https://www.") 176 .trim_start_matches("https://www.")
177 .trim_start_matches("https://")
178 .trim_start_matches("http://")
177 ), 179 ),
178 Style::new().dimmed().paint(self.title.to_ascii_lowercase()),
179 ) 180 )
180 } 181 }
181} 182}
diff --git a/src/lib.rs b/src/lib.rs
index 7376d44..5b2a501 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,20 +5,3 @@ pub mod manager;
5pub mod status; 5pub mod status;
6 6
7pub(crate) static DATE_FMT: &str = "%e %b %y"; 7pub(crate) static DATE_FMT: &str = "%e %b %y";
8
9pub trait PrintResult {
10 fn print(&self);
11}
12
13impl<T, E> PrintResult for Result<T, E>
14where
15 T: std::fmt::Display,
16 E: std::fmt::Display,
17{
18 fn print(&self) {
19 match self {
20 Ok(ok) => println!("{ok}"),
21 Err(err) => eprintln!("{err}"),
22 }
23 }
24}
diff --git a/src/main.rs b/src/main.rs
index 8c94843..b36e08f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
1use chrono::{naive::Days, prelude::*}; 1use chrono::{naive::Days, prelude::*};
2use clap::{Args, Parser, Subcommand, ValueEnum}; 2use clap::{Args, Parser, Subcommand, ValueEnum};
3use syn::{manager::Manager, PrintResult}; 3use syn::manager::Manager;
4 4
5#[derive(Parser)] 5#[derive(Parser)]
6#[command(author, version, about, long_about = None)] 6#[command(author, version, about, long_about = None)]
@@ -29,7 +29,7 @@ impl Default for Command {
29 29
30#[derive(Args)] 30#[derive(Args)]
31struct AddCommand { 31struct AddCommand {
32 url: String, 32 urls: Vec<String>,
33} 33}
34 34
35#[derive(Args)] 35#[derive(Args)]
@@ -49,11 +49,28 @@ struct PullCommand {
49 target: Option<String>, 49 target: Option<String>,
50} 50}
51 51
52pub trait PrintResult {
53 fn print(&self);
54}
55
56impl<T, E> PrintResult for Result<T, E>
57where
58 T: std::fmt::Display,
59 E: std::fmt::Display,
60{
61 fn print(&self) {
62 match self {
63 Ok(ok) => println!("{ok}"),
64 Err(err) => eprintln!("{err}"),
65 }
66 }
67}
68
52#[tokio::main(flavor = "current_thread")] 69#[tokio::main(flavor = "current_thread")]
53async fn main() { 70async fn main() {
54 let opts = Cli::parse(); 71 let opts = Cli::parse();
55 match &opts.command.unwrap_or_default() { 72 match &opts.command.unwrap_or_default() {
56 Command::Add(AddCommand { url }) => { 73 Command::Add(AddCommand { urls }) => {
57 let mut manager = Manager::load().unwrap_or_else(|e| { 74 let mut manager = Manager::load().unwrap_or_else(|e| {
58 eprintln!("{e}"); 75 eprintln!("{e}");
59 Manager::default() 76 Manager::default()
diff --git a/src/manager.rs b/src/manager.rs
index 34e19be..5330d80 100644
--- a/src/manager.rs
+++ b/src/manager.rs
@@ -13,7 +13,7 @@ pub struct Manager {
13} 13}
14 14
15impl Manager { 15impl Manager {
16 pub async fn add_feed(&mut self, url: &str) -> Result<PullStatus, Error> { 16 fn add_feed(&mut self, url: &str) -> Result<&mut Feed, Error> {
17 let link = Url::parse(&url).map_err(|e| AddError::InvalidUrl(e.to_string()))?; 17 let link = Url::parse(&url).map_err(|e| AddError::InvalidUrl(e.to_string()))?;
18 18
19 // check if this feed is already present 19 // check if this feed is already present
@@ -22,17 +22,24 @@ impl Manager {
22 } 22 }
23 23
24 // construct a new feed 24 // construct a new feed
25 let mut feed = Feed::new(link.clone()); 25 let feed = Feed::new(link.clone());
26
27 let status = feed
28 .pull()
29 .await
30 .map_err(|pull_err| Error::Pull(link, pull_err))?;
31 26
32 // add new feed 27 // add new feed
33 self.feeds.push(feed); 28 self.feeds.push(feed);
34 29
35 Ok(status) 30 Ok(self.feeds.last_mut().unwrap())
31 }
32
33 pub async fn add_feed_and_pull(&mut self, url: &str) -> Result<PullStatus, Error> {
34 let feed = self.add_feed(url)?;
35 feed.pull()
36 .await
37 .map_err(|pull_err| Error::Pull(feed.link.clone(), pull_err))
38 }
39
40 pub async fn add_feeds_and_pull(&mut self, urls: &[&str]) -> Vec<Result<PullStatus, Error>> {
41 let add_results = urls.into_iter().map(|url| self.add_feed(&url));
42 self.pull()
36 } 43 }
37 44
38 pub async fn pull(&mut self) -> Vec<Result<PullStatus, PullError>> { 45 pub async fn pull(&mut self) -> Vec<Result<PullStatus, PullError>> {
@@ -71,6 +78,8 @@ impl Manager {
71 } 78 }
72} 79}
73 80
81// an iterator over a combined list of feeds (assumes each feed is already a sorted list of
82// entries)
74struct EntryIterator<'e> { 83struct EntryIterator<'e> {
75 all_entries: Vec<&'e [Entry]>, 84 all_entries: Vec<&'e [Entry]>,
76} 85}