-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,830 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,309 @@ | ||
# YaGoStatus | ||
Yet Another i3status replacement written in Go. | ||
|
||
## Installation | ||
|
||
go get github.com/burik666/yagostatus | ||
cp $GOPATH/src/github.com/burik666/yagostatus/yagostatus.yml ~/.config/i3/yagostatus.yml | ||
|
||
Get the absolute path to the yagostatus binary: | ||
|
||
$ echo $GOPATH/bin/yagostatus | ||
/home/burik/go/bin/yagostatus | ||
|
||
|
||
Replace `status_command` to `/home/burik/go/bin/yagostatus` in your i3 config file (`$GOPATH` in `status_command` is empty). | ||
|
||
### Troubleshooting | ||
Yagostatus outputs error messages in stderr, you can log them by redirecting stderr to a file. | ||
|
||
`status_command /home/burik//go/bin/yagostatus 2> /tmp/yagostatus.log` | ||
|
||
## Configuration | ||
|
||
Yagostatus uses a configuration file in the yaml format. | ||
|
||
Example: | ||
```yml | ||
widgets: | ||
- widget: static | ||
blocks: > | ||
[ | ||
{ | ||
"full_text": "YaGoStatus", | ||
"color": "#2e9ef4" | ||
} | ||
] | ||
events: | ||
- button: 1 | ||
command: xdg-open https://github.com/burik666/yagostatus/ | ||
|
||
- widget: wrapper | ||
command: /usr/bin/i3status | ||
|
||
- widget: clock | ||
format: Jan _2 Mon 15:04:05 # https://golang.org/pkg/time/#Time.Format | ||
template: > | ||
{ | ||
"color": "#ffffff", | ||
"separator": true, | ||
"separator_block_width": 20 | ||
} | ||
``` | ||
## Widgets | ||
### Common parameters | ||
- `widget` - Widget name. | ||
- `template` - The template that is applied to the output of the widget. | ||
- `events` - List of commands to be executed on user actions. | ||
* `button` - X11 button ID (0 for any, 1 to 3 for left/middle/right mouse button. 4/5 for mouse wheel up/down. Default: `0`). | ||
* `command` - Command to execute (via `sh -c`). | ||
Сlick_event json will be written to stdin. | ||
Also env variables are available: `$I3_NAME`, `$I3_INSTANCE`, `$I3_BUTTON`, `$I3_X`, `$I3_Y`. | ||
* `output` - If `true` widget text will be replaced with the command output (default: `false`). | ||
* `name` - Filter by `name` for widgets with multiple blocks (default: empty). | ||
* `instance` - Filter by `instance` for widgets with multiple blocks (default: empty). | ||
|
||
Example: | ||
```yml | ||
- widget: static | ||
blocks: > | ||
[ | ||
{ | ||
"full_text": "Firefox", | ||
"name": "ff" | ||
}, | ||
{ | ||
"full_text": "Chrome", | ||
"name": "ch" | ||
} | ||
] | ||
template: > | ||
{ | ||
"color": "#0000ff" | ||
} | ||
events: | ||
- button: 1 | ||
command: /usr/bin/firefox | ||
name: ff | ||
- button: 1 | ||
command: /usr/bin/chrome | ||
name: ch | ||
``` | ||
|
||
|
||
### Widget `clock` | ||
|
||
The clock widget returns the current time in the specified format. | ||
|
||
- `format` - Time format (https://golang.org/pkg/time/#Time.Format). | ||
- `interval` - Clock update interval in seconds (default: `1`). | ||
|
||
|
||
### Widget `exec` | ||
|
||
This widget runs the command at the specified interval. | ||
|
||
- `command` - Command to execute (via `sh -c`). | ||
- `interval` - Update interval in seconds (set 0 to run once at start). | ||
- `events_update` - Update widget if an event occurred (default: `false`). | ||
|
||
|
||
### Widget `wrapper` | ||
|
||
The wrapper widget starts the command and proxy received blocks (and click_events). | ||
See: https://i3wm.org/docs/i3bar-protocol.html | ||
|
||
- `command` - Command to execute. | ||
|
||
|
||
### Widget `static` | ||
|
||
The static widget renders the blocks. Useful for labels and buttons. | ||
|
||
- `blocks` - JSON List of i3bar blocks. | ||
|
||
|
||
### Widget `http` | ||
|
||
The http widget starts http server and accept HTTP or Websocket requests. | ||
|
||
- `listen` - Address and port for binding (example: `localhost:9900`). | ||
- `path` - Path for receiving requests (example: `/mystatus/`). | ||
Must be unique for multiple widgets with same `listen`. | ||
|
||
For example, you can update the widget with the following command: | ||
|
||
curl http://localhost:9900/mystatus/ -d '[{"full_text": "hello"}, {"full_text": "world"}]' | ||
|
||
Send an empty array to clear: | ||
|
||
curl http://localhost:9900/mystatus/ -d '[]' | ||
|
||
|
||
## Examples | ||
|
||
### Volume control | ||
```yml | ||
- widget: exec | ||
command: | | ||
res=($(amixer get Master|grep -Eo '\[[0-9]+%\] \[(on|off)\]'|head -n1|tr -d "[]")) | ||
color="#ffffff" | ||
if [ "${res[1]}" = "off" ]; then | ||
color="#ff0000" | ||
fi | ||
echo -e '[{"full_text": "<span font_family=\"Symbola\">\xF0\x9F\x94\x8A</span> '${res[0]}'", "color": "'$color'"}]' | ||
interval: 0 | ||
events_update: true | ||
events: | ||
- button: 1 | ||
command: amixer -q set Master toggle | ||
- button: 4 | ||
command: amixer -q set Master 3%+ | ||
- button: 5 | ||
command: amixer -q set Master 3%- | ||
template: > | ||
{ | ||
"markup": "pango", | ||
"separator": true, | ||
"separator_block_width": 20 | ||
} | ||
``` | ||
|
||
### Weather | ||
|
||
To get access to weather API you need an APIID. | ||
See https://openweathermap.org/appid for details. | ||
|
||
Requires [jq](https://stedolan.github.com/jq/) for json parsing. | ||
|
||
```yml | ||
- widget: static | ||
blocks: > | ||
[ | ||
{ | ||
"full_text": "Weather:", | ||
"color": "#2e9ef4", | ||
"separator": false | ||
} | ||
] | ||
- widget: exec | ||
command: curl -s 'http://api.openweathermap.org/data/2.5/weather?q=London,uk&units=metric&appid=<APPID>'|jq .main.temp | ||
interval: 300 | ||
template: > | ||
{ | ||
"separator": true, | ||
"separator_block_width": 20 | ||
} | ||
``` | ||
|
||
### Conky | ||
|
||
```yml | ||
- widget: wrapper | ||
command: /usr/bin/conky -c /home/burik/.config/i3/conky.conf | ||
``` | ||
Specify the full path to `conky.conf`. | ||
|
||
**conky.conf** (conky 1.10 or higher): | ||
```lua | ||
conky.config = { | ||
out_to_x = false, | ||
own_window = false, | ||
out_to_console = true, | ||
background = false, | ||
max_text_width = 0, | ||
-- Update interval in seconds | ||
update_interval = 1.0, | ||
-- This is the number of times Conky will update before quitting. | ||
-- Set to zero to run forever. | ||
total_run_times = 0, | ||
-- Shortens units to a single character (kiB->k, GiB->G, etc.). Default is off. | ||
-- short_units yes | ||
-- Add spaces to keep things from moving about? This only affects certain objects. | ||
-- use_spacer should have an argument of left, right, or none | ||
use_spacer = 'left', | ||
-- Force UTF8? note that UTF8 support required XFT | ||
override_utf8_locale = false, | ||
-- number of cpu samples to average | ||
-- set to 1 to disable averaging | ||
cpu_avg_samples = 3, | ||
net_avg_samples = 3, | ||
diskio_avg_samples = 3, | ||
format_human_readable = true, | ||
lua_load = '~/.config/i3/conky.lua', | ||
}; | ||
conky.text = [[ | ||
[ | ||
{ "full_text": "CPU:", "color": "\#2e9ef4", "separator": false }, | ||
{ ${lua_parse cpu cpu1} , "min_width": "100%", "align": "right", "separator": false }, | ||
{ ${lua_parse cpu cpu2} , "min_width": "100%", "align": "right", "separator": false }, | ||
{ ${lua_parse cpu cpu3} , "min_width": "100%", "align": "right", "separator": false }, | ||
{ ${lua_parse cpu cpu4} , "min_width": "100%", "align": "right", "separator": true, "separator_block_width":20 }, | ||
{ "full_text": "RAM:", "color": "\#2e9ef4", "separator": false }, | ||
{ "full_text": "${mem} / ${memeasyfree}", "color": ${if_match ${memperc}<80}"\#ffffff"${else}"\#ff0000"${endif}, "separator": true, "separator_block_width":20 }, | ||
{ "full_text": "sda:", "color": "\#2e9ef4", "separator": false }, | ||
{ "full_text": "▼ ${diskio_read sda} ▲ ${diskio_write sda}", "color": "\#ffffff", "separator": true, "separator_block_width":20 }, | ||
{ "full_text": "eth0:", "color": "\#2e9ef4", "separator": false }, | ||
{ "full_text": "▼ ${downspeed eth0} ▲ ${upspeed eth0}", "color": "\#ffffff", "separator": true, "separator_block_width":20 } | ||
] | ||
]]; | ||
``` | ||
|
||
|
||
**conky.lua**: | ||
```lua | ||
function gradient_red(min, max, val) | ||
local min = tonumber(min) | ||
local max = tonumber(max) | ||
local val = tonumber(val) | ||
if (val > max) then val = max end | ||
if (val < min) then val = min end | ||
local v = val - min | ||
local d = (max - min) * 0.5 | ||
local red, green | ||
if (v <= d) then | ||
red = math.floor((255 * v) / d + 0.5) | ||
green = 255 | ||
else | ||
red = 255 | ||
green = math.floor(255 - (255 * (v-d)) / (max - min - d) + 0.5) | ||
end | ||
return string.format("%02x%02x00", red, green) | ||
end | ||
function conky_cpu (cpun) | ||
local val = tonumber(conky_parse("${cpu " .. cpun .. "}")) | ||
if val == nil then val = 0 end | ||
return "\"full_text\": \"" .. val .. "%\", \"color\": \"\\#" .. gradient_red(0, 100, val) .. "\"" | ||
end | ||
``` | ||
|
||
## License | ||
|
||
YaGoStatus is licensed under the GNU GPLv3 License. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"github.com/burik666/yagostatus/ygs" | ||
"gopkg.in/yaml.v2" | ||
"io/ioutil" | ||
) | ||
|
||
type tmpConfig struct { | ||
Widgets []map[string]interface{} `yaml:"widgets"` | ||
} | ||
|
||
type Config struct { | ||
Widgets []ConfigWidget | ||
} | ||
|
||
type ConfigWidgetEvent struct { | ||
Command string `yaml:"command"` | ||
Button uint8 `yaml:"button"` | ||
Name string `yaml:"name,omitempty"` | ||
Instance string `yaml:"instance,omitempty"` | ||
Output bool `yaml:"output,omitempty"` | ||
} | ||
|
||
type ConfigWidget struct { | ||
Name string | ||
Params map[string]interface{} | ||
Template ygs.I3BarBlock | ||
Events []ConfigWidgetEvent | ||
} | ||
|
||
func loadConfig(filename string) (*Config, error) { | ||
data, err := ioutil.ReadFile(filename) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var t tmpConfig | ||
if err := yaml.Unmarshal(data, &t); err != nil { | ||
return nil, err | ||
} | ||
|
||
config := Config{} | ||
|
||
for _, v := range t.Widgets { | ||
widget := ConfigWidget{} | ||
|
||
var ok bool | ||
widget.Name, ok = v["widget"].(string) | ||
if !ok { | ||
return nil, errors.New("Missing widget name.") | ||
} | ||
delete(v, "widget") | ||
|
||
tpl, ok := v["template"] | ||
if ok { | ||
if err := json.Unmarshal([]byte(tpl.(string)), &widget.Template); err != nil { | ||
return nil, err | ||
} | ||
delete(v, "template") | ||
} | ||
|
||
events, ok := v["events"] | ||
if ok { | ||
ymlevents, _ := yaml.Marshal(events) | ||
yaml.Unmarshal(ymlevents, &widget.Events) | ||
delete(v, "events") | ||
} | ||
|
||
widget.Params = v | ||
config.Widgets = append(config.Widgets, widget) | ||
} | ||
return &config, nil | ||
} |
Oops, something went wrong.