refactor and made configuration constants easier to see/change

This commit is contained in:
Paul Wilde 2022-05-04 16:17:02 +01:00
parent d0624471e0
commit 946f970f31
14 changed files with 531 additions and 458 deletions

View file

@ -21,35 +21,41 @@ which are selectable options in dmenu.
https://user-images.githubusercontent.com/31094984/166115207-c24e9ec8-136e-4956-9842-bcde496bb743.mp4 https://user-images.githubusercontent.com/31094984/166115207-c24e9ec8-136e-4956-9842-bcde496bb743.mp4
### Example in rofi: ### Example in rofi:
https://user-images.githubusercontent.com/31094984/166115213-511fdaaa-4c04-461a-9976-38a2e9bd83fe.mp4 https://user-images.githubusercontent.com/31094984/166115213-511fdaaa-4c04-461a-9976-38a2e9bd83fe.mp4
## How to use ## How to compile
They are compiled separately, for example: There are some configuration variables explicit to me, you'll need to change them for you for them to be useful I imagine.
Configuration variables are compile - there are no config files or runtime parameters (except for "rofi")
Each tool is compiled separately, for example:
```nim ```nim
nim c pingclock nim c pingclock
``` ```
and then run with and then run with
```sh ```sh
./pingclock dmenu ./pingclock
or or
./pingclock rofi ./pingclock rofi
``` ```
it can also be run without any arguments to receive a i3bar compatible json string
Personally, I have these bound to key combinations in i3. In fact, I have a seperate `bindsym` mode in which all these tools are accessible i.e. `$mod+i` to get to "info" mode then `p` to show pingclock. ## How to use
Personally, I have these bound to key combinations in i3.
In fact, I have a seperate `bindsym` mode in which all these
tools are accessible i.e. `$mod+i` to get to "info" mode then `p` to show pingclock.
It's completely up to you how to run them, they're just simple CLI tools really.
### You can also set the volume and brightness levels by typing a numeric figure into the dmenu/rofi input box ### You can also set the volume and brightness levels by typing a numeric figure into the dmenu/rofi input box
https://user-images.githubusercontent.com/31094984/166156793-2089cc10-2649-4079-b82d-bba272253dd6.mp4 https://user-images.githubusercontent.com/31094984/166156793-2089cc10-2649-4079-b82d-bba272253dd6.mp4
There's also an i3bar_tools_threaded folder with tools for use with i3bar/i3blocks which continously update. Currently these are not working as I recently switched from this as primary, to a secondary choice. ## Dependencies
- dmenu, rofi, yad (for calendar)
- basically any tool that's used to gather the information.
- "tools" for audio etc. (`pamixer`, `ncpamixer`, etc.) can be set in the source
These have some configuration variables explicit to me, you'll need to change them for you for them to be useful I imagine. ## Full disclosure
I'm aware my code is messy.
### Dependencies I'm aware my code is mostly undocumented.
- dmenu, rofi, or i3bar (with i3blocks) But hopefully these things are simple enough to work out.
I'm aware my code is messy. I'm aware my code is undocumented. But hopefully these things are simple enough to work out.

101
base.nim
View file

