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
### 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.

101
base.nim
View file

@ -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

View file

@ -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 = "<span foreground=\"" & icon_colour & "\">" & icon & "</span>" & $charge & "%"
return (text,main_text, col, bg, border)
# This next line is here for i3bar purposes
let html_text = "<span foreground=\"" & icon_colour & "\">" & icon & "</span>" & $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()

View file

@ -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()

View file

@ -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 &

46
fuzzytime.nim Normal file → Executable file
View file

@ -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()

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 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()

View file

@ -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 @["<empty>"]
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()

View file

@ -1,18 +1,22 @@
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 cmdOut = execCmdEx(ping_cmd)
let lines = splitLines(cmdOut.output)
let ping_line = lines[1]
let bounds = findBounds(ping_line, ping_re)
@ -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()

View file

@ -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 = "<span foreground='" & colour & "'>" & icon & "</span> " & $temp & "°C"
let text = "<span foreground='" & bg_col & "'>" & icon & "</span> " & $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()

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 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 = "<span size=\"x-large\">" & icon & "</span>" & $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()

View file

@ -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: