Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(setup): rename craft command to setup #53

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ directories = "5.0.1"
eyre = { workspace = true }
human-panic = "1.2.3"
insta = { version = "1.35.1", features = ["toml"] }
open = "5.0.2"
pace_cli = { workspace = true }
pace_core = { workspace = true }
serde = "1"
Expand Down
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ 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 craft`**
🔍 **`pace setup`**

- **Description:** Craft configuration files for pace, including the main
- **Description:** Create configuration files for pace, including the main
configuration file and any additional settings. This is useful for setting up
pace for the first time or when you need to change your settings. You can also
generate shell completions for your shell of choice. And generate a project
configuration file.
- **Usage:** `pace craft setup`
- **Usage:** `pace setup config` or `pace setup completions`

🔍 **`pace begin`**

Expand Down Expand Up @@ -223,6 +223,16 @@ Got an idea for an improvement? Don't keep it to yourself!
Please make sure, that you read the
[contribution guide](https://pace.cli.rs/docs/contributing_to_pace.html).

## Acknowledgements

Some of the inspiration for `pace` came from the following projects:

- [bartib](https://github.com/nikolassv/bartib)
- [Super Productivity](https://github.com/johannesjo/super-productivity)
- [timetracking](https://github.com/hardliner66/timetracking)
- [vayu](https://github.com/MythicalCow/vayu)
- [work-break](https://github.com/ShadoySV/work-break)

## Minimum Rust version policy

This crate's minimum supported `rustc` version is `1.74.1`.
Expand Down
7 changes: 5 additions & 2 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

/// Contains the main logic for prompting the user for input
pub(crate) mod prompt;
/// Contains the main logic for the `craft setup` command
/// Contains the main logic for the `setup` command
pub(crate) mod setup;

// Public API
pub use crate::{prompt::confirmation_or_break, setup::craft_setup};
pub use crate::{
prompt::confirmation_or_break,
setup::{setup_config, PathOptions},
};
8 changes: 4 additions & 4 deletions crates/cli/src/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub(crate) fn prompt_activity_log_path(activity_log_paths: &[String]) -> Result<
let selected_activity_log_path = match selection {
Some(index) => PathBuf::from(activity_log_paths[index].clone()),
None => {
eyre::bail!("Exiting setup assistant.");
eyre::bail!("Setup exited without changes.");
}
};

Expand All @@ -40,7 +40,7 @@ pub(crate) fn prompt_activity_log_path(activity_log_paths: &[String]) -> Result<
p
} else {
debug!("No parent directory for activity log file.");
eyre::bail!("Exiting setup assistant. No changes were made.");
eyre::bail!("Setup exited without changes. No changes were made.");
};

Ok(FinalSetupPaths::builder()
Expand Down Expand Up @@ -78,7 +78,7 @@ pub(crate) fn prompt_config_file_path(
let selected_config_path = match selection {
Some(index) => PathBuf::from(config_paths[index].clone()),
None => {
eyre::bail!("Exiting setup assistant.");
eyre::bail!("Setup exited without changes.");
}
};

Expand All @@ -87,7 +87,7 @@ pub(crate) fn prompt_config_file_path(
p
} else {
debug!("No parent directory for config file.");
eyre::bail!("Exiting setup assistant. No changes were made.");
eyre::bail!("Setup exited without changes. No changes were made.");
};

_ = final_paths
Expand Down
48 changes: 27 additions & 21 deletions crates/cli/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ use pace_core::{

use crate::prompt::{prompt_activity_log_path, prompt_config_file_path};

#[derive(Debug, TypedBuilder, Getters)]
pub struct PathOptions {
/// Path to the activity log file
#[getset(get = "pub")]
activity_log: Option<PathBuf>,
}

/// Final paths for the configuration and activity log files
///
/// This struct is used to store the final paths for the configuration and activity log files
Expand Down Expand Up @@ -254,32 +261,25 @@ pub(crate) fn print_intro(term: &Term) -> Result<()> {
println!("{assistant_headline}");

let intro_text = r"
Welcome to pace, your time tracking tool!

Whether you're diving in for the first time or keen on refining your setup,
this assistant is here to seamlessly tailor your environment to your preferences.
Keep the pace on your command line. Time tracking and management.

Ready to shape your experience? Here’s how:
Use this assistant to setup your pace environment and preferences.

- Glide through options with UP and DOWN arrows.
- Hit ENTER to use the default choice (or use y/n) and stride to the next prompt.
- Use UP / Down arrows to choose options
- or Enter for default choice when applicable

Worried about commitment? Don’t be. We’re only locking in your preferences at the
journey’s end, giving you the freedom to experiment. And if you decide to bow out early,
no sweat — Q, ESC, or Ctrl-C will let you exit gracefully without a trace of change.

Let’s embark on this customization adventure together—press ENTER when you’re ready
to elevate your productivity with pace.";
Preferences will only be saved if you complete the setup.
Use Q, ESC, or Ctrl-C to exit gracefully at any time.";

println!("{intro_text}\n");

let confirmation = Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Do you want to continue?")
.with_prompt("Ready to start?")
.default(true)
.interact()?;

if !confirmation {
eyre::bail!("Exiting setup assistant.");
eyre::bail!("Setup exited without changes.");
}

Ok(())
Expand All @@ -306,13 +306,13 @@ pub(crate) fn confirmation_or_break(prompt: &str) -> Result<()> {
.interact()?;

if !confirmation {
eyre::bail!("Exiting setup assistant. No changes were made.");
eyre::bail!("Setup exited without changes. No changes were made.");
}

Ok(())
}

/// The `craft setup` commands interior for the pace application
/// The `setup` commands interior for the pace application
///
/// # Arguments
///
Expand All @@ -325,19 +325,25 @@ pub(crate) fn confirmation_or_break(prompt: &str) -> Result<()> {
/// # Returns
///
/// Returns `Ok(())` if the setup assistant succeeds
pub fn craft_setup(term: &Term) -> Result<()> {
pub fn setup_config(term: &Term, path_opts: PathOptions) -> Result<()> {
let mut config = PaceConfig::default();

let config_paths = get_config_paths(PACE_CONFIG_FILENAME)
.into_iter()
.map(|f| f.to_string_lossy().to_string())
.collect::<Vec<String>>();

let activity_log_paths = get_activity_log_paths(PACE_ACTIVITY_LOG_FILENAME)
let mut activity_log_paths = get_activity_log_paths(PACE_ACTIVITY_LOG_FILENAME)
.into_iter()
.map(|f| f.to_string_lossy().to_string())
.collect::<Vec<String>>();

// Add the custom path from the cli input to the activity log paths
if let Some(mut custom_path) = path_opts.activity_log().clone() {
custom_path.push(PACE_ACTIVITY_LOG_FILENAME);
activity_log_paths.push(custom_path.to_string_lossy().to_string());
}

print_intro(term)?;

term.clear_screen()?;
Expand All @@ -357,11 +363,11 @@ pub fn craft_setup(term: &Term) -> Result<()> {
write_activity_log(&final_paths)?;

let Some(config_root) = final_paths.config_root() else {
eyre::bail!("No config root. Exiting setup assistant.");
eyre::bail!("No config root. Setup exited without changes.");
};

let Some(config_path) = final_paths.config_path() else {
eyre::bail!("No config path. Exiting setup assistant.");
eyre::bail!("No config path. Setup exited without changes.");
};

write_config(&config, config_root, config_path)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub struct GeneralConfig {
pub struct ActivityLogOptions {
/// The path to the activity log file
/// Default is operating system dependent
/// Use `pace craft setup` to set this value initially
/// Use `pace setup config` to set this value initially
#[getset(get = "pub", get_mut = "pub")]
activity_log_path: PathBuf,

Expand Down
33 changes: 18 additions & 15 deletions crates/core/src/domain/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::fmt::Formatter;
use getset::{Getters, MutGetters, Setters};
use merge::Merge;
use serde_derive::{Deserialize, Serialize};
use std::fmt::Display;
use std::{collections::HashSet, fmt::Display};
use strum_macros::EnumString;
use typed_builder::TypedBuilder;
use ulid::Ulid;
Expand All @@ -19,7 +19,9 @@ use crate::{
PaceResult,
};

#[derive(Debug, TypedBuilder, Getters, Setters, MutGetters, Clone, Eq, PartialEq, Default)]
#[derive(
Debug, TypedBuilder, Serialize, Getters, Setters, MutGetters, Clone, Eq, PartialEq, Default,
)]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub struct ActivityItem {
guid: ActivityGuid,
Expand Down Expand Up @@ -179,11 +181,13 @@ enum PomodoroCycle {
)]
#[getset(get = "pub", set = "pub", get_mut = "pub")]
#[derive(Merge)]
// TODO: How to better support subcategories
// subcategory: Option<Category>,
/// The category of the activity
// TODO: We had it as a struct before with an ID, but it's questionable if we should go for this
// TODO: Reconsider when we implement the project management part
// category: Category,
pub struct Activity {
/// The category of the activity
// TODO: We had it as a struct before with an ID, but it's questionable if we should go for this
// TODO: Reconsider when we implement the project management part
// category: Category,
#[builder(default, setter(into))]
#[getset(get = "pub", get_mut = "pub")]
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -200,8 +204,9 @@ pub struct Activity {
/// The start date and time of the activity
#[builder(default, setter(into))]
#[getset(get = "pub")]
// TODO: Should the begin time be updatable?
#[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.
begin: PaceDateTime,

#[builder(default)]
Expand All @@ -221,14 +226,11 @@ pub struct Activity {
#[merge(strategy = crate::util::overwrite_left_with_right)]
activity_kind_options: Option<ActivityKindOptions>,

// TODO: How to better support subcategories
// subcategory: Option<Category>,

// TODO: Was `Tag` before, but we want to check how to better support that
// TODO: also, we should consider using a HashSet instead of a Vec
// TODO: also, we might want to reconsider
// #[builder(default, setter(strip_option))]
// tags: Option<Vec<String>>,
/// Tags for the activity
#[builder(default, setter(into))]
#[merge(skip)]
// We
tags: Option<HashSet<String>>,

// Pomodoro-specific attributes
/// The pomodoro cycle of the activity
Expand Down Expand Up @@ -358,6 +360,7 @@ impl Activity {
.kind(self.kind)
.activity_kind_options(self.activity_kind_options.clone())
.pomodoro_cycle_options(self.pomodoro_cycle_options)
.tags(self.tags.clone())
.build()
}

Expand Down
Loading
Loading