Skip to content

Commit

Permalink
feat(commands): implement adjust command and update readme accordingly
Browse files Browse the repository at this point in the history
Signed-off-by: simonsan <14062932+simonsan@users.noreply.github.com>
  • Loading branch information
simonsan committed Feb 29, 2024
1 parent 1e0e60f commit 6c039aa
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 55 deletions.
45 changes: 32 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ cargo install pace-rs
Currently they are stating the intended functionality and may not be fully
implemented yet (e.g. using activities instead of tasks).

🔍 **`pace setup`**
**`pace setup`**

- **Description:** Create configuration files for pace, including the main
configuration file and any additional settings. This is useful for setting up
Expand All @@ -142,49 +142,66 @@ implemented yet (e.g. using activities instead of tasks).
configuration file.
- **Usage:** `pace setup config` or `pace setup completions`

🔍 **`pace begin`**
**`pace adjust`**

- **Description:** Adjust the current activity's start time, description,
category, or tags. This is useful for correcting mistakes or adding more
detail to your activities.
- **Usage:**
`pace adjust --category <Category> --description <Description> --start <Start Time>`

**`pace begin`**

- **Description:** Starts tracking time for the specified task. You can
optionally specify a category or project to help organize your tasks.
- **Usage:** `pace begin "Design Work" --category "Freelance" --time 10:00`
- **Usage:** `pace begin "Design Work" --category "Freelance" --start 10:00`

🔍 **`pace end`**
**`pace end`**

- **Description:** Stops time tracking for the specified task, marking it as
completed or finished for the day.
- **Usage:** `pace end --time 11:30 --only-last`
- **Usage:** `pace end --end 11:30 --only-last`

**`pace docs`**

🔍 **`pace now`**
- **Description:** Opens the (dev-)documentation in your default browser.
- **Usage:** `pace docs` or `pace docs --dev`

**`pace now`**

- **Description:** Displays the currently running task, showing you at a glance
what you're currently tracking.
- **Usage:** `pace now`

🔍 **`pace hold`**
**`pace hold`**

- **Description:** Pauses the time tracking for the specified task. This is
useful for taking breaks without ending the task.
- **Usage:** `pace hold` or `pace hold "Design Work"`
- **Usage:** `pace hold --reason <Reason>`

🔍 **`pace resume`**
**`pace resume`**

- **Description:** Resumes time tracking for a previously paused task, allowing
you to continue where you left off.
- **Usage:** `pace resume "Design Work"`
- **Usage:** `pace resume` or `pace resume --list`

⏲️ **`pace review`**

- **Description:** Gain insight in your activities and tasks. You can specify
the time frame for daily, weekly, or monthly insights.
- **Usage:** `pace review --weekly`
- **Usage:** tbd

**`pace help`**

- **Description:** Displays help information, offering quick access to command
usage and options.
- **Usage:** `pace help` or `pace <command> --help`
- **Usage:** `pace help`, `pace <command> --help`, or `pace help <command>`

<details>
<summary>Some Ideas For Additional Useful Commands</summary>

### Ideas For Additional Useful Commands
**Note:** These commands are not yet implemented and are subject change to
during their design process.

💡 **`pace export --json/--csv`**

Expand Down Expand Up @@ -216,6 +233,8 @@ implemented yet (e.g. using activities instead of tasks).
lengths and preferred review formats.
- **Usage:** `pace set --work 25 --break 5`

</details>

## Contributing

Found a bug? [Open an issue!](https://github.com/pace-rs/pace/issues/new/choose)
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod adjust;
pub mod begin;
pub mod docs;
pub mod end;
Expand Down
119 changes: 119 additions & 0 deletions crates/core/src/commands/adjust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use std::collections::HashSet;

use chrono::{NaiveDateTime, NaiveTime};
#[cfg(feature = "clap")]
use clap::Parser;
use getset::Getters;
use typed_builder::TypedBuilder;

use crate::{
error::ActivityLogErrorKind, get_storage_from_config, ActivityQuerying, ActivityStore,
ActivityWriteOps, PaceConfig, PaceDateTime, PaceResult, SyncStorage, UpdateOptions,
};

/// `adjust` subcommand options
#[derive(Debug, Clone, PartialEq, TypedBuilder, Eq, Hash, Default, Getters)]
#[getset(get = "pub")]
#[non_exhaustive]
#[cfg_attr(feature = "clap", derive(Parser))]
#[cfg_attr(
feature = "clap", clap(group = clap::ArgGroup::new("adjust").multiple(true).required(true)))]
pub struct AdjustCommandOptions {
/// The category for the activity
#[cfg_attr(
feature = "clap",
clap(short, long, group = "adjust", name = "Category", alias = "at")
)]
category: Option<String>,

/// The description of the activity
#[cfg_attr(
feature = "clap",
clap(short, long, group = "adjust", name = "Description", alias = "desc")
)]
description: Option<String>,

/// The start time of the activity. Format: HH:MM
#[cfg_attr(
feature = "clap",
clap(short, long, group = "adjust", name = "Start Time", alias = "begin")
)]
start: Option<NaiveTime>,

/// Tags for the activity
#[cfg_attr(
feature = "clap",
clap(
short,
long,
group = "adjust",
name = "Tags",
alias = "tag",
value_delimiter = ','
)
)]
tags: Option<Vec<String>>,

#[cfg_attr(
feature = "clap",
clap(
short,
long,
group = "adjust",
requires = "Tags",
name = "Override Tags",
alias = "otag"
)
)]
override_tags: bool,
}

