-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(commands)!: Move a lot of the commands into pace-core (#56)
* refactor(commands)!: Move a lot of the commands into pace-core Signed-off-by: simonsan <[email protected]> * refactor: rename option commands Signed-off-by: simonsan <[email protected]> * refactor: move constants to own module Signed-off-by: simonsan <[email protected]> * ci: add feature-powerset to local ci Signed-off-by: simonsan <[email protected]> * fix: missing attrib Signed-off-by: simonsan <[email protected]> * refactor(commands)!: Factor out some resume related things Signed-off-by: simonsan <[email protected]> * fix: shorten user prompt Signed-off-by: simonsan <[email protected]> --------- Signed-off-by: simonsan <[email protected]>
- Loading branch information
Showing
30 changed files
with
600 additions
and
531 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use std::collections::HashSet; | ||
|
||
#[cfg(feature = "clap")] | ||
use clap::Parser; | ||
|
||
use crate::{ | ||
extract_time_or_now, get_storage_from_config, Activity, ActivityKind, ActivityStateManagement, | ||
ActivityStore, PaceConfig, PaceResult, SyncStorage, | ||
}; | ||
|
||
/// `begin` subcommand | ||
#[derive(Debug)] | ||
#[cfg_attr(feature = "clap", derive(Parser))] | ||
pub struct BeginCommandOptions { | ||
/// The Category of the activity you want to start | ||
/// | ||
/// You can use the separator you setup in the configuration file | ||
/// to specify a subcategory. | ||
#[cfg_attr(feature = "clap", clap(short, long, name = "Category"))] | ||
category: Option<String>, | ||
|
||
/// The time the activity has been started at. Format: HH:MM | ||
// FIXME: We should directly parse that into PaceTime or PaceDateTime | ||
#[cfg_attr(feature = "clap", clap(long, name = "Starting Time", alias = "at"))] | ||
start: Option<String>, | ||
|
||
/// The description of the activity you want to start | ||
#[cfg_attr(feature = "clap", clap(name = "Activity Description"))] | ||
description: String, | ||
|
||
/// The tags you want to associate with the activity, separated by a comma | ||
#[cfg_attr( | ||
feature = "clap", | ||
clap(short, long, name = "Tag", value_delimiter = ',') | ||
)] | ||
tags: Option<Vec<String>>, | ||
|
||
/// TODO: The project you want to start tracking time for | ||
/// FIXME: involves parsing the project configuration first | ||
#[cfg_attr(feature = "clap", clap(skip))] | ||
_projects: Option<Vec<String>>, | ||
} | ||
|
||
impl BeginCommandOptions { | ||
/// Inner run implementation for the begin command | ||
pub fn handle_begin(&self, config: &PaceConfig) -> PaceResult<()> { | ||
let Self { | ||
category, | ||
start: time, | ||
description, | ||
tags, | ||
.. // TODO: exclude projects for now | ||
} = self; | ||
|
||
// parse tags from string or get an empty set | ||
let tags = tags | ||
.as_ref() | ||
.map(|tags| tags.iter().cloned().collect::<HashSet<String>>()); | ||
|
||
// parse time from string or get now | ||
let date_time = extract_time_or_now(time)?; | ||
|
||
// TODO: Parse categories and subcategories from string | ||
// let (category, subcategory) = if let Some(ref category) = category { | ||
// let separator = config.general().category_separator(); | ||
// extract_categories(category.as_str(), separator.as_str()) | ||
// } else { | ||
// // if no category is given, use the default category | ||
// // FIXME: This should be the default category from the project configuration | ||
// // but for now, we'll just use category defaults | ||
// // | ||
// // FIXME: We might also want to merge the project configuration with the general configuration first to have precedence | ||
// // | ||
// // let category = if let Some(category) = PACE_APP.config().general().default_category() { | ||
// // category | ||
// // } else { | ||
// // &Category::default() | ||
// // }; | ||
|
||
// (Category::default(), None) | ||
// }; | ||
|
||
let activity = Activity::builder() | ||
.description(description.clone()) | ||
.begin(date_time) | ||
.kind(ActivityKind::default()) | ||
.category(category.clone()) | ||
.tags(tags.clone()) | ||
.build(); | ||
|
||
let activity_store = ActivityStore::new(get_storage_from_config(config)?); | ||
|
||
let activity_item = activity_store.begin_activity(activity.clone())?; | ||
|
||
activity_store.sync()?; | ||
|
||
println!("{}", activity_item.activity()); | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#[cfg(feature = "clap")] | ||
use clap::Parser; | ||
|
||
use crate::{constants::PACE_DEV_DOCS_URL, constants::PACE_DOCS_URL, PaceResult}; | ||
|
||
/// Opens the documentation. | ||
#[derive(Debug, Clone)] | ||
#[cfg_attr(feature = "clap", derive(Parser))] | ||
pub struct DocsCommandOptions { | ||
/// Open the development documentation | ||
#[cfg_attr(feature = "clap", clap(short, long))] | ||
dev: bool, | ||
} | ||
|
||
impl DocsCommandOptions { | ||
pub fn handle_docs(&self) -> PaceResult<()> { | ||
match self.dev { | ||
true => open::that(PACE_DEV_DOCS_URL)?, | ||
false => open::that(PACE_DOCS_URL)?, | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#[cfg(feature = "clap")] | ||
use clap::Parser; | ||
use getset::Getters; | ||
use typed_builder::TypedBuilder; | ||
|
||
use crate::{ | ||
get_storage_from_config, parse_time_from_user_input, ActivityStateManagement, ActivityStore, | ||
EndOptions, PaceConfig, PaceResult, SyncStorage, | ||
}; | ||
|
||
/// `end` subcommand | ||
#[derive(Debug, Clone, PartialEq, TypedBuilder, Eq, Hash, Default, Getters)] | ||
#[getset(get = "pub")] | ||
#[non_exhaustive] | ||
#[cfg_attr(feature = "clap", derive(Parser))] | ||
pub struct EndCommandOptions { | ||
/// The time the activity has ended (defaults to the current time if not provided). Format: HH:MM | ||
#[cfg_attr(feature = "clap", clap(long, name = "Finishing Time", alias = "at"))] | ||
// FIXME: We should directly parse that into PaceTime or PaceDateTime | ||
end: Option<String>, | ||
|
||
/// End only the last unfinished activity | ||
#[cfg_attr(feature = "clap", clap(long))] | ||
only_last: bool, | ||
} | ||
|
||
impl EndCommandOptions { | ||
pub fn handle_end(&self, config: &PaceConfig) -> PaceResult<()> { | ||
let time = parse_time_from_user_input(&self.end)?; | ||
|
||
let activity_store = ActivityStore::new(get_storage_from_config(config)?); | ||
|
||
let end_opts = EndOptions::builder().end_time(time).build(); | ||
|
||
if self.only_last { | ||
if let Some(last_activity) = activity_store.end_last_unfinished_activity(end_opts)? { | ||
println!("Ended {}", last_activity.activity()); | ||
} | ||
} else if let Some(unfinished_activities) = | ||
activity_store.end_all_unfinished_activities(end_opts)? | ||
{ | ||
for activity in &unfinished_activities { | ||
println!("Ended {}", activity.activity()); | ||
} | ||
} else { | ||
println!("No unfinished activities to end."); | ||
} | ||
|
||
activity_store.sync()?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#[cfg(feature = "clap")] | ||
use clap::Parser; | ||
|
||
use crate::{ | ||
get_storage_from_config, ActivityItem, ActivityQuerying, ActivityReadOps, ActivityStatusFilter, | ||
ActivityStore, PaceConfig, PaceResult, | ||
}; | ||
|
||
/// `now` subcommand | ||
#[derive(Debug)] | ||
#[cfg_attr(feature = "clap", derive(Parser))] | ||
pub struct NowCommandOptions {} | ||
|
||
impl NowCommandOptions { | ||
pub fn handle_now(&self, config: &PaceConfig) -> PaceResult<()> { | ||
let activity_store = ActivityStore::new(get_storage_from_config(config)?); | ||
|
||
match activity_store.list_current_activities(ActivityStatusFilter::Active)? { | ||
Some(activities) => { | ||
let activity_items = activities | ||
.iter() | ||
.flat_map(|activity_id| activity_store.read_activity(*activity_id)) | ||
.collect::<Vec<ActivityItem>>(); | ||
|
||
activity_items.iter().for_each(|activity| { | ||
println!("{}", activity.activity()); | ||
}); | ||
} | ||
None => { | ||
println!("No activities are currently running."); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.