@ -1,19 +1,19 @@
import std/[os,osproc,strutils] import std/[os,osproc,strutils,json,rdstdin,marshal]
import std/json
import std/rdstdin
import marshal
type type
Info* = object Info* = object
title*: string title*: string
selected_fg*: string
selected_bg*: string
unselected_fg*: string
unselected_bg*: string
full_text*: string full_text*: string
# next few are for i3bar use
border*: string
background*: string
color*: string
html_text*: string html_text*: string
short_text*: string short_text*: string
border*: string
color*: string
selected_color*: string
background*: string
selected_background*: string
type type
i3BarInput* = object i3BarInput* = object
@ -21,6 +21,7 @@ type
x*: int x*: int
y*: int y*: int
const font = "Hermit-10"
const background* = "#000000" const background* = "#000000"
const backgroundalt* = "#bb222222" const backgroundalt* = "#bb222222"
const backgroundalt2* = "#bb333333" const backgroundalt2* = "#bb333333"
@ -42,27 +43,33 @@ const darkgrey* = "#444"
const primary* = yellow const primary* = yellow
const secondary* = red const secondary* = red
const alert* = "#bd2c40" const alert* = "#bd2c40"
var loop* = true var loop* = false
var stoploop* = false var stoploop* = true
var dmenu* = false var dmenu* = true
var rofi* = false var rofi* = false
proc newInfo*(): Info = proc newInfo*(title: string = "Info"): Info =
return Info( return Info(
title: "Info : ", title: title,
full_text: "", selected_fg: black,
short_text: "", selected_bg: white,
color: foreground, unselected_fg: white,
selected_color: background, unselected_bg: black,
# next few are for i3bar use
border: white, border: white,
selected_background: white, background: black,
background: black color: foreground,
) )
proc debugLog*(str: string) = proc debugLog*(str: string) =
let f = open("/tmp/debug.txt",fmAppend) let f = open("/tmp/debug.txt",fmAppend)
defer: f.close() defer: f.close()
f.writeLine(str) f.writeLine(str)
proc switchTwmMode*() =
# I intend to add support for more twm as time goes on (I switch around a lot)
# Switch out of an i3 bindsym mode if set
discard execCmd("i3-msg mode \"default\"")
proc parseInput*(): i3BarInput = proc parseInput*(): i3BarInput =
let input = readLineFromStdin("") let input = readLineFromStdin("")
try: try:
@ -81,8 +88,11 @@ proc getArguments*(): seq[string] =
return args return args
proc runDMenu*(data: Info, opts: varargs[string], rofi: bool = false): string = proc runDMenu*(data: Info, opts: varargs[string], rofi: bool = false): string =
discard execCmd("i3-msg mode \"default\"") switch_twm_mode()
# Build dmenu/rofi command
var cmd = "echo -e \"" var cmd = "echo -e \""
# if the text is empty, we don't want to create a menu item of it
if $data.full_text != "": if $data.full_text != "":
cmd &= $data.full_text & "\n" cmd &= $data.full_text & "\n"
for opt in opts: for opt in opts:
@ -91,41 +101,50 @@ proc runDMenu*(data: Info, opts: varargs[string], rofi: bool = false): string =
if not rofi: if not rofi:
cmd = cmd & "\" | dmenu" cmd = cmd & "\" | dmenu"
else: else:
# run rofi in dmenu mode
cmd = cmd & "\" | rofi -dmenu" cmd = cmd & "\" | rofi -dmenu"
cmd = cmd & " -l " & $(len(opts) + 1) cmd = cmd & " -l " & $(len(opts) + 1)
cmd = cmd & " -p \"" & $data.title & "\"" cmd = cmd & " -p \"" & $data.title & "\""
cmd = cmd & " -nb \"" & $background & "\"" cmd = cmd & " -nb \"" & $data.unselected_bg & "\""
cmd = cmd & " -nf \"" & $foreground & "\"" cmd = cmd & " -nf \"" & $data.unselected_fg & "\""
cmd = cmd & " -sb \"" & $data.selected_background & "\"" cmd = cmd & " -sb \"" & $data.selected_bg & "\""
cmd = cmd & " -sf \"" & $data.selected_color & "\"" cmd = cmd & " -sf \"" & $data.selected_fg & "\""
cmd = cmd & " -fn Hermit-10" cmd = cmd & " -fn " & font
#echo "Dmenu :", cmd #echo "Dmenu :", cmd
# Run command and get output
let output = execCmdEx(cmd) let output = execCmdEx(cmd)
let option:string = strip(output[0]) let option:string = strip(output[0])
return option return option
proc outputJSON*(data: Info, args: varargs[string]): string {.discardable.} = proc outputData*(data: Info, args: varargs[string]): string {.discardable.} =
var output = "" var output = ""
if dmenu: if rofi:
output = runDMenu(data, args)
elif rofi:
output = runDmenu(data,args, rofi = true) output = runDmenu(data,args, rofi = true)
else: elif loop:
# mainly for i3bar/i3blocks compatible output
var j_data = data var j_data = data
if j_data.html_text != "": if j_data.html_text != "":
j_data.full_text = j_data.html_text j_data.full_text = j_data.html_text
echo $$j_data echo $$j_data
else:
# if all else fails, use dmenu (default)
output = runDmenu(data,args)
return output return output
let args = getArguments() for arg in getArguments():
for arg in args: case arg:
if arg == "noloop": of "noloop":
stoploop = true stoploop = true
if arg == "dmenu": of "i3bar":
stoploop = true # I've kind of changed from using an i3bar to using #nobar so i3bar
dmenu = true # isn't really supported any more but this is here for backwards compatibility
if arg == "rofi": loop = true
stoploop = true stoploop = false
rofi = true of "dmenu":
stoploop = true
dmenu = true
of "rofi":
stoploop = true
rofi = true

View file

@ -1,92 +1,114 @@
import base import base
import strutils import std/[strutils,os]
import std/os
proc battery_exists(): bool = const battery = "BAT0"
let state = strip(readFile("/sys/class/power_supply/BAT0/present")) const ok_fg = lightgreen
if state == "1": const default_fg = white
return true const default_bg = black
const warning_fg = black
const warning_bg = red
const low_bg = black
const low_fg = red
const alert_fg = black
const alert_bg = yellow
const med_fg = green
const med_bg = black
proc batteryExists(): bool =
try:
let state = strip(readFile("/sys/class/power_supply/" & battery & "/present"))
if state == "1":
return true
except:
echo "Error getting battery : " & getCurrentExceptionMsg()
return false return false
proc is_charging(): bool = proc isCharging(): bool =
let state = strip(readFile("/sys/class/power_supply/BAT0/status")) try:
case state: let state = strip(readFile("/sys/class/power_supply/" & battery & "/status"))
of "Charging": if state == "Charging":
return true return true
else: except:
return false echo "Error getting charging status : " & getCurrentExceptionMsg()
return false
proc get_charge(): int = proc getCharge(): int =
var charge = 0 var charge = 0
let chg = strip(readFile("/sys/class/power_supply/BAT0/capacity")) try:
if chg != "": let chg = strip(readFile("/sys/class/power_supply/" & battery & "/capacity"))
charge = parseInt(chg) if chg != "":
charge = parseInt(chg)
except:
echo "Error getting battery level : " & getCurrentExceptionMsg()
return charge return charge
proc get_design(charge: int, state: bool): (string, string, string, string, string) = proc getDesign(charge: int, state: bool): (string, string, string, string, string) =
var icon = "" var icon = ""
var icon_colour = lightgreen var icon_colour = ok_fg
var col = foreground var col = default_fg
var bg = black var bg = default_bg
var border = lightgreen var border = ok_fg
if is_charging(): if isCharging():
icon = "" icon = ""
else: else:
case charge: case charge:
of 0..5: of 0..5:
icon_colour = black icon_colour = warning_fg
col = black col = warning_fg
bg = red bg = warning_bg
of 6..19: of 6..19:
icon_colour = alert icon_colour = low_fg
border = alert border = low_bg
bg = default_bg
of 20..39: of 20..39:
icon_colour = yellow icon_colour = alert_fg
border = yellow border = alert_bg
icon = "" icon = ""
of 40..59: of 40..59:
icon_colour = green icon_colour = med_fg
border= green border= med_fg
icon = "" icon = ""
of 60..79: of 60..79:
icon_colour = green icon_colour = med_fg
border= green border = med_fg
icon = "" icon = ""
of 80..100: of 80..100:
icon_colour = lightgreen icon_colour = ok_fg
border = lightgreen border = ok_fg
icon = "" icon = ""
else: else:
icon = "x " icon = "x "
let main_text = icon & " " & $charge & "%" let main_text = icon & " " & $charge & "%"
let text = "<span foreground=\"" & icon_colour & "\">" & icon & "</span>" & $charge & "%" # This next line is here for i3bar purposes
return (text,main_text, col, bg, border) let html_text = "<span foreground=\"" & icon_colour & "\">" & icon & "</span>" & $charge & "%"
proc get_output(charge: int, state: bool): Info = return (html_text,main_text, col, bg, border)
let (text,main_text,col,bg_col,bord_col) = get_design(charge, state)
let data = Info( proc getOutput(charge: int, state: bool): Info =
title: "Battery : ", let (html_text,main_text,col,bg_col,highlight_col) = get_design(charge, state)
full_text: main_text, var data = newInfo("Battery")
html_text: text, data.full_text = main_text
color: col, data.selected_bg = highlight_col
border: bord_col, data.selected_fg = col # may just want `black` here
background: bg_col, # i3bar stuff
selected_background: bord_col, data.html_text = html_text
selected_color: black data.color = col
) data.border = highlight_col
data.background = bg_col
return data return data
proc get_battery_info() = proc getBatteryInfo() =
var last_charge = -1 var last_charge = -1
var last_state = false var last_state = false
while true: while true:
let charge = get_charge() let charge = getCharge()
let state = is_charging() let state = isCharging()
if charge != last_charge or state != last_state: if charge != last_charge or state != last_state:
let data = get_output(charge, state) let data = getoutput(charge, state)
outputJSON(data) outputData(data)
last_charge = charge last_charge = charge
last_state = state last_state = state
if stoploop: if stoploop:
@ -94,8 +116,11 @@ proc get_battery_info() =
sleep(1000) sleep(1000)
proc main() = proc main() =
if battery_exists(): if batteryExists():
get_battery_info() getBatteryInfo()
else:
switchTwmMode()
main() if isMainModule:
main()

