Skip to content

Commit 5f8ae20

Browse files
committed
Simplify get_current_timew_task
1 parent 0af6de2 commit 5f8ae20

File tree

1 file changed

+10
-34
lines changed

1 file changed

+10
-34
lines changed

src/blocks/timewarrior.rs

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub async fn run(config: Config, mut api: CommonApi) -> Result<()> {
6464
let mut state = State::Idle;
6565
let mut widget = widget.clone();
6666

67-
let data = process_timewarrior_data(&call_timewarrior().await?);
67+
let data = get_current_timewarrior_task().await?;
6868
if let Some(tw) = data {
6969
if tw.end.is_none() {
7070
// only show active tasks
@@ -126,7 +126,8 @@ struct TimewarriorRAW {
126126
}
127127

128128
/// TimeWarrior entry
129-
#[derive(Debug, PartialEq)]
129+
#[derive(Debug, PartialEq, Deserialize)]
130+
#[serde(from = "TimewarriorRAW")]
130131
struct TimewarriorData {
131132
pub id: u32,
132133
pub start: DateTime<chrono::offset::Utc>,
@@ -161,24 +162,24 @@ fn format_datetime(date: &DateTime<chrono::Utc>, format: &str) -> String {
161162
date.format(format).to_string()
162163
}
163164

164-
/// Execute "timew export now" and return the result
165-
async fn call_timewarrior() -> Result<String> {
165+
/// Execute "timew export now" and return the current task (if any)
166+
async fn get_current_timewarrior_task() -> Result<Option<TimewarriorData>> {
166167
let out = Command::new("timew")
167168
.args(["export", "now"])
168169
.output()
169170
.await
170171
.error("failed to run timewarrior")?
171172
.stdout;
172-
let output = std::str::from_utf8(&out)
173-
.error("failed to read output from timewarrior (invalid UTF-8)")?
174-
.trim();
175-
Ok(output.to_string())
173+
Ok(serde_json::from_slice::<Vec<TimewarriorData>>(&out)
174+
.unwrap_or_default()
175+
.into_iter()
176+
.next())
176177
}
177178

178179
/// Stop or continue a task
179180
async fn stop_continue() -> Result<()> {
180181
let mut execute_continue: bool = true;
181-
if let Some(tw) = process_timewarrior_data(&call_timewarrior().await?) {
182+
if let Some(tw) = get_current_timewarrior_task().await? {
182183
// we only execute continue if the current task is stopped
183184
// i.e. has an end defined
184185
execute_continue = tw.end.is_some();
@@ -200,28 +201,3 @@ async fn stop_continue() -> Result<()> {
200201
.error("Error executing stop/continue")
201202
.map(|_| ())
202203
}
203-
204-
/// Process the output from "timew export" and return the first entry
205-
fn process_timewarrior_data(input: &str) -> Option<TimewarriorData> {
206-
let t: Vec<TimewarriorRAW> = serde_json::from_str(input).unwrap_or_default();
207-
t.into_iter().next().map(TimewarriorData::from)
208-
}
209-
210-
#[cfg(test)]
211-
mod tests {
212-
use super::*;
213-
214-
#[test]
215-
fn test_process_timewarrior_data() {
216-
assert_eq!(process_timewarrior_data(""), None,);
217-
218-
assert_eq!(process_timewarrior_data("[]"), None,);
219-
220-
let a = process_timewarrior_data("[{\"id\":1,\"start\":\"20230131T175754Z\",\"tags\":[\"i3status\"],\"annotation\":\"timewarrior plugin\"}]");
221-
assert_eq!(a.is_some(), true);
222-
if let Some(b) = a {
223-
assert_eq!(b.id, 1);
224-
assert_eq!(b.end, None);
225-
}
226-
}
227-
}

0 commit comments

Comments
 (0)