aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Jaremko2019-02-24 18:57:46 -0500
committerNathan Jaremko2019-02-24 18:57:46 -0500
commitec5f7a63028303f0f0aab78dbebd61afba68b184 (patch)
treefd48b58047e3abdb2b49c2de3128696371ad6754
parentb238a6606fb4ea0df4c69b4f15874a65f22263b4 (diff)
downloadpodcast-ec5f7a63028303f0f0aab78dbebd61afba68b184.tar.bz2
Add completion generation
-rw-r--r--CHANGELOG3
-rw-r--r--Cargo.toml2
-rw-r--r--src/actions.rs109
-rw-r--r--src/main.rs7
-rw-r--r--src/match_handler.rs18
-rw-r--r--src/parser.rs5
-rw-r--r--src/structs.rs7
-rw-r--r--src/utils.rs20
8 files changed, 73 insertions, 98 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ad65474..b99a4f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+0.8.2
+- Add completion generation for all major shells
+
0.8.1
- Fix parser to actually see "sub" subcommand
diff --git a/Cargo.toml b/Cargo.toml
index b13c130..c6c275b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,4 +32,4 @@ serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
serde_yaml = "0.8"
-toml = "0.4"
+toml = "0.4" \ No newline at end of file
diff --git a/src/actions.rs b/src/actions.rs
index 0ecb083..cb4a157 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -7,6 +7,8 @@ use std::io::{self, BufReader, Read, Write};
use std::process::Command;
use crate::errors::*;
+use clap::App;
+use clap::Shell;
use rayon::prelude::*;
use regex::Regex;
use reqwest;
@@ -54,11 +56,10 @@ pub fn download_rss(config: &Config, url: &str) -> Result<()> {
println!("Downloading episode(s)...");
let channel = download_rss_feed(url)?;
let mut download_limit = config.auto_download_limit as usize;
- if 0 < download_limit {
+ if 0 < download_limit {
let podcast = Podcast::from(channel);
let episodes = podcast.episodes();
- if episodes.len() < download_limit
- {
+ if episodes.len() < download_limit {
download_limit = episodes.len()
}
episodes[..download_limit].par_iter().for_each(|ep| {
@@ -187,36 +188,32 @@ pub fn download(podcast_name: &str, episode: &Episode) -> Result<()> {
create_dir_if_not_exist(&path)?;
if let Some(url) = episode.url() {
- if let Some(title) = episode.title() {
- let mut filename = title;
- filename.push_str(
- episode.extension()
- .chain_err(|| "unable to retrieve extension")?,
- );
- path.push(filename);
- if !path.exists() {
- {
- let mut handle = stdout.lock();
- writeln!(&mut handle, "Downloading: {:?}", &path).ok();
- }
- let mut file = File::create(&path).chain_err(|| UNABLE_TO_CREATE_FILE)?;
- let mut resp = reqwest::get(url).chain_err(|| UNABLE_TO_GET_HTTP_RESPONSE)?;
- let mut content: Vec<u8> = Vec::new();
- resp.read_to_end(&mut content)
- .chain_err(|| UNABLE_TO_READ_RESPONSE_TO_END)?;
- file.write_all(&content)
- .chain_err(|| UNABLE_TO_WRITE_FILE)?;
- } else {
+ if let Some(title) = episode.title() {
+ let mut filename = title;
+ filename.push_str(
+ episode
+ .extension()
+ .chain_err(|| "unable to retrieve extension")?,
+ );
+ path.push(filename);
+ if !path.exists() {
+ {
let mut handle = stdout.lock();
- writeln!(
- &mut handle,
- "File already exists: {:?}",
- &path
- )
- .ok();
+ writeln!(&mut handle, "Downloading: {:?}", &path).ok();
}
+ let mut file = File::create(&path).chain_err(|| UNABLE_TO_CREATE_FILE)?;
+ let mut resp = reqwest::get(url).chain_err(|| UNABLE_TO_GET_HTTP_RESPONSE)?;
+ let mut content: Vec<u8> = Vec::new();
+ resp.read_to_end(&mut content)
+ .chain_err(|| UNABLE_TO_READ_RESPONSE_TO_END)?;
+ file.write_all(&content)
+ .chain_err(|| UNABLE_TO_WRITE_FILE)?;
+ } else {
+ let mut handle = stdout.lock();
+ writeln!(&mut handle, "File already exists: {:?}", &path).ok();
}
}
+ }
Ok(())
}
@@ -256,8 +253,7 @@ pub fn download_episode_by_name(
.collect();
if let Some(ep) = filtered_episodes.first() {
- download(podcast.title(), ep)
- .chain_err(|| "unable to download episode")?;
+ download(podcast.title(), ep).chain_err(|| "unable to download episode")?;
}
}
}
@@ -519,50 +515,13 @@ pub fn remove_podcast(state: &mut State, p_search: &str) -> Result<()> {
Ok(())
}
-pub fn print_completion(arg: &str) {
- let zsh = r#"#compdef podcast
-#autoload
-
-# Copyright (C) 2019:
-# Nathan Jaremko <njaremko@gmail.com>
-# All Rights Reserved.
-# This file is licensed under the GPLv2+. Please see COPYING for more information.
-
-_podcast() {
- local ret=1
- _arguments -C \
- '1: :_podcast_cmds' \
- && ret=0
-}
-
-_podcast_cmds () {
- local subcommands;
- subcommands=(
- "download:Download episodes of podcast"
- "help:Prints this message or the help of the given subcommand(s)"
- "ls:List podcasts or episodes of a podcast"
- "play:Play episodes of a podcast"
- "refresh:Refreshes subscribed podcasts"
- "rm:Unsubscribe from a podcast"
- "completion:Shell Completions"
- "search:Searches for podcasts"
- "subscribe:Subscribe to a podcast RSS feed"
- "update:check for updates"
- )
- _describe -t commands 'podcast' subcommands
- _arguments : \
- "--version[Output version information]" \
- "--help[Output help message]"
-}
-
-_podcast"#;
-
- //let bash = "";
- //let sh = "";
+pub fn print_completion(app: &mut App, arg: &str) {
match arg {
- "zsh" => println!("{}", zsh),
- //"bash" => println!("{}", bash),
- //"sh" => println!("{}", sh),
- _ => println!("Only options avaliable are: zsh"),
+ "zsh" => app.gen_completions_to("podcast", Shell::Zsh, &mut io::stdout()),
+ "bash" => app.gen_completions_to("podcast", Shell::Bash, &mut io::stdout()),
+ "powershell" => app.gen_completions_to("podcast", Shell::PowerShell, &mut io::stdout()),
+ "fish" => app.gen_completions_to("podcast", Shell::Fish, &mut io::stdout()),
+ "elvish" => app.gen_completions_to("podcast", Shell::Elvish, &mut io::stdout()),
+ other => eprintln!("Completions are not available for {}", other),
}
}
diff --git a/src/main.rs b/src/main.rs
index 8be9e82..9d5b4d5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -30,14 +30,15 @@ pub mod errors {
use self::errors::*;
use self::structs::*;
-const VERSION: &str = "0.8.1";
+const VERSION: &str = "0.8.2";
fn main() -> Result<()> {
utils::create_directories().chain_err(|| "unable to create directories")?;
migration_handler::migrate_old_subscriptions()?;
let mut state = State::new(VERSION).chain_err(|| "unable to load state")?;
let config = Config::new()?;
- let matches = parser::get_matches(&VERSION);
- match_handler::handle_matches(&VERSION, &mut state, &config, &matches)?;
+ let mut app = parser::get_app(&VERSION);
+ let matches = app.clone().get_matches();
+ match_handler::handle_matches(&VERSION, &mut state, &config, &mut app, &matches)?;
state.save().chain_err(|| "unable to save state")
}
diff --git a/src/match_handler.rs b/src/match_handler.rs
index 599e8f1..428f99c 100644
--- a/src/match_handler.rs
+++ b/src/match_handler.rs
@@ -1,4 +1,7 @@
-use clap::ArgMatches;
+use clap::{App, ArgMatches};
+
+use std::env;
+use std::path::Path;
use crate::actions::*;
use crate::errors::*;
@@ -8,6 +11,7 @@ pub fn handle_matches(
version: &str,
state: &mut State,
config: &Config,
+ app: &mut App,
matches: &ArgMatches,
) -> Result<()> {
match matches.subcommand_name() {
@@ -92,8 +96,16 @@ pub fn handle_matches(
.subcommand_matches("completion")
.chain_err(|| "unable to find subcommand matches")?;
match matches.value_of("SHELL") {
- Some(shell) => print_completion(shell),
- None => print_completion(""),
+ Some(shell) => print_completion(app, shell),
+ None => {
+ let shell_path_env = env::var("SHELL");
+ if let Ok(p) = shell_path_env {
+ let shell_path = Path::new(&p);
+ if let Some(shell) = shell_path.file_name() {
+ print_completion(app, shell.to_str().chain_err(|| format!("Unable to convert {:?} to string", shell))?)
+ }
+ }
+ }
}
}
Some("refresh") => update_rss(state),
diff --git a/src/parser.rs b/src/parser.rs
index ce5ca93..6802ceb 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,6 +1,6 @@
-use clap::{App, Arg, ArgMatches, SubCommand};
+use clap::{App, Arg, SubCommand};
-pub fn get_matches<'a>(version: &str) -> ArgMatches<'a> {
+pub fn get_app<'a, 'b>(version: &'a str) -> App<'a, 'b> {
App::new("podcast")
.version(version)
.author("Nathan J. <njaremko@gmail.com>")
@@ -133,5 +133,4 @@ pub fn get_matches<'a>(version: &str) -> ArgMatches<'a> {
.index(1),
),
)
- .get_matches()
}
diff --git a/src/structs.rs b/src/structs.rs
index d6bad40..1c3ceaf 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -103,9 +103,10 @@ impl State {
};
state.version = String::from(version);
// Check if a day has passed (86400 seconds) since last launch
- if 86400 < Utc::now()
- .signed_duration_since(state.last_run_time)
- .num_seconds()
+ if 86400
+ < Utc::now()
+ .signed_duration_since(state.last_run_time)
+ .num_seconds()
{
update_rss(&mut state);
check_for_update(&state.version)?;
diff --git a/src/utils.rs b/src/utils.rs
index 5c3b2db..e1b2ccb 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -66,7 +66,7 @@ pub fn create_dir_if_not_exist(path: &PathBuf) -> Result<()> {
.recursive(true)
.create(&path)
.chain_err(|| UNABLE_TO_CREATE_DIRECTORY)?;
- Ok(())
+ Ok(())
}
pub fn create_directories() -> Result<()> {
@@ -76,16 +76,16 @@ pub fn create_directories() -> Result<()> {
}
pub fn delete(title: &str) -> Result<()> {
- let mut path = get_xml_dir()?;
- let mut filename = String::from(title);
- filename.push_str(".xml");
- path.push(filename);
- fs::remove_file(path).chain_err(|| UNABLE_TO_REMOVE_FILE)
- }
+ let mut path = get_xml_dir()?;
+ let mut filename = String::from(title);
+ filename.push_str(".xml");
+ path.push(filename);
+ fs::remove_file(path).chain_err(|| UNABLE_TO_REMOVE_FILE)
+}
- pub fn delete_all() -> Result<()> {
- fs::remove_dir_all(get_xml_dir()?).chain_err(|| UNABLE_TO_READ_DIRECTORY)
- }
+pub fn delete_all() -> Result<()> {
+ fs::remove_dir_all(get_xml_dir()?).chain_err(|| UNABLE_TO_READ_DIRECTORY)
+}
pub fn already_downloaded(dir: &str) -> Result<HashSet<String>> {
let mut result = HashSet::new();