impl AdjustCommandOptions {
pub fn handle_adjust(&self, config: &PaceConfig) -> PaceResult<()> {
let activity_store = ActivityStore::new(get_storage_from_config(config)?);

let activity_item = activity_store
.most_recent_active_activity()?
.ok_or_else(|| ActivityLogErrorKind::NoActiveActivityToAdjust)?;

let guid = *activity_item.guid();
let mut activity = activity_item.activity().clone();

_ = activity.set_category(self.category.clone());

if let Some(description) = &self.description {
_ = activity.set_description(description.clone());
}

if let Some(start) = &self.start {
let start_time =
PaceDateTime::new(NaiveDateTime::new(*activity.begin().date(), *start));
_ = activity.set_begin(start_time);
}

if let Some(tags) = &self.tags {
let tags = tags.iter().cloned().collect::<HashSet<String>>();

if self.override_tags {
_ = activity.set_tags(Some(tags.clone()));
} else {
let merged_tags = activity.tags_mut().as_mut().map_or_else(
|| tags.clone(),
|existing_tags| existing_tags.union(&tags).cloned().collect(),
);
_ = activity.set_tags(Some(merged_tags));
}
}

_ = activity_store.update_activity(guid, activity.clone(), UpdateOptions::default())?;

if activity_item.activity() != &activity {
activity_store.sync()?;
println!("{} has been adjusted.", activity);
} else {
println!("No changes were made.");
}

Ok(())
}
}
4 changes: 2 additions & 2 deletions crates/core/src/commands/begin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
ActivityStore, PaceConfig, PaceResult, SyncStorage,
};

/// `begin` subcommand
/// `begin` subcommand options
#[derive(Debug)]
#[cfg_attr(feature = "clap", derive(Parser))]
pub struct BeginCommandOptions {
Expand All @@ -31,7 +31,7 @@ pub struct BeginCommandOptions {
/// The tags you want to associate with the activity, separated by a comma
#[cfg_attr(
feature = "clap",
clap(short, long, name = "Tag", value_delimiter = ',')
clap(short, long, name = "Tags", alias = "tag", value_delimiter = ',')
)]
tags: Option<Vec<String>>,

Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/commands/docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use clap::Parser;

use crate::{constants::PACE_DEV_DOCS_URL, constants::PACE_DOCS_URL, PaceResult};

/// Opens the documentation.
/// `docs` subcommand options
#[derive(Debug, Clone)]
#[cfg_attr(feature = "clap", derive(Parser))]
pub struct DocsCommandOptions {
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/commands/end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
EndOptions, PaceConfig, PaceResult, SyncStorage,
};

/// `end` subcommand
/// `end` subcommand options
#[derive(Debug, Clone, PartialEq, TypedBuilder, Eq, Hash, Default, Getters)]
#[getset(get = "pub")]
#[non_exhaustive]
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/commands/hold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
IntermissionAction, PaceConfig, PaceDateTime, PaceResult, SyncStorage,
};

/// `hold` subcommand>
/// `hold` subcommand options
#[derive(Debug)]
#[cfg_attr(feature = "clap", derive(Parser))]
pub struct HoldCommandOptions {
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/commands/now.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
ActivityStore, PaceConfig, PaceResult,
};

/// `now` subcommand
/// `now` subcommand options
#[derive(Debug)]
#[cfg_attr(feature = "clap", derive(Parser))]
pub struct NowCommandOptions {}
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/commands/resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use typed_builder::TypedBuilder;

use crate::PaceDateTime;

/// `resume` subcommand
/// `resume` subcommand options
#[derive(Debug, Getters, TypedBuilder, Clone, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "clap", derive(Parser))]
pub struct ResumeCommandOptions {
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/commands/review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
ActivityKind, ActivityStore, ActivityTracker, PaceConfig, PaceResult,
};

/// `review` subcommand options
#[derive(Debug, Getters)]
#[getset(get = "pub")]
#[cfg_attr(feature = "clap", derive(Parser))]
Expand Down
7 changes: 2 additions & 5 deletions crates/core/src/domain/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,7 @@ pub struct Activity {
/// The start date and time of the activity
#[builder(default, setter(into))]
#[getset(get = "pub")]
#[merge(skip)]
// The begin time should be immutable, because it's the start of the activity
// and should not be changed. We may reconsider that if there is any use case for that.
#[merge(strategy = crate::util::overwrite_left_with_right)]
begin: PaceDateTime,

#[builder(default)]
Expand All @@ -228,8 +226,7 @@ pub struct Activity {

/// Tags for the activity
#[builder(default, setter(into))]
#[merge(skip)]
// We
#[merge(strategy = crate::util::overwrite_left_with_right)]
tags: Option<HashSet<String>>,

// Pomodoro-specific attributes
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ pub enum ActivityLogErrorKind {
ParentIdNotSet(ActivityGuid),
/// Category not set for activity with id '{0}'
CategoryNotSet(ActivityGuid),
/// No active activity to adjust
NoActiveActivityToAdjust,
}

trait PaceErrorMarker: Error {}
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub use toml;
// Public API
pub use crate::{
commands::{
adjust::AdjustCommandOptions,
begin::BeginCommandOptions,
docs::DocsCommandOptions,
end::EndCommandOptions,
Expand Down
Loading

0 comments on commit 6c039aa

Please sign in to comment.