Skip to content

Commit

Permalink
reintroduce commands
Browse files Browse the repository at this point in the history
  • Loading branch information
jbirnick committed Dec 28, 2024
1 parent 8cd90df commit 439a5ed
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 47 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
> This used to be a shell script. Now it is a binary.
> The CLI arguments have changed only slightly but the underlying architecture is completely different.
> Therefore, if you switch from the shell script version to the binary, please make sure to **fully adapt the new default config**.
> In particular you need to remove `interval`, set `exec-on-event` to false, change the actions of your timers to just names (no more actions), and change `increase -60` to `decrease 60`.
> In particular you need to add `tail` for `exec`, remove `interval`, set `exec-on-event` to false, and change `increase -60` to `decrease 60`.
This script implements a **simple** and **interactive** timer for your bar:
- e.g. scroll to increase / decrease timer
Expand Down Expand Up @@ -47,10 +47,10 @@ Use cases: pomodoro timer, self-reminder when next meeting begins, tea/pasta tim
"running": "RUNNING",
"paused": "PAUSE"
},
"on-click": "/path/to/waybar-timer new 25 Pomodoro",
"on-click": "/path/to/waybar-timer new 25 'notify-send \"Session finished\"'",
"on-click-middle": "/path/to/waybar-timer cancel",
"on-click-right": "/path/to/waybar-timer togglepause",
"on-scroll-up": "/path/to/waybar-timer increase 60 || /path/to/waybar-timer new 1",
"on-scroll-up": "/path/to/waybar-timer increase 60 || /path/to/waybar-timer new 'notify-send -u critical \"Timer expired\"'",
"on-scroll-down": "/path/to/waybar-timer decrease 60"
}
```
Expand Down Expand Up @@ -87,8 +87,9 @@ The main command of the script is:

Now the following commands allow you to control the timer.

- #### `new <MINUTES> [NAME]`
- #### `new <MINUTES> [COMMAND]`
Creates a new timer of length `MINUTES` minutes.
If you specify `COMMAND`, it will be executed (within a bash shell) when the timer finishes.

- #### `increase <SECONDS>`
Extend the current timer by `SECONDS` seconds.
Expand All @@ -101,14 +102,15 @@ Now the following commands allow you to control the timer.

- #### `cancel`
Cancel the current timer.
The specified `COMMAND` will _not_ be executed.

## Tips & Tricks

When there is no timer active, then [`increase`](#increase-seconds) does nothing, i.e. it doesn't change the state of the timer.
However, you might want it to _start a new timer_.
You can implement this because `increase` will exit with code 1 when there is no current timer, so you can do:
```
waybar-timer increase 60 || waybar-timer new 1'
waybar-timer increase 60 || waybar-timer new 1 'notify-send "Timer expired."'
```
Then if there is an existing timer it gets increased, otherwise a new one minute timer is created.
This is also implemented in the [example configuration](#example-configuration).
Expand Down
81 changes: 39 additions & 42 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@ const SOCKET_PATH: &str = "/tmp/waybar_timer.sock";
//const SOCKET_PATH: &str = "mysocket";
const INTERVAL: std::time::Duration = std::time::Duration::from_secs(1);

fn send_notification(summary: String, critical: bool) {
fn send_notification(summary: String) {
let _ = notify_rust::Notification::new()
.appname("Waybar Timer")
.id(12345)
.summary(&summary)
.urgency(match critical {
true => notify_rust::Urgency::Critical,
false => notify_rust::Urgency::Low,
})
.urgency(notify_rust::Urgency::Low)
.show();
}

Expand All @@ -40,7 +37,7 @@ impl Error for WorldError {}
#[serde_dispatch]
trait World {
fn cancel(&mut self) -> Result<(), WorldError>;
fn start(&mut self, minutes: u32, name: Option<String>) -> Result<(), WorldError>;
fn start(&mut self, minutes: u32, command: Option<String>) -> Result<(), WorldError>;
fn increase(&mut self, seconds: i64) -> Result<(), WorldError>;
fn togglepause(&mut self) -> Result<(), WorldError>;
}
Expand All @@ -50,11 +47,11 @@ enum Timer {
Idle,
Running {
expiry: OffsetDateTime,
name: Option<String>,
command: Option<String>,
},
Paused {
time_left: Duration,
name: Option<String>,
command: Option<String>,
},
}

Expand All @@ -64,49 +61,43 @@ impl Timer {
let now = OffsetDateTime::now_local().unwrap();

// check if timer expired
if let Self::Running { expiry, name } = self {
if let Self::Running { expiry, command } = self {
let time_left = *expiry - now;
if time_left <= Duration::ZERO {
// timer has expired, send notification and set timer to idle
let summary = match name {
Some(name) => format!("Timer '{name}' expired"),
None => "Timer expired".into(),
};
send_notification(summary, true);
if let Some(command) = command {
let _ = std::process::Command::new("bash")
.arg("-c")
.arg(command)
.output();
}
*self = Timer::Idle;
}
}

// print new output to stdout (for waybar)
let (text, alt, tooltip) = match self {
Self::Idle => (0, "standby", "No timer set".into()),
Self::Running { expiry, name } => {
Self::Running { expiry, .. } => {
let time_left = *expiry - now;
let minutes_left = time_left.whole_minutes() + 1;
let tooltip = Self::tooltip(name, expiry);
let tooltip = Self::tooltip(expiry);
(minutes_left, "running", tooltip)
}
Self::Paused { time_left, name } => {
Self::Paused { time_left, .. } => {
let minutes_left = time_left.whole_minutes() + 1;
let tooltip = match name {
Some(name) => format!("Timer '{name}' paused"),
None => "Timer paused".into(),
};
let tooltip = "Timer paused".into();
(minutes_left, "paused", tooltip)
}
};
println!("{{\"text\": \"{text}\", \"alt\": \"{alt}\", \"tooltip\": \"{tooltip}\", \"class\": \"timer\"}}");
std::io::stdout().flush()
}

fn tooltip(name: &Option<String>, expiry: &OffsetDateTime) -> String {
fn tooltip(expiry: &OffsetDateTime) -> String {
let format_desc = time::macros::format_description!("[hour]:[minute]");
let expiry_str = expiry.format(&format_desc).unwrap();

match name {
Some(name) => format!("Timer '{name}' expires at {expiry_str}"),
None => format!("Timer expires at {expiry_str}"),
}
format!("Timer expires at {expiry_str}")
}
}

Expand All @@ -116,14 +107,14 @@ impl World for Timer {
Ok(())
}

fn start(&mut self, minutes: u32, name: Option<String>) -> Result<(), WorldError> {
fn start(&mut self, minutes: u32, command: Option<String>) -> Result<(), WorldError> {
match self {
Self::Idle => {
let expiry = OffsetDateTime::now_local().unwrap()
+ Duration::minutes(minutes.into())
- Duration::MILLISECOND;
send_notification(Self::tooltip(&name, &expiry), false);
*self = Self::Running { expiry, name };
send_notification(Self::tooltip(&expiry));
*self = Self::Running { expiry, command };
Ok(())
}
Self::Paused { .. } | Self::Running { .. } => Err(WorldError::TimerAlreadyExisting),
Expand All @@ -132,12 +123,15 @@ impl World for Timer {

fn increase(&mut self, seconds: i64) -> Result<(), WorldError> {
match self {
Self::Running { expiry, name } => {
Self::Running { expiry, .. } => {
*expiry += Duration::seconds(seconds);
send_notification(Self::tooltip(name, expiry), false);
send_notification(Self::tooltip(expiry));
Ok(())
}
Self::Paused { time_left, name: _ } => {
Self::Paused {
time_left,
command: _,
} => {
*time_left += Duration::seconds(seconds);
Ok(())
}
Expand All @@ -147,21 +141,21 @@ impl World for Timer {

fn togglepause(&mut self) -> Result<(), WorldError> {
match self {
Self::Running { expiry, name } => {
Self::Running { expiry, command } => {
let time_left = *expiry - OffsetDateTime::now_local().unwrap();
send_notification(Self::tooltip(name, expiry), false);
send_notification(Self::tooltip(expiry));
*self = Self::Paused {
time_left,
name: name.take(),
command: command.take(),
};
Ok(())
}
Self::Paused { time_left, name } => {
Self::Paused { time_left, command } => {
let expiry = OffsetDateTime::now_local().unwrap() + *time_left;
send_notification(Self::tooltip(name, &expiry), false);
send_notification(Self::tooltip(&expiry));
*self = Self::Running {
expiry,
name: name.take(),
command: command.take(),
};
Ok(())
}
Expand All @@ -176,7 +170,10 @@ enum Args {
/// Start a server process (should be from within waybar)
Tail,
/// Start a new timer
New { minutes: u32, name: Option<String> },
New {
minutes: u32,
command: Option<String>,
},
/// Increase the current timer
Increase { seconds: u32 },
/// Decrease the current timer
Expand All @@ -194,9 +191,9 @@ fn main() -> Result<(), Box<dyn Error>> {
run_tail();
Ok(())
}
Args::New { minutes, name } => {
Args::New { minutes, command } => {
let stream = UnixStream::connect(SOCKET_PATH)?;
WorldRPCClient::call_with(&stream, &stream).start(&minutes, &name)??;
WorldRPCClient::call_with(&stream, &stream).start(&minutes, &command)??;
stream.shutdown(std::net::Shutdown::Both)?;
Ok(())
}
Expand Down

0 comments on commit 439a5ed

Please sign in to comment.