Compare commits
11 Commits
57142c6645
...
4d6ada502d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d6ada502d | ||
|
|
c624a111dc | ||
| da5d80a1c8 | |||
| e35a1eeda1 | |||
| dc18aaaf03 | |||
| 6b6919fed2 | |||
| 085973963a | |||
| 6664709189 | |||
| 11cbf9687e | |||
| 466d2807e6 | |||
|
|
b2c4547842 |
22
.github/workflows/rust.yml
vendored
Normal file
22
.github/workflows/rust.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "i3status-custom-pim"
|
||||
description = "Generates JSON output for use with custom block of i3status-rust."
|
||||
version = "0.1.0"
|
||||
authors = ["Martin Bley <martin@mb-oss.de>"]
|
||||
authors = ["Martin Bley <dev@mb-oss.de>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
65
README.md
65
README.md
@@ -1,3 +1,66 @@
|
||||
# i3status-custom-pim
|
||||
Generates JSON output for use with _custom_ block of [i3status-rust](https://github.com/greshake/i3status-rust)
|
||||

|
||||
|
||||
`i3status-custom-pim` is a tool to output JSON content for users of the [pimutils](https://github.com/pimutils)
|
||||
|
||||
- [khal](https://github.com/pimutils/khal) and
|
||||
- [todoman](https://github.com/pimutils/todoman).
|
||||
|
||||
The output can be used for the custom block of [i3status-rust](https://github.com/greshake/i3status-rust) to display events or due dates in the i3 status bar.
|
||||
|
||||
## Requirements
|
||||
In order to build a binary, you need the Rust language and the package manager `cargo`. And of course you need the pimutils [khal](https://github.com/pimutils/khal) and/or
|
||||
[todoman](https://github.com/pimutils/todoman). Please refer to the documentation on the project pages in order to install and configure these tools.
|
||||
|
||||
## Install
|
||||
There are no packaged versions yet, so you have to compile `i3status-cutom-pim` yourself.
|
||||
```
|
||||
$ cargo install --git https://github.com/theamma/i3status-custom-pim i3status-custom-pim
|
||||
```
|
||||
By default, this will install the binary to `~/.cargo/bin/i3status-custom-pim`. Please make sure, this is in your $PATH or copy the binary to an appropriate location (like `/usr/local/bin`).
|
||||
|
||||
You may also compile manually
|
||||
```
|
||||
$ git clone https://github.com/theamma/i3status-custom-pim
|
||||
$ cd i3status-custom-pim && cargo build --release
|
||||
```
|
||||
|
||||
## Configuration
|
||||
To add the blocks, add this to your i3status-rs configuration
|
||||
|
||||
```
|
||||
[[block]]
|
||||
block = "custom"
|
||||
command = ''' i3status-custom-pim -k '''
|
||||
json = true
|
||||
|
||||
[[block]]
|
||||
block = "custom"
|
||||
command = ''' i3status-custom-pim -t -i tasks -w 20160 -c 7200'''
|
||||
json = true
|
||||
```
|
||||
|
||||
Thresholds for *warning* or *critical* state can be given via commandline switches. In *warning* state the widget will change the background colour to orange, in *critical* state to red.
|
||||
|
||||
Please note: A due date has to be set for each task, otherwise the block will run into an error. This bug is addressed in issue #2.
|
||||
|
||||
Please run `i3status-custom-pim --help` for available options.
|
||||
```
|
||||
i3status-custom-pim 0.1.0
|
||||
Martin Bley <dev@mb-oss.de>
|
||||
Generates JSON output for use with custom block of i3status-rust.
|
||||
|
||||
USAGE:
|
||||
i3status-custom-pim [FLAGS] [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-k, --khal output khal events
|
||||
-t, --todo output todos
|
||||
-V, --version Prints version information
|
||||
|
||||
OPTIONS:
|
||||
-i, --icon <icon> the icon used (only names valid in i3status-rust) [default: calendar]
|
||||
-c <threshold-crit> threshold for critical status in minutes [default: 15]
|
||||
-w <threshold-warn> threshold for warning status in minutes [default: 60]
|
||||
```
|
||||
|
||||
BIN
img/example_bar.png
Normal file
BIN
img/example_bar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
79
src/main.rs
79
src/main.rs
@@ -1,4 +1,4 @@
|
||||
use chrono::{Local, NaiveTime};
|
||||
use chrono::{Local, NaiveDateTime, NaiveTime};
|
||||
use std::process;
|
||||
use std::process::Command;
|
||||
use structopt::StructOpt;
|
||||
@@ -38,34 +38,27 @@ struct Cli {
|
||||
#[derive(Debug)]
|
||||
enum Status {
|
||||
Idle,
|
||||
Warn,
|
||||
Crit,
|
||||
Warning,
|
||||
Critical,
|
||||
}
|
||||
|
||||
fn get_status(events: Vec<String>, w: i64, c: i64) -> Result<Status, String> {
|
||||
let now = Local::now().time();
|
||||
let mut event_remaining: i64 = 24 * 60;
|
||||
fn get_status(events: Vec<NaiveDateTime>, w: i64, c: i64) -> Result<Status, String> {
|
||||
let now = Local::now();
|
||||
let mut event_remaining: i64 = 365 * 24 * 60;
|
||||
let mut state = Status::Idle;
|
||||
|
||||
for e in events.iter() {
|
||||
let e_start = match NaiveTime::parse_from_str(e, "%H:%M") {
|
||||
Ok(s) => s,
|
||||
Err(f) => {
|
||||
let message = format!("error parsing time value: {}", f);
|
||||
return Err(message);
|
||||
}
|
||||
};
|
||||
let diff = e_start - now;
|
||||
let diff = *e - now.naive_local();
|
||||
if (diff.num_minutes() < event_remaining) && (diff.num_minutes() >= 0) {
|
||||
event_remaining = diff.num_minutes()
|
||||
}
|
||||
|
||||
if event_remaining >= 0 {
|
||||
if event_remaining <= w {
|
||||
state = Status::Warn;
|
||||
state = Status::Warning;
|
||||
}
|
||||
if event_remaining <= c {
|
||||
state = Status::Crit;
|
||||
state = Status::Critical;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +70,7 @@ fn main() {
|
||||
|
||||
if (!args.khal && !args.todo) || (args.khal && args.todo) {
|
||||
eprintln!("Please provide either khal or todo flag.");
|
||||
Cli::clap().print_help();
|
||||
Cli::clap().print_help().unwrap();
|
||||
println!();
|
||||
process::exit(1);
|
||||
}
|
||||
@@ -117,16 +110,20 @@ fn main() {
|
||||
|
||||
let dayline = match out_iter.nth(0) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
eprintln!("Output seems empty. Exiting");
|
||||
process::exit(1);
|
||||
}
|
||||
None => { "None" }
|
||||
};
|
||||
|
||||
let mut events: Vec<String> = Vec::new();
|
||||
let today = Local::today();
|
||||
let mut events: Vec<NaiveDateTime> = Vec::new();
|
||||
if dayline.trim() == "Today" {
|
||||
for e in out_iter {
|
||||
events.push(e.to_string());
|
||||
let event_start = match NaiveTime::parse_from_str(e, "%H:%M") {
|
||||
Ok(s) => s,
|
||||
Err(_f) => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
events.push(today.and_time(event_start).unwrap().naive_local());
|
||||
}
|
||||
}
|
||||
let count = events.len();
|
||||
@@ -143,9 +140,7 @@ fn main() {
|
||||
args.icon, state, count
|
||||
);
|
||||
} else if args.todo {
|
||||
let cmd = Command::new("todo")
|
||||
.arg("--porcelain")
|
||||
.output();
|
||||
let cmd = Command::new("todo").arg("--porcelain").output();
|
||||
|
||||
let stdout = match cmd {
|
||||
Ok(o) => o.stdout,
|
||||
@@ -163,28 +158,34 @@ fn main() {
|
||||
}
|
||||
};
|
||||
|
||||
let mut parsed = match json::parse(&output){
|
||||
let parsed = match json::parse(&output) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
eprintln!("parsing JSON failed: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let count = parsed.len();
|
||||
println!("{:#?}", count);
|
||||
//println!("{:#?}", count);
|
||||
|
||||
let mut tasks: Vec<String> = Vec::new();
|
||||
let mut tasks: Vec<NaiveDateTime> = Vec::new();
|
||||
for due in parsed.members() {
|
||||
tasks.push(due.as_str().unwrap().to_string());
|
||||
tasks.push(NaiveDateTime::from_timestamp(
|
||||
due["due"].as_i64().unwrap(),
|
||||
0,
|
||||
));
|
||||
}
|
||||
/*
|
||||
for i in parsed {
|
||||
i.foo();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
let state = match get_status(tasks, args.threshold_warn, args.threshold_crit) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
eprintln!("{}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
println!(
|
||||
"{{ \"icon\": \"{}\", \"state\": \"{:?}\", \"text\": \"{}\" }}",
|
||||
args.icon, state, count
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user