diff --git a/README.MD b/README.MD
index 8751bf4..787d288 100644
--- a/README.MD
+++ b/README.MD
@@ -21,35 +21,41 @@ which are selectable options in dmenu.
https://user-images.githubusercontent.com/31094984/166115207-c24e9ec8-136e-4956-9842-bcde496bb743.mp4
-
### Example in rofi:
https://user-images.githubusercontent.com/31094984/166115213-511fdaaa-4c04-461a-9976-38a2e9bd83fe.mp4
-## How to use
-They are compiled separately, for example:
+## How to compile
+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 c pingclock
```
and then run with
```sh
-./pingclock dmenu
+./pingclock
or
./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
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.
-
-### Dependencies
-- dmenu, rofi, or i3bar (with i3blocks)
-
-I'm aware my code is messy. I'm aware my code is undocumented. But hopefully these things are simple enough to work out.
+## Full disclosure
+I'm aware my code is messy.
+I'm aware my code is mostly undocumented.
+But hopefully these things are simple enough to work out.
diff --git a/base.nim b/base.nim
index 1285e58..a00d7f8 100644
--- a/base.nim
+++ b/base.nim
@@ -1,19 +1,19 @@
-import std/[os,osproc,strutils]
-import std/json
-import std/rdstdin
-import marshal
+import std/[os,osproc,strutils,json,rdstdin,marshal]
type
Info* = object
title*: string
+ selected_fg*: string
+ selected_bg*: string
+ unselected_fg*: string
+ unselected_bg*: string
full_text*: string
+ # next few are for i3bar use
+ border*: string
+ background*: string
+ color*: string
html_text*: string
short_text*: string
- border*: string
- color*: string
- selected_color*: string
- background*: string
- selected_background*: string
type
i3BarInput* = object
@@ -21,6 +21,7 @@ type
x*: int
y*: int
+const font = "Hermit-10"
const background* = "#000000"
const backgroundalt* = "#bb222222"
const backgroundalt2* = "#bb333333"
@@ -42,27 +43,33 @@ const darkgrey* = "#444"
const primary* = yellow
const secondary* = red
const alert* = "#bd2c40"
-var loop* = true
-var stoploop* = false
-var dmenu* = false
+var loop* = false
+var stoploop* = true
+var dmenu* = true
var rofi* = false
-proc newInfo*(): Info =
+proc newInfo*(title: string = "Info"): Info =
return Info(
- title: "Info : ",
- full_text: "",
- short_text: "",
- color: foreground,
- selected_color: background,
+ title: title,
+ selected_fg: black,
+ selected_bg: white,
+ unselected_fg: white,
+ unselected_bg: black,
+ # next few are for i3bar use
border: white,
- selected_background: white,
- background: black
+ background: black,
+ color: foreground,
)
proc debugLog*(str: string) =
let f = open("/tmp/debug.txt",fmAppend)
defer: f.close()
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 =
let input = readLineFromStdin("")
try:
@@ -81,8 +88,11 @@ proc getArguments*(): seq[string] =
return args
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 \""
+ # if the text is empty, we don't want to create a menu item of it
if $data.full_text != "":
cmd &= $data.full_text & "\n"
for opt in opts:
@@ -91,41 +101,50 @@ proc runDMenu*(data: Info, opts: varargs[string], rofi: bool = false): string =
if not rofi:
cmd = cmd & "\" | dmenu"
else:
+ # run rofi in dmenu mode
cmd = cmd & "\" | rofi -dmenu"
cmd = cmd & " -l " & $(len(opts) + 1)
cmd = cmd & " -p \"" & $data.title & "\""
- cmd = cmd & " -nb \"" & $background & "\""
- cmd = cmd & " -nf \"" & $foreground & "\""
- cmd = cmd & " -sb \"" & $data.selected_background & "\""
- cmd = cmd & " -sf \"" & $data.selected_color & "\""
- cmd = cmd & " -fn Hermit-10"
+ cmd = cmd & " -nb \"" & $data.unselected_bg & "\""
+ cmd = cmd & " -nf \"" & $data.unselected_fg & "\""
+ cmd = cmd & " -sb \"" & $data.selected_bg & "\""
+ cmd = cmd & " -sf \"" & $data.selected_fg & "\""
+ cmd = cmd & " -fn " & font
#echo "Dmenu :", cmd
+ # Run command and get output
let output = execCmdEx(cmd)
let option:string = strip(output[0])
return option
-proc outputJSON*(data: Info, args: varargs[string]): string {.discardable.} =
+proc outputData*(data: Info, args: varargs[string]): string {.discardable.} =
var output = ""
- if dmenu:
- output = runDMenu(data, args)
- elif rofi:
+ if rofi:
output = runDmenu(data,args, rofi = true)
- else:
+ elif loop:
+ # mainly for i3bar/i3blocks compatible output
var j_data = data
if j_data.html_text != "":
j_data.full_text = j_data.html_text
echo $$j_data
+ else:
+ # if all else fails, use dmenu (default)
+ output = runDmenu(data,args)
return output
-let args = getArguments()
-for arg in args:
- if arg == "noloop":
- stoploop = true
- if arg == "dmenu":
- stoploop = true
- dmenu = true
- if arg == "rofi":
- stoploop = true
- rofi = true
+for arg in getArguments():
+ case arg:
+ of "noloop":
+ stoploop = true
+ of "i3bar":
+ # I've kind of changed from using an i3bar to using #nobar so i3bar
+ # isn't really supported any more but this is here for backwards compatibility
+ loop = true
+ stoploop = false
+ of "dmenu":
+ stoploop = true
+ dmenu = true
+ of "rofi":
+ stoploop = true
+ rofi = true
diff --git a/battery.nim b/battery.nim
index 85f8f1d..36d4007 100644
--- a/battery.nim
+++ b/battery.nim
@@ -1,92 +1,114 @@
import base
-import strutils
-import std/os
+import std/[strutils,os]
-proc battery_exists(): bool =
- let state = strip(readFile("/sys/class/power_supply/BAT0/present"))
- if state == "1":
- return true
+const battery = "BAT0"
+const ok_fg = lightgreen
+const default_fg = white
+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
-proc is_charging(): bool =
- let state = strip(readFile("/sys/class/power_supply/BAT0/status"))
- case state:
- of "Charging":
+proc isCharging(): bool =
+ try:
+ let state = strip(readFile("/sys/class/power_supply/" & battery & "/status"))
+ if state == "Charging":
return true
- else:
- return false
+ except:
+ echo "Error getting charging status : " & getCurrentExceptionMsg()
+ return false
-proc get_charge(): int =
+proc getCharge(): int =
var charge = 0
- let chg = strip(readFile("/sys/class/power_supply/BAT0/capacity"))
- if chg != "":
- charge = parseInt(chg)
+ try:
+ let chg = strip(readFile("/sys/class/power_supply/" & battery & "/capacity"))
+ if chg != "":
+ charge = parseInt(chg)
+ except:
+ echo "Error getting battery level : " & getCurrentExceptionMsg()
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_colour = lightgreen
- var col = foreground
- var bg = black
- var border = lightgreen
- if is_charging():
+ var icon_colour = ok_fg
+ var col = default_fg
+ var bg = default_bg
+ var border = ok_fg
+ if isCharging():
icon = " "
else:
case charge:
of 0..5:
- icon_colour = black
- col = black
- bg = red
+ icon_colour = warning_fg
+ col = warning_fg
+ bg = warning_bg
of 6..19:
- icon_colour = alert
- border = alert
+ icon_colour = low_fg
+ border = low_bg
+ bg = default_bg
of 20..39:
- icon_colour = yellow
- border = yellow
+ icon_colour = alert_fg
+ border = alert_bg
icon = " "
of 40..59:
- icon_colour = green
- border= green
+ icon_colour = med_fg
+ border= med_fg
icon = " "
of 60..79:
- icon_colour = green
- border= green
+ icon_colour = med_fg
+ border = med_fg
icon = " "
of 80..100:
- icon_colour = lightgreen
- border = lightgreen
+ icon_colour = ok_fg
+ border = ok_fg
icon = " "
else:
icon = "x "
let main_text = icon & " " & $charge & "%"
- let text = "" & icon & "" & $charge & "%"
- return (text,main_text, col, bg, border)
+ # This next line is here for i3bar purposes
+ let html_text = "" & icon & "" & $charge & "%"
-proc get_output(charge: int, state: bool): Info =
- let (text,main_text,col,bg_col,bord_col) = get_design(charge, state)
- let data = Info(
- title: "Battery : ",
- full_text: main_text,
- html_text: text,
- color: col,
- border: bord_col,
- background: bg_col,
- selected_background: bord_col,
- selected_color: black
- )
+ return (html_text,main_text, col, bg, border)
+
+proc getOutput(charge: int, state: bool): Info =
+ let (html_text,main_text,col,bg_col,highlight_col) = get_design(charge, state)
+ var data = newInfo("Battery")
+ data.full_text = main_text
+ data.selected_bg = highlight_col
+ data.selected_fg = col # may just want `black` here
+ # i3bar stuff
+ data.html_text = html_text
+ data.color = col
+ data.border = highlight_col
+ data.background = bg_col
return data
-proc get_battery_info() =
+proc getBatteryInfo() =
var last_charge = -1
var last_state = false
while true:
- let charge = get_charge()
- let state = is_charging()
+ let charge = getCharge()
+ let state = isCharging()
if charge != last_charge or state != last_state:
- let data = get_output(charge, state)
- outputJSON(data)
+ let data = getoutput(charge, state)
+ outputData(data)
last_charge = charge
last_state = state
if stoploop:
@@ -94,8 +116,11 @@ proc get_battery_info() =
sleep(1000)
proc main() =
- if battery_exists():
- get_battery_info()
+ if batteryExists():
+ getBatteryInfo()
+ else:
+ switchTwmMode()
-main()
+if isMainModule:
+ main()
diff --git a/brightness.nim b/brightness.nim
index 860c3c5..783115b 100644
--- a/brightness.nim
+++ b/brightness.nim
@@ -1,16 +1,24 @@
-import std/os
-import strutils
-import std/osproc
-import std/math
import base
+import std/[os,strutils,osproc,math]
-proc getLimit(): int
-
-let limit = getLimit()
+const backlight = "intel_backlight"
+const default_bg = yellow
+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 =
- let limit = parseInt(strip(readFile("/sys/class/backlight/intel_backlight/max_brightness")))
- return limit
+ try:
+ 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 =
var icon = "🌑"
@@ -29,34 +37,37 @@ proc getDesign(pcnt: float): string =
let text = icon & " " & $percent & "%"
return text
-proc get_brightness*(run_once: bool = false) =
+proc getBrightness*(run_once: bool = false) =
var last_pcnt: float = 0
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
if pcnt != last_pcnt:
let text = getDesign(pcnt)
- var data = newInfo()
- data.title = "Brightness : "
+ var data = newInfo("Brightness")
data.full_text = text
- data.border = yellow
- data.selected_background = yellow
- data.selected_color = black
+ data.selected_bg = default_fg
+ data.selected_fg = default_bg
+ # i3bar stuff
+ data.border = default_fg
let args = @["up", "down"]
- let option = outputJSON(data,args)
+ let option = outputData(data,args)
if option in args:
case option:
of "up":
- discard execCmd("xbacklight -inc 5")
- get_brightness(true)
+ let cmd = replace(backlight_up,"%v",default_value)
+ discard execCmd(cmd)
+ getBrightness(true)
of "down":
- discard execCmd("xbacklight -dec 5")
- get_brightness(true)
+ let cmd = replace(backlight_down,"%v",default_value)
+ discard execCmd(cmd)
+ getBrightness(true)
else:
try:
let i = parseInt(option)
- discard execCmd("xbacklight -set " & $i)
- get_brightness(true)
+ let cmd = replace(backlight_set,"%v",$i)
+ discard execCmd(cmd)
+ getBrightness(true)
except:
echo getCurrentExceptionMsg()
@@ -68,7 +79,10 @@ proc get_brightness*(run_once: bool = false) =
sleep(1000)
proc main() =
- get_brightness()
+ if limit == -1:
+ switchTwmMode()
+ return
+ getBrightness()
if isMainModule:
main()
diff --git a/date.nim b/date.nim
index 138cfad..cf4299b 100644
--- a/date.nim
+++ b/date.nim
@@ -1,20 +1,20 @@
-import std/os
-import std/times
-import std/osproc
-import std/re
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 =
- var data = newInfo()
- data.title = "Date : "
+ var data = newInfo("Date")
data.full_text = date
- data.border = blue
- data.selected_background = blue
- data.selected_color = white
+ data.border = default_bg
+ data.selected_bg = default_bg
+ data.selected_fg = default_fg
return data
-#proc openCalendar(datestr: string) =
proc newCalendar(): string =
var c = """yad --calendar \
--undecorated --fixed --close-on-unfocus --no-buttons \
@@ -23,38 +23,25 @@ proc newCalendar(): string =
--title="yad-calendar" --borders 0 > /dev/null
"""
return c
+
proc openCalendar*(input: i3barInput) =
var c = newCalendar()
-
c = replace(c,re"%pos_x", $(input.x - 111))
c = replace(c,re"%pos_y", $input.y)
-
discard execCmd(c)
proc dmenuCalendar() =
var c = newCalendar()
-
- c = replace(c,re"%pos_x", "100")
- c = replace(c,re"%pos_y", "0")
-
+ c = replace(c,re"%pos_x", cal_pos_x)
+ c = replace(c,re"%pos_y", cal_pos_y)
discard execCmd(c)
-
proc getDate*() =
- var last_date = ""
- while true:
- let now = now()
- let d = now.format("yyyy-MM-dd")
- if d != last_date:
- let data = getObject(d)
- let args = @["open calendar"]
- case outputJSON(data, args):
- of "open calendar":
- dmenuCalendar()
- last_date = d
- if stoploop:
- break
- sleep(5000)
+ let date_today = times.now().format(default_format)
+ let data = getObject(date_today)
+ let output = outputData(data)
+ if output == date_today:
+ dmenuCalendar()
proc main() =
getDate()
@@ -63,26 +50,3 @@ proc main() =
if isMainModule:
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 &
diff --git a/fuzzytime.nim b/fuzzytime.nim
old mode 100644
new mode 100755
index d74b11b..ca5cdf0
--- a/fuzzytime.nim
+++ b/fuzzytime.nim
@@ -1,11 +1,13 @@
-import std/times
-import std/os
import base
+import std/[os,times]
-proc get_hour(hr: int): string
-proc get_minute(min: int): string
+const default_bg = lightblue
+const default_fg = black
-proc get_fuzzytime(): string =
+proc getHour(hr: int): string
+proc getMinute(min: int): string
+
+proc getFuzzyTime(): string =
let tm = now()
var hr = tm.hour()
let min = tm.minute()
@@ -18,11 +20,11 @@ proc get_fuzzytime(): string =
else:
hr = hr + 1
if min >= 58 or min <= 02:
- return get_hour(hr) & " " & get_minute(min)
+ return getHour(hr) & " " & getMinute(min)
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:
of 1, 13:
return "one"
@@ -51,7 +53,7 @@ proc get_hour(hr: int): string =
else:
return "error"
-proc get_minute(min: int): string =
+proc getMinute(min: int): string =
case min:
of 58,59,0,1,2:
return "o'clock"
@@ -71,28 +73,20 @@ proc get_minute(min: int): string =
return "error"
proc getObject(time: string): Info =
- var data = Info()
- data.title = "Fuzzy Time :"
+ var data = newInfo("Fuzzy Time")
data.full_text = time
- data.color = foreground
- data.border = lightblue
- data.selected_background = lightblue
- data.selected_color = black
+ data.selected_bg = default_bg
+ data.selected_fg = default_fg
+ #i3bar stuff
+ data.color = default_fg
+ data.border = default_fg
return data
proc main() =
- var last_time = ""
- while true:
- let time = get_fuzzytime()
- if time != last_time:
- let data = getObject(time)
- outputJSON(data)
- if stoploop:
- break
- last_time = time
-
- sleep(2000)
+ let time = getFuzzyTime()
+ let data = getObject(time)
+ outputData(data)
if isMainModule:
main()
diff --git a/i3bar_tools_threaded/readme.md b/i3bar_tools_threaded/readme.md
new file mode 100644
index 0000000..8910e84
--- /dev/null
+++ b/i3bar_tools_threaded/readme.md
@@ -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.
diff --git a/nic.nim b/nic.nim
index 9b074ac..f31f79e 100644
--- a/nic.nim
+++ b/nic.nim
@@ -1,66 +1,66 @@
import base
-import std/os
-import std/osproc
-import strutils
+import std/[os,osproc,strutils,sequtils]
-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 ip = execCmdEx(cmd)
return strip(ip.output)
-proc get_online_state(nic: string): string =
- let oper = readFile("/sys/class/net/" & nic & "/operstate")
- let state = strip(oper)
- return "[" & state & "]"
+proc getOnlineState(nic: string): string =
+ try:
+ let oper = readFile("/sys/class/net/" & nic & "/operstate")
+ let state = strip(oper)
+ return "[" & state & "]"
+ except:
+ echo "Error getting operstate for " & nic & " : ", getCurrentExceptionMsg()
+ return ""
-proc get_net(nic: string): (string, string) =
- let state = get_online_state(nic)
- let ip = get_ip(nic)
+proc getConnState(nic: string): (string, string) =
+ let state = getOnlineState(nic)
+ let ip = getIP(nic)
if state == "[down]" or ip == "":
return ("disconnected", state)
return (ip, state)
-proc getObject(conn: string, nic: string): Info =
- var data = newInfo()
- data.title = "IP :"
- data.full_text = conn
- data.border = purple
- data.selected_background = purple
- data.selected_color = black
+proc getObject(): Info =
+ var data = newInfo("IP")
+ data.selected_bg = default_bg
+ data.selected_fg = default_fg
+ # i3bar stuff
+ data.border = default_bg
return data
-proc get_net_info*(nic: string) =
- var last_ip = ""
- var last_state = ""
- while true:
- let (ip, state) = get_net(nic)
- if ip != last_ip or state != last_state:
- let data = getObject(state & " " & ip, nic)
- let args = @["nmtui-connect"]
- let option = outputJSON(data, args)
- case option:
- of "nmtui-connect":
- discard execCmd("alacritty -e nmtui-connect")
- last_ip = ip
- last_state = state
- if stoploop:
- break
- sleep(1000)
+proc getNetInfo*(my_nics: seq[string]) =
+ var my_nic_states: seq[string] = @[]
+ for nic in my_nics:
+ let (ip, state) = getConnState(nic)
+ my_nic_states.add(nic & ":" & state & " " & ip)
+ let data = getObject()
+ let args = concat(my_nic_states,@["manage"])
+ let option = outputData(data, args)
+ if option in my_nic_states:
+ discard execCmd(mng_cmd)
+ case option:
+ of "manage":
+ discard execCmd(mng_cmd)
-
-proc get_nic*(): string =
+proc getNics*(): seq[string] =
+ var my_nics: seq[string] = @[]
for nic in nics:
if dirExists("/sys/class/net/" & nic):
- return nic
- return "no-nic"
+ my_nics.add(nic)
+
+ if len(my_nics) > 0:
+ return my_nics
+ return @["no-nic"]
proc main() =
- let mynic = get_nic()
- if dirExists("/sys/class/net/" & mynic):
- get_net_info(mynic)
- else:
- echo "No NIC"
+ getNetInfo(getNics())
-main()
+if isMainModule:
+ main()
diff --git a/notes.nim b/notes.nim
index a4ad077..6526370 100644
--- a/notes.nim
+++ b/notes.nim
@@ -1,13 +1,15 @@
import base
import std/[os,strutils,sequtils]
-proc start_notes()
-const all_choices = @["exit"]
-const note_choices = @["rm","back"]
-const note_file = getHomeDir() & "Nextcloud/.notes.dmenu"
+const note_file = getHomeDir() & "Nextcloud/.notes.dmenu" # Putting it in Nextcloud so it can sync :-)
+const default_bg = white
+const default_fg = black
-proc read_notes(): seq[string] =
+proc startNotes()
+proc displayOptionMenu(option: string)
+
+proc readNotes(): seq[string] =
try:
var notes: seq[string] = @[]
for line in note_file.lines:
@@ -17,7 +19,7 @@ proc read_notes(): seq[string] =
echo "read_notes, Can't open notes file :", getCurrentExceptionMsg()
return @[""]
-proc write_notes(notes: seq[string]) =
+proc writeNotes(notes: seq[string]) =
try:
let f = open(note_file, fmWrite)
defer: f.close()
@@ -26,15 +28,15 @@ proc write_notes(notes: seq[string]) =
except:
echo "write_notes, Cannot write notes to file : ", getCurrentExceptionMsg()
-proc remove_note(note: string) =
- let notes = read_notes()
+proc removeNote(note: string) =
+ let notes = readNotes()
var new_notes: seq[string] = @[]
for a_note in notes:
if note != 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 == "":
return
try:
@@ -44,60 +46,76 @@ proc write_note(note: string) =
except:
echo "write_note, Unable to write note :", getCurrentExceptionMsg()
-proc replace_note(new_note: string, old_note: string) =
- let notes = read_notes()
+proc replaceNote(new_note: string, old_note: string) =
+ let notes = readNotes()
var new_notes: seq[string] = @[]
for a_note in notes:
if old_note == a_note:
new_notes.add(new_note)
else:
new_notes.add(a_note)
- write_notes(new_notes)
+ writeNotes(new_notes)
-proc get_notes(): (Info, seq[string]) =
- var info = newInfo()
- info.title = "Notes :"
- let notes = read_notes()
+proc getNotes(): (Info, seq[string]) =
+ var info = newInfo("Notes")
+ info.selected_bg = default_bg
+ info.selected_fg = default_fg
+ let notes = readNotes()
return (info,notes)
-proc display_option_menu(option: string) =
- var select = newInfo()
- select.title = "Note :"
+proc displayDeleteConfirmationMenu(note: string) =
+ var yes_no = newInfo("Confirm Delete note : " & 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 chosen = outputJSON(select,args)
+ let chosen = outputData(select,args)
if chosen in note_choices:
case chosen:
of "rm":
- remove_note(option)
- start_notes()
+ displayDeleteConfirmationMenu(option)
+ startNotes()
of "back":
- start_notes()
+ startNotes()
elif chosen != "" and chosen != option:
- replace_note(chosen, option)
- display_option_menu(chosen)
+ replaceNote(chosen, option)
+ displayOptionMenu(chosen)
else:
- display_option_menu(option)
+ displayOptionMenu(option)
-proc start_notes() =
- let (info,notes) = get_notes()
+proc startNotes() =
+ let (info,notes) = getNotes()
+ let all_choices = @["exit"]
let args = concat(notes, all_choices)
- let option = outputJSON(info, args)
+ let option = outputData(info, args)
if option in all_choices:
case option:
of "exit":
return
if option in notes:
- display_option_menu(option)
+ displayOptionMenu(option)
elif option != "":
- write_note(option)
- start_notes()
+ writeNote(option)
+ startNotes()
proc main() =
echo "Note file : ", note_file
if not dmenu and not rofi:
echo "Can only be run in dmenu or rofi mode. Exiting..."
return
- start_notes()
+ startNotes()
if isMainModule:
main()
diff --git a/pingclock.nim b/pingclock.nim
index fa3d103..8f7debc 100644
--- a/pingclock.nim
+++ b/pingclock.nim
@@ -1,19 +1,23 @@
-import std/os
-import std/osproc
-import std/re
-import strutils
import base
+import std/[osproc, re, strutils]
-const host: string = "web.wilde.cloud"
-const cmd: string = "ping -4 -c 1 " & host
-const time_secs: int = 4
+const host: string = "9.9.9.9"
+const default_bg = blue
+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.]+")
+const ping_cmd: string = "ping -4 -c 1 " & host
-proc get_ping(): float =
+proc getPing(): float =
var ping: float = -1
- let cmdOut = execCmdEx(cmd)
- let lines = splitLines(cmdOut.output)
+ let cmdOut = execCmdEx(ping_cmd)
+ let lines = splitLines(cmdOut.output)
let ping_line = lines[1]
let bounds = findBounds(ping_line, ping_re)
if bounds.first > 0:
@@ -25,46 +29,57 @@ proc getObject(ping: float): Info =
let pingstr = split($ping,".")
let niceping = pingstr[0] & "." & pingstr[1][0]
var text = "🏓 " & niceping & " ms"
- var col = foreground
+ var state = 0
if ping < 0:
text = "❌ No Pong"
- col = yellow
+ state = 1
else:
case ping:
of 0..100:
- col = foreground
+ state = 0
of 101..400:
- col = yellow
+ state = 1
of 401..1000:
- col = alert
+ state = 2
else:
- col = red
+ state = 9
- var data = newInfo()
- data.title = "Ping Clock:"
+ var data = newInfo("Ping Clock")
data.full_text = text
- data.color = col
- data.border = blue
+ # i3bar stuff
+ data.color = default_fg
+ data.border = default_bg
data.background = black
- data.selected_background = blue
- data.selected_color = white
+ data.selected_bg = default_bg
+ 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
proc main() =
- var last_ping: float = 0
- while loop:
- let ping = get_ping()
- if ping != last_ping:
- let data = getObject(ping)
- let output = outputJSON(data)
- if output == data.full_text:
- main()
- last_ping = ping
- loop = not stoploop
- if loop:
- sleep(time_secs * 1000)
-
+ let ping = get_ping()
+ let data = getObject(ping)
+ let output = outputData(data)
+ if output == data.full_text:
+ main()
if isMainModule:
main()
diff --git a/temperature.nim b/temperature.nim
index ee77fec..0f1795d 100644
--- a/temperature.nim
+++ b/temperature.nim
@@ -1,9 +1,12 @@
-import std/os
-import std/re
-import std/math
-import strutils
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] =
var zones: seq[string] = @[]
@@ -29,40 +32,41 @@ proc getAverageTemp(zones: seq[string]): int =
proc getObject(temp: int): Info =
var icon = ""
- var colour = foreground
+ var bg_col = default_bg
+ var fg_col = default_fg
case temp:
of 40..59:
- colour = yellow
+ bg_col = alert_bg
+ fg_col = alert_fg
icon = ""
of 60.. 200:
- colour = red
+ bg_col = warning_bg
+ fg_col = warning_fg
icon = ""
else:
- colour = green
+ bg_col = default_bg
+ fg_col = default_fg
icon = ""
- let text = "" & icon & " " & $temp & "°C"
+ let text = "" & icon & " " & $temp & "°C"
let main_text = icon & " " & $temp & "°C"
- var data = newInfo()
- data.title = "Temp : "
+ var data = newInfo("Temperature")
data.full_text = main_text
+ data.selected_bg = bg_col
+ data.selected_fg = fg_col
+ # i3bar stuff
data.html_text = text
- data.color = foreground
- data.border = colour
- data.selected_background = colour
- data.selected_color = black
+ data.color = bg_col
+ data.border = bg_col
return data
proc main() =
let zones = getThermalZones()
- var last_temp = 0
- while true:
- let temp = getAverageTemp(zones)
- if temp != last_temp:
- let data = getObject(temp)
- outputJSON(data)
- last_temp = temp
- if stoploop:
- break
- sleep(10000)
+ let temp = getAverageTemp(zones)
+ let data = getObject(temp)
+ let option = outputData(data)
+ if option == data.full_text:
+ # Refresh
+ main()
-main()
+if isMainModule:
+ main()
diff --git a/i3bar_tides.nim b/tides.nim
similarity index 100%
rename from i3bar_tides.nim
rename to tides.nim
diff --git a/volume.nim b/volume.nim
old mode 100644
new mode 100755
index e259e77..fa68ae9
--- a/volume.nim
+++ b/volume.nim
@@ -1,24 +1,34 @@
-import std/os
-import strutils
-import std/osproc
-import std/math
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
if strip(vol) == "Connection error":
- discard execCmdEx("pulseaudio -k; sleep 5; pulseaudio -D")
- vol = get_current_volume()
- vol = check_volume(vol)
+ sleep(1000)
+ vol = getCurrentVolume()
+ vol = checkVolume(vol)
return vol
proc getDesign(volume: string): (string,string) =
- let vol = check_volume(volume)
+ let vol = checkVolume(volume)
var icon = " "
if vol == "muted":
- return (icon & "muted", "")
+ return (icon & "muted", icon & "muted")
let pcnt = parseInt(strip(vol))
case pcnt:
of 85..100:
@@ -35,63 +45,61 @@ proc getDesign(volume: string): (string,string) =
let text = "" & icon & "" & $pcnt & "%"
return (text, main_text)
-proc get_current_volume(): string =
- let mute = execCmdEx("pamixer --get-mute")
+proc getCurrentVolume(): string =
+ let mute = execCmdEx(vol_get_mute)
if strip(mute.output) == "true":
return "muted"
- let vol = execCmdEx("pamixer --get-volume")
+ let vol = execCmdEx(vol_get)
return vol.output
-proc get_volume*(run_once: bool = false) =
- var last_vol: string = ""
- while true:
- let vol = get_current_volume()
- if vol != last_vol or true:
- let (text, main_text) = getDesign(vol)
- var data = Info()
- data.title = "Volume : "
- data.html_text = text
- data.full_text = main_text
- data.color = foreground
- data.border = green
- data.background = black
- data.selected_background = green
- data.selected_color = black
- let args = @["up", "down", "mute", "ncpamixer", "pavucontrol"]
- let option = outputJSON(data,args)
- if option in args:
- case option:
- of "up":
- discard execCmd("pamixer -i 5")
- get_volume()
- of "down":
- discard execCmd("pamixer -d 5")
- get_volume()
- of "mute":
- discard execCmd("pamixer -t")
- get_volume()
- of "ncpamixer":
- discard execCmd("ncpamixer")
- of "pavucontrol":
- discard execCmd("pavucontrol")
- else:
- try:
- let vol = parseInt(option)
- let x = execCmd("pamixer --set-volume " & $vol)
- echo x
- get_volume()
- except:
- echo getCurrentExceptionMsg()
- get_volume()
- if run_once:
- break
- last_vol = vol
- if stoploop:
- break
- sleep(1000)
+proc getVolume*(run_once: bool = false) =
+ let vol = getCurrentVolume()
+ let (text, main_text) = getDesign(vol)
+ var data = newInfo("Volume")
+ data.full_text = main_text
+ data.selected_bg = default_bg
+ data.selected_fg = default_fg
+ # i3bar stuff
+ data.html_text = text
+ data.color = foreground
+ data.border = green
+ data.background = black
+ let args = concat(@["up", "down", "mute", "---", "exit", "---"],audio_tools)
+ let option = outputData(data,args)
+ if option == "":
+ return
+ elif option in args:
+ if option in audio_tools:
+ discard(execCmd(option))
+ return
+ case option:
+ of "up":
+ let cmd = replace(vol_up, "%v", vol_default_by)
+ discard execCmd(cmd)
+ getVolume()
+ of "down":
+ let cmd = replace(vol_down, "%v", vol_default_by)
+ discard execCmd(cmd)
+ getVolume()
+ of "mute":
+ discard execCmd(vol_mute)
+ getVolume()
+ of "---":
+ getVolume()
+ of "exit":
+ return
+ else:
+ try:
+ let vol = parseInt(option)
+ let cmd = replace(vol_set, "%v", $vol)
+ let x = execCmd(cmd)
+ getVolume()
+ except:
+ echo getCurrentExceptionMsg()
+ getVolume()
proc main() =
- get_volume()
+ getVolume()
if isMainModule:
main()
diff --git a/wlan.nim b/wlan.nim
index 8575182..8552d3c 100644
--- a/wlan.nim
+++ b/wlan.nim
@@ -1,17 +1,17 @@
import base
-import std/os
-import std/osproc
-import strutils
+import std/[os,osproc,strutils,sequtils]
-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 =
- let essid = execCmdEx("iwgetid -r")
- return strip(essid.output)
-
-proc get_signal_quality(): string =
+proc getSignalQuality(): string =
let wl = readFile("/proc/net/wireless")
let ln = splitLines(wl)[2]
let links = split(ln," ")
@@ -19,43 +19,45 @@ proc get_signal_quality(): string =
qual = replace(qual,".","")
return "[" & qual & "]"
-proc get_wifi(): (string, string) =
- let essid = get_essid()
- if essid == "":
- return ("disconnected", "")
- let quality = get_signal_quality()
- return (essid, quality)
+proc getWifi(nic: string): (string, string) =
+ let ssid = getSsid()
+ if ssid == "":
+ return ("disconnected", "disconnected")
+ let quality = getSignalQuality()
+ return (ssid, quality)
-proc getObject(conn: string): Info =
- var data = newInfo()
- data.title = "WiFi : "
- data.full_text = conn
+proc getObject(): Info =
+ var data = newInfo("WiFi")
data.border = purple
- data.selected_background = purple
- data.selected_color = black
+ data.selected_bg = default_bg
+ data.selected_fg = default_fg
return data
-proc get_wifi_info*() =
- var last_qual = ""
- while true:
- let (essid, quality) = get_wifi()
- if quality != last_qual:
- let data = getObject(quality & " " & essid)
- let args = @["nmtui-connect"]
- let output = outputJSON(data, args)
- echo output
- case output:
- of "nmtui-connect":
- discard execCmd("alacritty -e nmtui-connect")
- last_qual = quality
- if stoploop:
- break
- sleep(1000)
+proc getWifiInfo*(nics: seq[string]) =
+ var lst: seq[string] = @[]
+ for nic in nics:
+ let (essid, quality) = getWifi(nic)
+ lst.add(nic & ":" & quality & " " & essid)
+ let data = getObject()
+ let args = concat(lst,@["---", "manage","exit"])
+ let output = outputData(data, args)
+ case output:
+ of "manage":
+ discard execCmd(mng_cmd)
+ of "exit":
+ return
+ of "---":
+ return
proc main() =
- if dirExists("/sys/class/net/" & wlan_nic):
- get_wifi_info()
+ var my_nics: seq[string] = @[]
+ for nic in wlan_nics:
+ if dirExists("/sys/class/net/" & nic):
+ my_nics.add(nic)
+ if len(my_nics) > 0:
+ getWifiInfo(my_nics)
else:
+ switchTwmMode()
echo "No WLAN"
if isMainModule: