Skip to content

Commit

Permalink
Add support for JSON output format
Browse files Browse the repository at this point in the history
  • Loading branch information
jkallio committed Jan 16, 2024
1 parent 2695599 commit 73bc535
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pomodoro-cli"
version = "1.0.0"
version = "1.1.0"
authors = ["Jussi Kallio <jkallio@gmail.com>"]
license = "MIT"
description = "A simple command line Pomodoro timer."
Expand Down
93 changes: 59 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Pomodoro timer is a simple timer that helps you to stay focused on your tasks.

### Download binary

- [pomodoro cli (v.1.0.0)](https://github.com/jkallio/pomodoro-cli/releases/tag/v1.0)
- [pomodoro cli (v.1.1.0)](https://github.com/jkallio/pomodoro-cli/releases/tag/v1.1.0)

### Cargo

Expand Down Expand Up @@ -59,6 +59,13 @@ $ pomodoro-cli stop
$ pomodoro-cli pause
```

### Add more time to a running timer

```bash
# Call start again while the timer is running to add more time to the timer
$ pomodoro-cli start --duration 5m
```

### Query the timer status

```bash
Expand All @@ -67,6 +74,56 @@ $ pomodoro-cli status --format seconds

## Get remaining time in human readable format
$ pomodoro-cli status --format human

# Get the timer status in JSON format (for Waybar integration)
$ pomodoro-cli status --format json
```

# Waybar integration

![Waybar](./assets/screenshot_waybar.png)

Add the following module to your waybar configuration:

```json
"custom/pomo": {
"format": "  {}",
"exec": "pomodoro-cli status --format json",
"return-type": "json",
"on-click": "pomodoro-cli start --duration 5m --notify",
"on-click-middle": "pomodoro-cli pause",
"on-click-right": "pomodoro-cli stop",
"interval": 1
},
```

### CSS styling

The module supports three different states: `running`, `paused` and `stopped`. You can customize the styling of each state by adding the following CSS rules to your Waybar configuration:

```css
#custom-pomo.finished {
background: #8F0808;
}

#custom-pomo.running {
background: #304D30;
}

#custom-pomo.paused {
background: #AB730A;
}
```

### Update Waybar module immediately

If you want to signal Waybar to update the module immediately when you can add `pkill -SIGRTMIN+10 waybar` to the `on-click` commands. For example:

```json
"custom/pomo": {
on-click": "pomodoro-cli start --duration 5m; pkill -SIGRTMIN+10 waybar",
signal": 10,
}
```

# Customization
Expand All @@ -91,41 +148,9 @@ $ mkdir -p ~/.config/pomodoro-cli
$ cp /path/to/icon.png ~/.config/pomodoro-cli/icon.png
```

# Waybar integration

Add the following module to your waybar configuration:

![Waybar](./assets/screenshot_waybar.png)

```json
"custom/pomodoro": {
"format": "  {}",
"tooltip": false,
"exec": "pomodoro-cli status --format human",
"on-click": "pomodoro-cli start --duration 5m",
"on-click-middle": "pomodoro-cli pause",
"on-click-right": "pomodoro-cli stop",
"interval": 1
}
```

If you want to signal Waybar to update the module immediately when you click it, change use the following configuration:

```json
"custom/pomo": {
"format": "  {}",
"tooltip": false,
"exec": "pomodoro-cli status --format human",
"signal": 10,
"on-click": "pomodoro-cli start --duration 5m; pkill -SIGRTMIN+10 waybar",
"on-click-middle": "pomodoro-cli pause; pkill -SIGRTMIN+10 waybar",
"on-click-right": "pomodoro-cli stop; pkill -SIGRTMIN+10 waybar",
"interval": 1
}
```

# Alternatives