View file

@ -1,16 +1,24 @@
import std/os
import strutils
import std/osproc
import std/math
import base import base
import std/[os,strutils,osproc,math]
proc getLimit(): int const backlight = "intel_backlight"
const default_bg = yellow
let limit = getLimit() const default_fg = black
const backlight_cmd = "xbacklight"
const backlight_up = backlight_cmd & " -inc %v" # %v is amount by
const backlight_down = backlight_cmd & " -dec %v" # %v is amount by
const backlight_set = backlight_cmd & " -set %v" # %v is amount by
const default_value = "5"
proc getLimit(): int = proc getLimit(): int =
let limit = parseInt(strip(readFile("/sys/class/backlight/intel_backlight/max_brightness"))) try:
return limit let back_l = readFile("/sys/class/backlight/" & backlight & "/max_brightness")
return parseInt(strip(back_l))
except:
echo "Error getting backlight max : ", getCurrentExceptionMsg()
return -1
let limit = getLimit()
proc getDesign(pcnt: float): string = proc getDesign(pcnt: float): string =
var icon = "🌑" var icon = "🌑"
@ -29,34 +37,37 @@ proc getDesign(pcnt: float): string =
let text = icon & " " & $percent & "%" let text = icon & " " & $percent & "%"
return text return text
proc get_brightness*(run_once: bool = false) = proc getBrightness*(run_once: bool = false) =
var last_pcnt: float = 0 var last_pcnt: float = 0
while true: while true:
let current = parseInt(strip(readFile("/sys/class/backlight/intel_backlight/actual_brightness"))) let current = parseInt(strip(readFile("/sys/class/backlight/" & backlight & "actual_brightness")))
let pcnt = (current/limit)*100 let pcnt = (current/limit)*100
if pcnt != last_pcnt: if pcnt != last_pcnt:
let text = getDesign(pcnt) let text = getDesign(pcnt)
var data = newInfo() var data = newInfo("Brightness")
data.title = "Brightness : "
data.full_text = text data.full_text = text
data.border = yellow data.selected_bg = default_fg
data.selected_background = yellow data.selected_fg = default_bg
data.selected_color = black # i3bar stuff
data.border = default_fg
let args = @["up", "down"] let args = @["up", "down"]
let option = outputJSON(data,args) let option = outputData(data,args)
if option in args: if option in args:
case option: case option:
of "up": of "up":
discard execCmd("xbacklight -inc 5") let cmd = replace(backlight_up,"%v",default_value)
get_brightness(true) discard execCmd(cmd)
getBrightness(true)
of "down": of "down":
discard execCmd("xbacklight -dec 5") let cmd = replace(backlight_down,"%v",default_value)
get_brightness(true) discard execCmd(cmd)
getBrightness(true)
else: else:
try: try:
let i = parseInt(option) let i = parseInt(option)
discard execCmd("xbacklight -set " & $i) let cmd = replace(backlight_set,"%v",$i)
get_brightness(true) discard execCmd(cmd)
getBrightness(true)
except: except:
echo getCurrentExceptionMsg() echo getCurrentExceptionMsg()
@ -68,7 +79,10 @@ proc get_brightness*(run_once: bool = false) =
sleep(1000) sleep(1000)
proc main() = proc main() =
get_brightness() if limit == -1:
switchTwmMode()
return
getBrightness()
if isMainModule: if isMainModule:
main() main()

View file

