list profiles

This commit is contained in:
aaron-jack-manning 2022-09-03 12:28:25 +10:00
parent 310aa84f50
commit ae7887fd35
5 changed files with 115 additions and 14 deletions

View File

@ -69,6 +69,9 @@ pub enum Command {
GitIgnore, GitIgnore,
/// Lists tasks according to the specified fields, ordering and filters. /// Lists tasks according to the specified fields, ordering and filters.
List { List {
/// Use an existing profile for list options, ignoring other arguments.
#[clap(long)]
profile : Option<String>,
#[clap(flatten)] #[clap(flatten)]
options : ListOptions, 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 { pub struct ListOptions {
/// Which columns to include. /// Which columns to include.
#[clap(short, value_enum)] #[clap(short, value_enum)]
@ -195,7 +198,26 @@ pub enum ConfigCommand {
Editor { Editor {
/// Command to launch editor. Omit to view current editor. /// Command to launch editor. Omit to view current editor.
editor : Option<String>, 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)] #[derive(clap::Subcommand, Debug, PartialEq, Eq)]

View File

@ -1,3 +1,4 @@
use crate::args;
use crate::error; use crate::error;
use crate::format; use crate::format;
@ -8,6 +9,13 @@ pub struct Config {
/// Paths for all vaults, ordered according to recent usage, with current at the front. /// Paths for all vaults, ordered according to recent usage, with current at the front.
pub vaults : Vec<(String, path::PathBuf)>, pub vaults : Vec<(String, path::PathBuf)>,
pub editor : String, 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 { impl Default for Config {
@ -15,6 +23,7 @@ impl Default for Config {
Self { Self {
vaults : Vec::default(), vaults : Vec::default(),
editor : String::from("vim"), 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)))) Err(error::Error::Generic(format!("No vault named {} exists", format::vault(old_name))))
} }
} }
} }
/// Adds the vault to the configuration. /// Adds the vault to the configuration.
@ -132,6 +139,51 @@ impl Config {
Ok(()) 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(())
}
}
} }

View File

@ -23,6 +23,8 @@ pub static TASK : (u8, u8, u8) = (39, 174, 96);
pub static FILE : (u8, u8, u8) = (255, 184, 184); pub static FILE : (u8, u8, u8) = (255, 184, 184);
// Grey // Grey
pub static GREY : (u8, u8, u8) = (99, 110, 114); pub static GREY : (u8, u8, u8) = (99, 110, 114);
// Pink
pub static PROFILE : (u8, u8, u8) = (253, 121, 168);
mod due { mod due {
pub static OVERDUE : (u8, u8, u8) = (192, 57, 43); pub static OVERDUE : (u8, u8, u8) = (192, 57, 43);
@ -65,11 +67,14 @@ pub fn file(string : &str) -> colored::ColoredString {
text(string, FILE).bold() text(string, FILE).bold()
} }
pub fn greyed_out(string : &str) -> colored::ColoredString { pub fn greyed_out(string : &str) -> colored::ColoredString {
text(string, GREY) text(string, GREY)
} }
pub fn profile(string : &str) -> colored::ColoredString {
text(string, PROFILE)
}
pub fn priority(priority : &tasks::Priority) -> String { pub fn priority(priority : &tasks::Priority) -> String {
use tasks::Priority::*; use tasks::Priority::*;
let priority = match priority { let priority = match priority {

View File

@ -60,9 +60,8 @@ fn program() -> Result<(), error::Error> {
} }
} }
else if let Command::Config(command) = command { else if let Command::Config(command) = command {
use ConfigCommand::*;
match command { match command {
Editor { editor } => { ConfigCommand::Editor { editor } => {
match editor { match editor {
Some(editor) => { Some(editor) => {
config.editor = editor; config.editor = editor;
@ -72,6 +71,21 @@ fn program() -> Result<(), error::Error> {
println!("Current editor command: {}", config.editor); 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()?; task.save()?;
println!("Marked task {} as complete", format::id(id)); 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)?; tasks::list(options, vault_folder, &state)?;
}, },
// All commands which are dealt with in if let chain at start. // All commands which are dealt with in if let chain at start.

View File

@ -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. /// 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(); let mut table = comfy_table::Table::new();
table table
@ -512,10 +512,10 @@ pub fn list(mut options : super::ListOptions, vault_folder : &path::Path, state
let mut headers = vec!["Id", "Name"]; let mut headers = vec!["Id", "Name"];
// Remove duplicate columns. // Remove duplicate columns.
{ let unique_columns : Vec<_> = {
let mut columns = HashSet::new(); let mut columns = HashSet::new();
options.column = options.column options.column.clone()
.into_iter() .into_iter()
.filter(|c| { .filter(|c| {
if columns.contains(c) { if columns.contains(c) {
@ -526,11 +526,11 @@ pub fn list(mut options : super::ListOptions, vault_folder : &path::Path, state
true true
} }
}) })
.collect(); .collect()
} };
use super::Column; use super::Column;
for column in &options.column { for column in &unique_columns {
match column { match column {
Column::Tracked => { Column::Tracked => {
headers.push("Tracked"); headers.push("Tracked");