- [i3-gnome-pomodoro](https://github.com/kantord/i3-gnome-pomodoro)
- [openpomodoro-cli](https://github.com/open-pomodoro/openpomodoro-cli)
- [rust-cli-pomodoro](https://crates.io/crates/rust-cli-pomodoro)
- [pomo](https://kevinschoon.github.io/pomo/)
Binary file modified assets/screenshot_waybar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 19 additions & 29 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ pub fn run(args: &Cli) {
stop_timer();
}
SubCommand::Status { format } => {
let format = match *format {
Some(StatusFormat::Human) => StatusFormat::Human,
_ => StatusFormat::Seconds,
};
get_status(format);
let status = get_status(*format);
println!("{}", status);
}
}
}
Expand Down Expand Up @@ -108,35 +105,28 @@ pub fn trigger_alarm(timer_info: &TimerInfo) {
}

/// Return the status of the timer in the given format.
pub fn get_status(format: StatusFormat) {
pub fn get_status(format: Option<StatusFormat>) -> String {
let timer_info = TimerInfo::from_file();
let elapsed = timer_info.get_time_elapsed();

match timer_info.state {
TimerState::Finished => {
println!("Finished");
}
TimerState::Paused => {
println!(
let status: String = match format {
Some(StatusFormat::Human) => match timer_info.state {
TimerState::Finished => "Finished".to_string(),
TimerState::Paused => format!(
"Paused ({} left)",
get_human_readable_time(timer_info.get_time_left())
);
return;
}
TimerState::Running => {
if elapsed >= timer_info.duration {
stop_timer();
trigger_alarm(&timer_info);
return;
}
match format {
StatusFormat::Human => {
println!("{}", get_human_readable_time(timer_info.get_time_left()))
}
StatusFormat::Seconds => {
println!("{}", timer_info.get_time_left());
}
),
TimerState::Running => {
format!("{}", get_human_readable_time(timer_info.get_time_left()))
}
}
},
Some(StatusFormat::Json) => format!("{}", timer_info.get_json_info()),
_ => format!("{}", timer_info.get_time_left()),
};

if timer_info.is_running() && elapsed >= timer_info.duration {
stop_timer();
trigger_alarm(&timer_info);
}
return status;
}
5 changes: 3 additions & 2 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::Serialize;
#[derive(Parser, Debug)]
#[clap(
name = "Pomodoro CLI",
version = "1.0.0",
version = "1.1.0",
author = "Jussi Kallio",
about = "Pomodoro timer is a simple timer that helps you to stay focused on your task."
)]
Expand Down Expand Up @@ -43,10 +43,11 @@ pub enum SubCommand {
}

/// Defines the returned time format for the status command
#[derive(clap::ValueEnum, Clone, Default, Debug, Serialize)]
#[derive(clap::ValueEnum, Clone, Default, Debug, Serialize, Copy)]
#[serde(rename_all = "lowercase")]
pub enum StatusFormat {
#[default]
Seconds,
Human,
Json,
}
41 changes: 41 additions & 0 deletions src/timer_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ pub struct TimerInfo {
pub notify: bool,
}

#[derive(Serialize)]
pub struct WaybarTimerInfo {
pub text: String,
pub tooltip: String,
pub class: String,
pub percentage: f64,
}

/// Implement default for TimerInfo
impl Default for TimerInfo {
fn default() -> Self {
Expand Down Expand Up @@ -64,6 +72,39 @@ impl TimerInfo {
self.duration - self.get_time_elapsed()
}

/// Returns the info in Waybar JSON format.
pub fn get_json_info(&self) -> String {
let time_left = self.get_time_left();
let percentage = (time_left as f64 / self.duration as f64) * 100.0;
let text = get_human_readable_time(time_left);
let tooltip = match self.state {
TimerState::Running => format!(
"Running\nLeft: {}\nElapsed: {} ",
get_human_readable_time(self.get_time_left()),
get_human_readable_time(self.get_time_elapsed())
),
TimerState::Paused => format!(
"Paused\nLeft: {}\nElapsed: {} ",
get_human_readable_time(self.get_time_left()),
get_human_readable_time(self.get_time_elapsed())
),
TimerState::Finished => "Finished".to_string(),
}
.to_string();
let class = match self.state {
TimerState::Running => "running",
TimerState::Paused => "paused",
TimerState::Finished => "finished",
};
let waybar_info = WaybarTimerInfo {
text,
tooltip,
class: class.to_string(),
percentage,
};
serde_json::to_string(&waybar_info).unwrap()
}

/// Returns the time elapsed since start in seconds.
pub fn get_time_elapsed(&self) -> i64 {
match self.state {
Expand Down

0 comments on commit 73bc535

Please sign in to comment.