@ -1,20 +1,20 @@
import std/os
import std/times
import std/osproc
import std/re
import base import base
import std/[os,times,osproc,re]
const default_bg = blue
const default_fg = white
const default_format = "yyyy-MM-dd"
const cal_pos_x = "20"
const cal_pos_y = "20"
proc getObject(date: string): Info = proc getObject(date: string): Info =
var data = newInfo() var data = newInfo("Date")
data.title = "Date : "
data.full_text = date data.full_text = date
data.border = blue data.border = default_bg
data.selected_background = blue data.selected_bg = default_bg
data.selected_color = white data.selected_fg = default_fg
return data return data
#proc openCalendar(datestr: string) =
proc newCalendar(): string = proc newCalendar(): string =
var c = """yad --calendar \ var c = """yad --calendar \
--undecorated --fixed --close-on-unfocus --no-buttons \ --undecorated --fixed --close-on-unfocus --no-buttons \
@ -23,38 +23,25 @@ proc newCalendar(): string =
--title="yad-calendar" --borders 0 > /dev/null --title="yad-calendar" --borders 0 > /dev/null
""" """
return c return c
proc openCalendar*(input: i3barInput) = proc openCalendar*(input: i3barInput) =
var c = newCalendar() var c = newCalendar()
c = replace(c,re"%pos_x", $(input.x - 111)) c = replace(c,re"%pos_x", $(input.x - 111))
c = replace(c,re"%pos_y", $input.y) c = replace(c,re"%pos_y", $input.y)
discard execCmd(c) discard execCmd(c)
proc dmenuCalendar() = proc dmenuCalendar() =
var c = newCalendar() var c = newCalendar()
c = replace(c,re"%pos_x", cal_pos_x)
c = replace(c,re"%pos_x", "100") c = replace(c,re"%pos_y", cal_pos_y)
c = replace(c,re"%pos_y", "0")
discard execCmd(c) discard execCmd(c)
proc getDate*() = proc getDate*() =
var last_date = "" let date_today = times.now().format(default_format)
while true: let data = getObject(date_today)
let now = now() let output = outputData(data)
let d = now.format("yyyy-MM-dd") if output == date_today:
if d != last_date: dmenuCalendar()
let data = getObject(d)
let args = @["open calendar"]
case outputJSON(data, args):
of "open calendar":
dmenuCalendar()
last_date = d
if stoploop:
break
sleep(5000)
proc main() = proc main() =
getDate() getDate()
@ -63,26 +50,3 @@ proc main() =
if isMainModule: if isMainModule:
main() main()
#DATE="$(date +"%a %d %H:%M")"
#if [ "$(xdotool getwindowfocus getwindowname)" = "yad-calendar" ]; then
# exit 0
#fi
#eval "$(xdotool getmouselocation --shell)"
#eval "$(xdotool getdisplaygeometry --shell)"
## X
#if [ "$((X + YAD_WIDTH / 2 + BORDER_SIZE))" -gt "$WIDTH" ]; then #Right side
# : $((pos_x = WIDTH - YAD_WIDTH - BORDER_SIZE))
#elif [ "$((X - YAD_WIDTH / 2 - BORDER_SIZE))" -lt 0 ]; then #Left side
# : $((pos_x = BORDER_SIZE))
#else #Center
# : $((pos_x = X - YAD_WIDTH / 2))
#fi
## Y
#if [ "$Y" -gt "$((HEIGHT / 2))" ]; then #Bottom
# : $((pos_y = HEIGHT - YAD_HEIGHT - BAR_HEIGHT - BORDER_SIZE))
#else #Top
# : $((pos_y = BAR_HEIGHT + BORDER_SIZE))
#fi
#yad --calendar --undecorated --fixed --close-on-unfocus --no-buttons \
# --width="$YAD_WIDTH" --height="$YAD_HEIGHT" --posx="$pos_x" --posy="$pos_y" \
# --title="yad-calendar" --borders=0 >/dev/null &

46
fuzzytime.nim Normal file → Executable file
View file

@ -1,11 +1,13 @@
import std/times
import std/os
import base import base
import std/[os,times]
proc get_hour(hr: int): string const default_bg = lightblue
proc get_minute(min: int): string const default_fg = black
proc get_fuzzytime(): string = proc getHour(hr: int): string
proc getMinute(min: int): string
proc getFuzzyTime(): string =
let tm = now() let tm = now()
var hr = tm.hour() var hr = tm.hour()
let min = tm.minute() let min = tm.minute()
@ -18,11 +20,11 @@ proc get_fuzzytime(): string =
else: else:
hr = hr + 1 hr = hr + 1
if min >= 58 or min <= 02: if min >= 58 or min <= 02:
return get_hour(hr) & " " & get_minute(min) return getHour(hr) & " " & getMinute(min)
else: else:
return get_minute(min) & " " & link & " " & get_hour(hr) return getMinute(min) & " " & link & " " & getHour(hr)
proc get_hour(hr: int): string = proc getHour(hr: int): string =
case hr: case hr:
of 1, 13: of 1, 13:
return "one" return "one"
@ -51,7 +53,7 @@ proc get_hour(hr: int): string =
else: else:
return "error" return "error"
proc get_minute(min: int): string = proc getMinute(min: int): string =
case min: case min:
of 58,59,0,1,2: of 58,59,0,1,2:
return "o'clock" return "o'clock"
@ -71,28 +73,20 @@ proc get_minute(min: int): string =
return "error" return "error"
proc getObject(time: string): Info = proc getObject(time: string): Info =
var data = Info() var data = newInfo("Fuzzy Time")
data.title = "Fuzzy Time :"
data.full_text = time data.full_text = time
data.color = foreground data.selected_bg = default_bg
data.border = lightblue data.selected_fg = default_fg
data.selected_background = lightblue #i3bar stuff
data.selected_color = black data.color = default_fg
data.border = default_fg
return data return data
proc main() = proc main() =
var last_time = "" let time = getFuzzyTime()
while true: let data = getObject(time)
let time = get_fuzzytime() outputData(data)
if time != last_time:
let data = getObject(time)
outputJSON(data)
if stoploop:
break
last_time = time
sleep(2000)
if isMainModule: if isMainModule:
main() main()

View file

@ -0,0 +1,4 @@
## EVERYTHING IN THIS FOLDER CURRENTLY DOES NOT WORK!!!
I have moved away from using a desktop bar, and as such I have no need for the
threaded procedures these use. I may make them work again at some point, but for
now please consider this folder broken.

92
nic.nim
View file

@ -1,66 +1,66 @@
import base import base
import std/os import std/[os,osproc,strutils,sequtils]
import std/osproc
import strutils
const nics: seq[string] = @["wlan0", "enp3s0","wlp2s0","enp0s20f0u3"] const default_fg = black
const default_bg = purple
const mng_cmd = "alacritty -e nmtui-connect"
const nics: seq[string] = @["wlan0","bridge0", "enp3s0","wlp2s0","enp0s20f0u3"]
proc get_ip(nic: string): string = proc getIP(nic: string): string =
let cmd = "ifconfig " & nic & " | grep inet | awk -F\" \" '{print $2}' | head -1 | awk '{print $1}'" let cmd = "ifconfig " & nic & " | grep inet | awk -F\" \" '{print $2}' | head -1 | awk '{print $1}'"
let ip = execCmdEx(cmd) let ip = execCmdEx(cmd)
return strip(ip.output) return strip(ip.output)
proc get_online_state(nic: string): string = proc getOnlineState(nic: string): string =
let oper = readFile("/sys/class/net/" & nic & "/operstate") try:
let state = strip(oper) let oper = readFile("/sys/class/net/" & nic & "/operstate")
return "[" & state & "]" let state = strip(oper)
return "[" & state & "]"
except:
echo "Error getting operstate for " & nic & " : ", getCurrentExceptionMsg()
return ""
proc get_net(nic: string): (string, string) = proc getConnState(nic: string): (string, string) =
let state = get_online_state(nic) let state = getOnlineState(nic)
let ip = get_ip(nic) let ip = getIP(nic)
if state == "[down]" or ip == "": if state == "[down]" or ip == "":
return ("disconnected", state) return ("disconnected", state)
return (ip, state) return (ip, state)
proc getObject(conn: string, nic: string): Info = proc getObject(): Info =
var data = newInfo() var data = newInfo("IP")
data.title = "IP :" data.selected_bg = default_bg
data.full_text = conn data.selected_fg = default_fg
data.border = purple # i3bar stuff
data.selected_background = purple data.border = default_bg
data.selected_color = black
return data return data
proc get_net_info*(nic: string) = proc getNetInfo*(my_nics: seq[string]) =
var last_ip = "" var my_nic_states: seq[string] = @[]
var last_state = "" for nic in my_nics:
while true: let (ip, state) = getConnState(nic)
let (ip, state) = get_net(nic) my_nic_states.add(nic & ":" & state & " " & ip)
if ip != last_ip or state != last_state: let data = getObject()
let data = getObject(state & " " & ip, nic) let args = concat(my_nic_states,@["manage"])
let args = @["nmtui-connect"] let option = outputData(data, args)
let option = outputJSON(data, args) if option in my_nic_states:
case option: discard execCmd(mng_cmd)
of "nmtui-connect": case option:
discard execCmd("alacritty -e nmtui-connect") of "manage":
last_ip = ip discard execCmd(mng_cmd)
last_state = state
if stoploop:
break
sleep(1000)
proc getNics*(): seq[string] =
proc get_nic*(): string = var my_nics: seq[string] = @[]
for nic in nics: for nic in nics:
if dirExists("/sys/class/net/" & nic): if dirExists("/sys/class/net/" & nic):
return nic my_nics.add(nic)
return "no-nic"
if len(my_nics) > 0:
return my_nics
return @["no-nic"]
proc main() = proc main() =
let mynic = get_nic() getNetInfo(getNics())
if dirExists("/sys/class/net/" & mynic):
get_net_info(mynic)
else:
echo "No NIC"
main() if isMainModule:
main()

View file

@ -1,13 +1,15 @@
import base import base
import std/[os,strutils,sequtils] import std/[os,strutils,sequtils]
proc start_notes()
const all_choices = @["exit"] const note_file = getHomeDir() & "Nextcloud/.notes.dmenu" # Putting it in Nextcloud so it can sync :-)
const note_choices = @["rm","back"] const default_bg = white
const note_file = getHomeDir() & "Nextcloud/.notes.dmenu" const default_fg = black
proc read_notes(): seq[string] = proc startNotes()
proc displayOptionMenu(option: string)
proc readNotes(): seq[string] =
try: try:
var notes: seq[string] = @[] var notes: seq[string] = @[]
for line in note_file.lines: for line in note_file.lines:
@ -17,7 +19,7 @@ proc read_notes(): seq[string] =
echo "read_notes, Can't open notes file :", getCurrentExceptionMsg() echo "read_notes, Can't open notes file :", getCurrentExceptionMsg()
return @["<empty>"] return @["<empty>"]
proc write_notes(notes: seq[string]) = proc writeNotes(notes: seq[string]) =
try: try:
let f = open(note_file, fmWrite) let f = open(note_file, fmWrite)
defer: f.close() defer: f.close()
@ -26,15 +28,15 @@ proc write_notes(notes: seq[string]) =
except: except:
echo "write_notes, Cannot write notes to file : ", getCurrentExceptionMsg() echo "write_notes, Cannot write notes to file : ", getCurrentExceptionMsg()
proc remove_note(note: string) = proc removeNote(note: string) =
let notes = read_notes() let notes = readNotes()
var new_notes: seq[string] = @[] var new_notes: seq[string] = @[]
for a_note in notes: for a_note in notes:
if note != a_note: if note != a_note:
new_notes.add(a_note) new_notes.add(a_note)
write_notes(new_notes) writeNotes(new_notes)
proc write_note(note: string) = proc writeNote(note: string) =
if note == "": if note == "":
return return
try: try:
@ -44,60 +46,76 @@ proc write_note(note: string) =
except: except:
echo "write_note, Unable to write note :", getCurrentExceptionMsg() echo "write_note, Unable to write note :", getCurrentExceptionMsg()
proc replace_note(new_note: string, old_note: string) = proc replaceNote(new_note: string, old_note: string) =
let notes = read_notes() let notes = readNotes()
var new_notes: seq[string] = @[] var new_notes: seq[string] = @[]
for a_note in notes: for a_note in notes:
if old_note == a_note: if old_note == a_note:
new_notes.add(new_note) new_notes.add(new_note)
else: else:
new_notes.add(a_note) new_notes.add(a_note)
write_notes(new_notes) writeNotes(new_notes)
proc get_notes(): (Info, seq[string]) = proc getNotes(): (Info, seq[string]) =
var info = newInfo() var info = newInfo("Notes")
info.title = "Notes :" info.selected_bg = default_bg
let notes = read_notes() info.selected_fg = default_fg
let notes = readNotes()
return (info,notes) return (info,notes)
proc display_option_menu(option: string) = proc displayDeleteConfirmationMenu(note: string) =
var select = newInfo() var yes_no = newInfo("Confirm Delete note : " & note)
select.title = "Note :" yes_no.selected_bg = default_bg
yes_no.selected_fg = default_fg
let args = @["yes", "no"]
let choice = outputData(yes_no, args)
case choice:
of "yes":
removeNote(note)
of "no":
displayOptionMenu(note)
proc displayOptionMenu(option: string) =
var select = newInfo("Note")
select.selected_bg = default_bg
select.selected_fg = default_fg
let note_choices = @["rm","back"]
let args = concat(@[option],note_choices) let args = concat(@[option],note_choices)
let chosen = outputJSON(select,args) let chosen = outputData(select,args)
if chosen in note_choices: if chosen in note_choices:
case chosen: case chosen:
of "rm": of "rm":
remove_note(option) displayDeleteConfirmationMenu(option)
start_notes() startNotes()
of "back": of "back":
start_notes() startNotes()
elif chosen != "" and chosen != option: elif chosen != "" and chosen != option:
replace_note(chosen, option) replaceNote(chosen, option)
display_option_menu(chosen) displayOptionMenu(chosen)
else: else:
display_option_menu(option) displayOptionMenu(option)
proc start_notes() = proc startNotes() =
let (info,notes) = get_notes() let (info,notes) = getNotes()
let all_choices = @["exit"]
let args = concat(notes, all_choices) let args = concat(notes, all_choices)
let option = outputJSON(info, args) let option = outputData(info, args)
if option in all_choices: if option in all_choices:
case option: case option:
of "exit": of "exit":
return return
if option in notes: if option in notes:
display_option_menu(option) displayOptionMenu(option)
elif option != "": elif option != "":
write_note(option) writeNote(option)
start_notes() startNotes()
proc main() = proc main() =
echo "Note file : ", note_file echo "Note file : ", note_file
if not dmenu and not rofi: if not dmenu and not rofi:
echo "Can only be run in dmenu or rofi mode. Exiting..." echo "Can only be run in dmenu or rofi mode. Exiting..."
return return
start_notes() startNotes()
if isMainModule: if isMainModule:
main() main()

View file

@ -1,19 +1,23 @@
import std/os
import std/osproc
import std/re
import strutils
import base import base
import std/[osproc, re, strutils]
const host: string = "web.wilde.cloud" const host: string = "9.9.9.9"
const cmd: string = "ping -4 -c 1 " & host const default_bg = blue
const time_secs: int = 4 const default_fg = white
const medium_bg = alert
const medium_fg = black
const alert_bg = alert
const alert_fg = black
const warning_bg = red
const warning_fg = white
let ping_re = re(r"time=[0-9.]+") let ping_re = re(r"time=[0-9.]+")
const ping_cmd: string = "ping -4 -c 1 " & host
proc get_ping(): float = proc getPing(): float =
var ping: float = -1 var ping: float = -1
let cmdOut = execCmdEx(cmd) let cmdOut = execCmdEx(ping_cmd)
let lines = splitLines(cmdOut.output) let lines = splitLines(cmdOut.output)
let ping_line = lines[1] let ping_line = lines[1]
let bounds = findBounds(ping_line, ping_re) let bounds = findBounds(ping_line, ping_re)
if bounds.first > 0: if bounds.first > 0:
@ -25,46 +29,57 @@ proc getObject(ping: float): Info =
let pingstr = split($ping,".") let pingstr = split($ping,".")
let niceping = pingstr[0] & "." & pingstr[1][0] let niceping = pingstr[0] & "." & pingstr[1][0]
var text = "🏓 " & niceping & " ms" var text = "🏓 " & niceping & " ms"
var col = foreground var state = 0
if ping < 0: if ping < 0:
text = "❌ No Pong" text = "❌ No Pong"
col = yellow state = 1
else: else:
case ping: case ping:
of 0..100: of 0..100:
col = foreground state = 0
of 101..400: of 101..400:
col = yellow state = 1
of 401..1000: of 401..1000:
col = alert state = 2
else: else:
col = red state = 9
var data = newInfo() var data = newInfo("Ping Clock")
data.title = "Ping Clock:"
data.full_text = text data.full_text = text
data.color = col # i3bar stuff
data.border = blue data.color = default_fg
data.border = default_bg
data.background = black data.background = black
data.selected_background = blue data.selected_bg = default_bg
data.selected_color = white data.selected_fg = default_fg
case state:
of 1:
data.selected_bg = medium_bg
data.selected_fg = medium_fg
# i3bar stuff
data.color = medium_bg
of 2:
data.selected_bg = alert_bg
data.selected_fg = alert_fg
# i3bar stuff
data.color = alert_bg
of 9:
data.selected_bg = warning_bg
data.selected_fg = warning_fg
# i3bar stuff
data.color = warning_bg
else:
#default options already set
let ok = true
return data return data
proc main() = proc main() =
var last_ping: float = 0 let ping = get_ping()
while loop: let data = getObject(ping)
let ping = get_ping() let output = outputData(data)
if ping != last_ping: if output == data.full_text:
let data = getObject(ping) main()
let output = outputJSON(data)
if output == data.full_text:
main()
last_ping = ping
loop = not stoploop
if loop:
sleep(time_secs * 1000)
if isMainModule: if isMainModule:
main() main()

View file

@ -1,9 +1,12 @@
import std/os
import std/re
import std/math
import strutils
import base import base
import std/[os,re,math,strutils]
const default_bg = green
const default_fg = black
const alert_bg = yellow
const alert_fg = black
const warning_bg = red
const warning_fg = black
proc getThermalZones(): seq[string] = proc getThermalZones(): seq[string] =
var zones: seq[string] = @[] var zones: seq[string] = @[]
@ -29,40 +32,41 @@ proc getAverageTemp(zones: seq[string]): int =
proc getObject(temp: int): Info = proc getObject(temp: int): Info =
var icon = "" var icon = ""
var colour = foreground var bg_col = default_bg
var fg_col = default_fg
case temp: case temp:
of 40..59: of 40..59:
colour = yellow bg_col = alert_bg
fg_col = alert_fg
icon = "" icon = ""
of 60.. 200: of 60.. 200:
colour = red bg_col = warning_bg
fg_col = warning_fg
icon = "" icon = ""
else: else:
colour = green bg_col = default_bg
fg_col = default_fg
icon = "" icon = ""
let text = "<span foreground='" & colour & "'>" & icon & "</span> " & $temp & "°C" let text = "<span foreground='" & bg_col & "'>" & icon & "</span> " & $temp & "°C"
let main_text = icon & " " & $temp & "°C" let main_text = icon & " " & $temp & "°C"
var data = newInfo() var data = newInfo("Temperature")
data.title = "Temp : "
data.full_text = main_text data.full_text = main_text
data.selected_bg = bg_col
data.selected_fg = fg_col
# i3bar stuff
data.html_text = text data.html_text = text
data.color = foreground data.color = bg_col
data.border = colour data.border = bg_col
data.selected_background = colour
data.selected_color = black
return data return data
proc main() = proc main() =
let zones = getThermalZones() let zones = getThermalZones()
var last_temp = 0 let temp = getAverageTemp(zones)
while true: let data = getObject(temp)
let temp = getAverageTemp(zones) let option = outputData(data)
if temp != last_temp: if option == data.full_text:
let data = getObject(temp) # Refresh
outputJSON(data) main()
last_temp = temp
if stoploop:
break
sleep(10000)
main() if isMainModule:
main()

132
volume.nim Normal file → Executable file
View file

