From 946f970f3103093d53022d59917d8ad40761c186 Mon Sep 17 00:00:00 2001 From: Paul Wilde Date: Wed, 4 May 2022 16:17:02 +0100 Subject: [PATCH] refactor and made configuration constants easier to see/change --- README.MD | 32 +++++--- base.nim | 101 ++++++++++++++---------- battery.nim | 139 +++++++++++++++++++-------------- brightness.nim | 62 +++++++++------ date.nim | 72 +++++------------ fuzzytime.nim | 46 +++++------ i3bar_tools_threaded/readme.md | 4 + nic.nim | 92 +++++++++++----------- notes.nim | 86 ++++++++++++-------- pingclock.nim | 85 +++++++++++--------- temperature.nim | 56 +++++++------ i3bar_tides.nim => tides.nim | 0 volume.nim | 132 ++++++++++++++++--------------- wlan.nim | 82 +++++++++---------- 14 files changed, 531 insertions(+), 458 deletions(-) mode change 100644 => 100755 fuzzytime.nim create mode 100644 i3bar_tools_threaded/readme.md rename i3bar_tides.nim => tides.nim (100%) mode change 100644 => 100755 volume.nim 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: