list profiles
This commit is contained in:
		
							
								
								
									
										26
									
								
								src/args.rs
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/args.rs
									
									
									
									
									
								
							@@ -69,6 +69,9 @@ pub enum Command {
 | 
			
		||||
    GitIgnore,
 | 
			
		||||
    /// Lists tasks according to the specified fields, ordering and filters.
 | 
			
		||||
    List {
 | 
			
		||||
        /// Use an existing profile for list options, ignoring other arguments.
 | 
			
		||||
        #[clap(long)]
 | 
			
		||||
        profile : Option<String>,
 | 
			
		||||
        #[clap(flatten)]
 | 
			
		||||
        options : ListOptions,
 | 
			
		||||
    },
 | 
			
		||||
@@ -104,7 +107,7 @@ pub enum Command {
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(clap::StructOpt, Debug, PartialEq, Eq)]
 | 
			
		||||
#[derive(clap::StructOpt, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
 | 
			
		||||
pub struct ListOptions {
 | 
			
		||||
    /// Which columns to include.
 | 
			
		||||
    #[clap(short, value_enum)]
 | 
			
		||||
@@ -195,7 +198,26 @@ pub enum ConfigCommand {
 | 
			
		||||
    Editor {
 | 
			
		||||
        /// Command to launch editor. Omit to view current editor.
 | 
			
		||||
        editor : Option<String>,
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    /// For working with profiles for the list command.
 | 
			
		||||
    #[clap(subcommand)]
 | 
			
		||||
    Profile(ProfileCommand),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(clap::Subcommand, Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum ProfileCommand {
 | 
			
		||||
    New {
 | 
			
		||||
        /// Name of the new profile.
 | 
			
		||||
        name : String,
 | 
			
		||||
        #[clap(flatten)]
 | 
			
		||||
        options : ListOptions,
 | 
			
		||||
    },
 | 
			
		||||
    Delete {
 | 
			
		||||
        /// Name of the profile to delete.
 | 
			
		||||
        name : String,
 | 
			
		||||
    },
 | 
			
		||||
    /// List names of currently set up profiles.
 | 
			
		||||
    List,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(clap::Subcommand, Debug, PartialEq, Eq)]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
use crate::args;
 | 
			
		||||
use crate::error;
 | 
			
		||||
use crate::format;
 | 
			
		||||
 | 
			
		||||
@@ -8,6 +9,13 @@ pub struct Config {
 | 
			
		||||
    /// Paths for all vaults, ordered according to recent usage, with current at the front.
 | 
			
		||||
    pub vaults : Vec<(String, path::PathBuf)>,
 | 
			
		||||
    pub editor : String,
 | 
			
		||||
    pub profiles : Vec<Profile>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
 | 
			
		||||
pub struct Profile {
 | 
			
		||||
    name : String,
 | 
			
		||||
    options : args::ListOptions,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Config {
 | 
			
		||||
@@ -15,6 +23,7 @@ impl Default for Config {
 | 
			
		||||
        Self {
 | 
			
		||||
            vaults : Vec::default(),
 | 
			
		||||
            editor : String::from("vim"),
 | 
			
		||||
            profiles : Vec::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -62,8 +71,6 @@ impl Config {
 | 
			
		||||
                Err(error::Error::Generic(format!("No vault named {} exists", format::vault(old_name))))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Adds the vault to the configuration.
 | 
			
		||||
@@ -132,6 +139,51 @@ impl Config {
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    pub fn create_profile(&mut self, name : String, options : args::ListOptions) -> Result<(), error::Error> {
 | 
			
		||||
        if self.profiles.iter().any(|Profile { name : n, options : _ }| n == &name) {
 | 
			
		||||
            Err(error::Error::Generic(format!("A profile by the name {} already exists", format::profile(&name))))
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            self.profiles.push(Profile { name, options });
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_profile(&self, name : &String) -> Result<&args::ListOptions, error::Error> {
 | 
			
		||||
        self.profiles
 | 
			
		||||
            .iter()
 | 
			
		||||
            .find(|Profile { name : n, options : _ }| n == name)
 | 
			
		||||
            .map(|Profile { name : _, options : o }| o)
 | 
			
		||||
            .ok_or(error::Error::Generic(format!("No profile by the name {} exists", format::profile(name))))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn delete_profile(&mut self, name : &String) -> Result<(), error::Error> {
 | 
			
		||||
        match self.profiles.iter().position(|Profile { name : n, options : _ }| n == name) {
 | 
			
		||||
            Some(index) => {
 | 
			
		||||
                let _ = self.profiles.swap_remove(index);
 | 
			
		||||
                Ok(())
 | 
			
		||||
            },
 | 
			
		||||
            None => {
 | 
			
		||||
                Err(error::Error::Generic(format!("No profile by the name {} exists", format::profile(name))))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// Lists all profiles to stdout.
 | 
			
		||||
    pub fn list_profiles(&self) -> Result<(), error::Error> {
 | 
			
		||||
        if self.profiles.is_empty() {
 | 
			
		||||
            Err(error::Error::Generic(format!("No profiles currently set up, try running: {}", format::command("toru config profile new <NAME> <OPTIONS>"))))
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            for Profile { name, options : _ } in self.profiles.iter() {
 | 
			
		||||
                println!("{}", format::profile(name));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,8 @@ pub static TASK : (u8, u8, u8) = (39, 174, 96);
 | 
			
		||||
pub static FILE : (u8, u8, u8) = (255, 184, 184);
 | 
			
		||||
// Grey
 | 
			
		||||
pub static GREY : (u8, u8, u8) = (99, 110, 114);
 | 
			
		||||
// Pink
 | 
			
		||||
pub static PROFILE : (u8, u8, u8) = (253, 121, 168);
 | 
			
		||||
 | 
			
		||||
mod due {
 | 
			
		||||
    pub static OVERDUE : (u8, u8, u8) = (192, 57, 43);
 | 
			
		||||
@@ -65,11 +67,14 @@ pub fn file(string : &str) -> colored::ColoredString {
 | 
			
		||||
    text(string, FILE).bold()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub fn greyed_out(string : &str) -> colored::ColoredString {
 | 
			
		||||
    text(string, GREY)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn profile(string : &str) -> colored::ColoredString {
 | 
			
		||||
    text(string, PROFILE)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn priority(priority : &tasks::Priority) -> String {
 | 
			
		||||
    use tasks::Priority::*;
 | 
			
		||||
    let priority = match priority {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -60,9 +60,8 @@ fn program() -> Result<(), error::Error> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if let Command::Config(command) = command {
 | 
			
		||||
        use ConfigCommand::*;
 | 
			
		||||
        match command {
 | 
			
		||||
            Editor { editor } => {
 | 
			
		||||
            ConfigCommand::Editor { editor } => {
 | 
			
		||||
                match editor {
 | 
			
		||||
                    Some(editor) => {
 | 
			
		||||
                        config.editor = editor;
 | 
			
		||||
@@ -72,6 +71,21 @@ fn program() -> Result<(), error::Error> {
 | 
			
		||||
                        println!("Current editor command: {}", config.editor);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            ConfigCommand::Profile(command) => {
 | 
			
		||||
                match command {
 | 
			
		||||
                    ProfileCommand::New { name, options } => {
 | 
			
		||||
                        config.create_profile(name.clone(), options)?;
 | 
			
		||||
                        println!("Created profile {}", format::profile(&name))
 | 
			
		||||
                    },
 | 
			
		||||
                    ProfileCommand::Delete { name } => {
 | 
			
		||||
                        config.delete_profile(&name)?;
 | 
			
		||||
                        println!("Deleted profile {}", format::profile(&name))
 | 
			
		||||
                    },
 | 
			
		||||
                    ProfileCommand::List => {
 | 
			
		||||
                        config.list_profiles()?;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -157,7 +171,15 @@ fn program() -> Result<(), error::Error> {
 | 
			
		||||
                task.save()?;
 | 
			
		||||
                println!("Marked task {} as complete", format::id(id));
 | 
			
		||||
            },
 | 
			
		||||
            Command::List { options } => {
 | 
			
		||||
            Command::List { profile, options } => {
 | 
			
		||||
                let options = match profile {
 | 
			
		||||
                    Some(profile) => {
 | 
			
		||||
                        config.get_profile(&profile)?
 | 
			
		||||
                    },
 | 
			
		||||
                    None => {
 | 
			
		||||
                        &options
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                tasks::list(options, vault_folder, &state)?;
 | 
			
		||||
            },
 | 
			
		||||
            // All commands which are dealt with in if let chain at start.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/tasks.rs
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/tasks.rs
									
									
									
									
									
								
							@@ -355,7 +355,7 @@ fn compare_due_dates<T : Ord>(first : &Option<T>, second : &Option<T>) -> cmp::O
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Lists all tasks in the specified vault.
 | 
			
		||||
pub fn list(mut options : super::ListOptions, vault_folder : &path::Path, state : &state::State) -> Result<(), error::Error> {
 | 
			
		||||
pub fn list(options : &super::ListOptions, vault_folder : &path::Path, state : &state::State) -> Result<(), error::Error> {
 | 
			
		||||
 | 
			
		||||
    let mut table = comfy_table::Table::new();
 | 
			
		||||
    table
 | 
			
		||||
@@ -512,10 +512,10 @@ pub fn list(mut options : super::ListOptions, vault_folder : &path::Path, state
 | 
			
		||||
    let mut headers = vec!["Id", "Name"];
 | 
			
		||||
 | 
			
		||||
    // Remove duplicate columns.
 | 
			
		||||
    {
 | 
			
		||||
    let unique_columns : Vec<_> = {
 | 
			
		||||
        let mut columns = HashSet::new();
 | 
			
		||||
 | 
			
		||||
        options.column = options.column
 | 
			
		||||
        options.column.clone()
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .filter(|c| {
 | 
			
		||||
                if columns.contains(c) {
 | 
			
		||||
@@ -526,11 +526,11 @@ pub fn list(mut options : super::ListOptions, vault_folder : &path::Path, state
 | 
			
		||||
                    true
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .collect();
 | 
			
		||||
    }
 | 
			
		||||
            .collect()
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    use super::Column;
 | 
			
		||||
    for column in &options.column {
 | 
			
		||||
    for column in &unique_columns {
 | 
			
		||||
        match column {
 | 
			
		||||
            Column::Tracked => {
 | 
			
		||||
                headers.push("Tracked");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user