@ -1,24 +1,34 @@
import std/os
import strutils
import std/osproc
import std/math
import base import base
import std/[os,strutils,sequtils,osproc,math]
proc get_current_volume(): string {.gcsafe.} const audio_tools = @["ncpamixer", "pavucontrol"]
const vol_cmd = "pamixer"
const vol_up = vol_cmd & " -i %v" # where %v is amount by
const vol_down = vol_cmd & " -d %v" # where %v is amount by
const vol_set = vol_cmd & " --set-volume %v" # where %v is amount by
const vol_mute = vol_cmd & " -t"
const vol_default_by = "5"
const vol_get = vol_cmd & " --get-volume"
const vol_get_mute = vol_cmd & " --get-mute"
const default_bg = green
const default_fg = black
proc check_volume(volume: string): string =
proc getCurrentVolume(): string {.gcsafe.}
proc checkVolume(volume: string): string =
var vol = volume var vol = volume
if strip(vol) == "Connection error": if strip(vol) == "Connection error":
discard execCmdEx("pulseaudio -k; sleep 5; pulseaudio -D") sleep(1000)
vol = get_current_volume() vol = getCurrentVolume()
vol = check_volume(vol) vol = checkVolume(vol)
return vol return vol
proc getDesign(volume: string): (string,string) = proc getDesign(volume: string): (string,string) =
let vol = check_volume(volume) let vol = checkVolume(volume)
var icon = "" var icon = ""
if vol == "muted": if vol == "muted":
return (icon & "muted", "") return (icon & "muted", icon & "muted")
let pcnt = parseInt(strip(vol)) let pcnt = parseInt(strip(vol))
case pcnt: case pcnt:
of 85..100: of 85..100:
@ -35,63 +45,61 @@ proc getDesign(volume: string): (string,string) =
let text = "<span size=\"x-large\">" & icon & "</span>" & $pcnt & "%" let text = "<span size=\"x-large\">" & icon & "</span>" & $pcnt & "%"
return (text, main_text) return (text, main_text)
proc get_current_volume(): string = proc getCurrentVolume(): string =
let mute = execCmdEx("pamixer --get-mute") let mute = execCmdEx(vol_get_mute)
if strip(mute.output) == "true": if strip(mute.output) == "true":
return "muted" return "muted"
let vol = execCmdEx("pamixer --get-volume") let vol = execCmdEx(vol_get)
return vol.output return vol.output
proc get_volume*(run_once: bool = false) = proc getVolume*(run_once: bool = false) =
var last_vol: string = "" let vol = getCurrentVolume()
while true: let (text, main_text) = getDesign(vol)
let vol = get_current_volume() var data = newInfo("Volume")
if vol != last_vol or true: data.full_text = main_text
let (text, main_text) = getDesign(vol) data.selected_bg = default_bg
var data = Info() data.selected_fg = default_fg
data.title = "Volume : " # i3bar stuff
data.html_text = text data.html_text = text
data.full_text = main_text data.color = foreground
data.color = foreground data.border = green
data.border = green data.background = black
data.background = black let args = concat(@["up", "down", "mute", "---", "exit", "---"],audio_tools)
data.selected_background = green let option = outputData(data,args)
data.selected_color = black if option == "":
let args = @["up", "down", "mute", "ncpamixer", "pavucontrol"] return
let option = outputJSON(data,args) elif option in args:
if option in args: if option in audio_tools:
case option: discard(execCmd(option))
of "up": return
discard execCmd("pamixer -i 5") case option:
get_volume() of "up":
of "down": let cmd = replace(vol_up, "%v", vol_default_by)
discard execCmd("pamixer -d 5") discard execCmd(cmd)
get_volume() getVolume()
of "mute": of "down":
discard execCmd("pamixer -t") let cmd = replace(vol_down, "%v", vol_default_by)
get_volume() discard execCmd(cmd)
of "ncpamixer": getVolume()
discard execCmd("ncpamixer") of "mute":
of "pavucontrol": discard execCmd(vol_mute)
discard execCmd("pavucontrol") getVolume()
else: of "---":
try: getVolume()
let vol = parseInt(option) of "exit":
let x = execCmd("pamixer --set-volume " & $vol) return
echo x else:
get_volume() try:
except: let vol = parseInt(option)
echo getCurrentExceptionMsg() let cmd = replace(vol_set, "%v", $vol)
get_volume() let x = execCmd(cmd)
if run_once: getVolume()
break except:
last_vol = vol echo getCurrentExceptionMsg()
if stoploop: getVolume()
break
sleep(1000)
proc main() = proc main() =
get_volume() getVolume()
if isMainModule: if isMainModule:
main() main()

View file

@ -1,17 +1,17 @@
import base import base
import std/os import std/[os,osproc,strutils,sequtils]
import std/osproc
import strutils
const wlan_nic*: string ="wlan0" const default_bg = purple
const default_fg = white
const wlan_nics: seq[string] = @["wlan0"]
const get_ssid_cmd = "iwgetid -r"
const mng_cmd = "alacritty -e nmtui-connect"
# /sys/class/net/wlp2s0/operstate up or down if connected proc getSsid(): string =
let ssid = execCmdEx(get_ssid_cmd)
return strip(ssid.output)
proc get_essid(): string = proc getSignalQuality(): string =
let essid = execCmdEx("iwgetid -r")
return strip(essid.output)
proc get_signal_quality(): string =
let wl = readFile("/proc/net/wireless") let wl = readFile("/proc/net/wireless")
let ln = splitLines(wl)[2] let ln = splitLines(wl)[2]
let links = split(ln," ") let links = split(ln," ")
@ -19,43 +19,45 @@ proc get_signal_quality(): string =
qual = replace(qual,".","") qual = replace(qual,".","")
return "[" & qual & "]" return "[" & qual & "]"
proc get_wifi(): (string, string) = proc getWifi(nic: string): (string, string) =
let essid = get_essid() let ssid = getSsid()
if essid == "": if ssid == "":
return ("disconnected", "") return ("disconnected", "disconnected")
let quality = get_signal_quality() let quality = getSignalQuality()
return (essid, quality) return (ssid, quality)
proc getObject(conn: string): Info = proc getObject(): Info =
var data = newInfo() var data = newInfo("WiFi")
data.title = "WiFi : "
data.full_text = conn
data.border = purple data.border = purple
data.selected_background = purple data.selected_bg = default_bg
data.selected_color = black data.selected_fg = default_fg
return data return data
proc get_wifi_info*() = proc getWifiInfo*(nics: seq[string]) =
var last_qual = "" var lst: seq[string] = @[]
while true: for nic in nics:
let (essid, quality) = get_wifi() let (essid, quality) = getWifi(nic)
if quality != last_qual: lst.add(nic & ":" & quality & " " & essid)
let data = getObject(quality & " " & essid) let data = getObject()
let args = @["nmtui-connect"] let args = concat(lst,@["---", "manage","exit"])
let output = outputJSON(data, args) let output = outputData(data, args)
echo output case output:
case output: of "manage":
of "nmtui-connect": discard execCmd(mng_cmd)
discard execCmd("alacritty -e nmtui-connect") of "exit":
last_qual = quality return
if stoploop: of "---":
break return
sleep(1000)
proc main() = proc main() =
if dirExists("/sys/class/net/" & wlan_nic): var my_nics: seq[string] = @[]
get_wifi_info() for nic in wlan_nics:
if dirExists("/sys/class/net/" & nic):
my_nics.add(nic)
if len(my_nics) > 0:
getWifiInfo(my_nics)
else: else:
switchTwmMode()
echo "No WLAN" echo "No WLAN"
if isMainModule: if isMainModule: