Compare commits
No commits in common. "92d1eea678f562ada8f89ce11dc34f47f2aef09a" and "91ca8e12a4b612fdfb4b6f080ac928267b2bb34c" have entirely different histories.
92d1eea678
...
91ca8e12a4
75 changed files with 1633 additions and 1072 deletions
70
README.MD
Executable file
70
README.MD
Executable file
|
@ -0,0 +1,70 @@
|
|||
# A selection of information output tools for dmenu
|
||||
|
||||
These are a selection of independant tools for displaying various information
|
||||
about system status in dmenu. Some of them i.e. `volurrme` have options (up, down, mute...)
|
||||
which are selectable options in dmenu.
|
||||
|
||||
## Tools
|
||||
- `pingclurrk` performs a single `ping` to a server and returns the response time
|
||||
- `batturry` shows the current battery level
|
||||
- `brightnurrs` shows the current backlight level and gives options to adjust it
|
||||
- `volurrme` shows the current volume level and gives options to adjust and manage it
|
||||
- `calendurr` shows the date
|
||||
- `furrytime` shows the fuzzytime clock
|
||||
- `wirelurrs` shows the state of the wireless network interface. SSID connected to and signal level.
|
||||
- `netwurrk` shows the status and/or the ip address of the network interface card
|
||||
- `temperaturr` shows the current CPU temperature
|
||||
- `noteurr` a simple one liner note taking tool, displaying notes in `dmenu`/`rofi`
|
||||
- `calculaturr` a calculator, utilising `qalculate` - inspired by [@fedops](https://codeberg.org/fedops/scripts)
|
||||
- `emurrji` an emoji picker
|
||||
- `remmina_choosurr` reads the files in your remmina config directory and allows you to connect to and edit them
|
||||
- `translaturr` utilises libretranslate (you'll need and API key or your own instance) to translate test. Prefix the text with `en>de`, `de>en`, `en>fr`, etc. as you need. Must be compiled with `-d:ssl`
|
||||
- `clipurr` clipboard manager
|
||||
- `passwuurd` a passmenu clone, that works in rofi too
|
||||
- `cmd_wrappurr` a basic tool to run other `dmenu` related tools with uniform styling.
|
||||
- For example: `dmenu_run`, `clipmenu`, `passmenu` etc.
|
||||
|
||||
### Why do all the tools have "urr" in them?
|
||||
This is something I was inspired to do after writing `clipurr`… "purr", like a cat... see?
|
||||
So I thought I'd rename everything else to conform to this amazing naming convention… cool eh‽
|
||||
|
||||
|
||||
## 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
|
||||
|
||||
Each tool is compiled separately, for example:
|
||||
```sh
|
||||
nimble install
|
||||
or
|
||||
nim c pingclurrk
|
||||
```
|
||||
|
||||
and then run with
|
||||
```sh
|
||||
./pingclurrk
|
||||
or
|
||||
./pingclurrk rofi
|
||||
```
|
||||
|
||||
## How to use
|
||||
Personally, I have these bound to key combinations in i3 and sway.
|
||||
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.
|
||||
|
||||
### You can also set the volume and brightness levels by typing a numeric figure into the dmenu/rofi input box
|
||||
|
||||
## Dependencies
|
||||
- `dmenu` or `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
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
<a href="https://notnull.click/users/paul" rel="me">Fediverse</a>
|
13
archive/clipurr/clipurr.nimble
Normal file
13
archive/clipurr/clipurr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Clipboard manager for X11 or Wayland"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["clipurr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
184
archive/clipurr/src/clipurr.nim
Normal file
184
archive/clipurr/src/clipurr.nim
Normal file
|
@ -0,0 +1,184 @@
|
|||
import ../../globurrl
|
||||
import std/[strutils,os,db_sqlite,osproc]
|
||||
|
||||
const CLIP_DB = WM_TOOLS_DIR & "clipurr_cache.sqlite"
|
||||
const KEEP_ITEMS = 15
|
||||
|
||||
proc openDBConn(): DBConn
|
||||
|
||||
proc addClip(str: var string)
|
||||
|
||||
proc killOldRunningProcesses() =
|
||||
let x = execCmdEx("killall wl-paste clipnotify")
|
||||
echo x
|
||||
|
||||
|
||||
proc runDaemon() =
|
||||
echo "Starting Daemon..."
|
||||
if wayland:
|
||||
echo "Using Wl-paste"
|
||||
let cwd = getAppDir()
|
||||
let outp = execProcess("wl-paste -n -w " & cwd & "/clipurr set")
|
||||
else:
|
||||
var run = true
|
||||
while run:
|
||||
# TODO;
|
||||
# Check if WM is running otherwise the TTY will be spammed with "Using Clipnotify" text
|
||||
if XisRunning():
|
||||
echo "Using Clipnotify"
|
||||
let outp = execCmdEx("clipnotify")
|
||||
if outp.exitcode == 0:
|
||||
var content = getCurrentClipboardContent()
|
||||
addClip(content)
|
||||
|
||||
echo "Exiting Daemon..."
|
||||
|
||||
proc openDBConn(): DBConn =
|
||||
let db: DBconn = open(CLIP_DB,"","","")
|
||||
try:
|
||||
db.exec(sql"""create table if not exists
|
||||
clip_items (
|
||||
timestamp DATETIME NOT NULL,
|
||||
clip NVARCHAR(500) NOT NULL
|
||||
)
|
||||
""")
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
return db
|
||||
|
||||
proc clearHistory() =
|
||||
let db = openDBConn()
|
||||
|
||||
try:
|
||||
db.exec(sql"drop table if exists clip_items")
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
proc maintainDB() =
|
||||
return # order by and offset doesn't work unless certain sqlite compile time options set
|
||||
# will create a different way to do this
|
||||
try:
|
||||
let db = openDBConn()
|
||||
defer: db.close()
|
||||
db.exec(sql"""BEGIN""")
|
||||
db.exec(sql"delete from clip_items order by timestamp desc offset ?", KEEP_ITEMS)
|
||||
db.exec(sql"""COMMIT""")
|
||||
except:
|
||||
echo "Error cleaning DB : " & getCurrentExceptionMsg()
|
||||
|
||||
proc escapeClip(str: string): string =
|
||||
var clip = str
|
||||
clip = clip.replace("`","\\`")
|
||||
clip = clip.replace("\\n`","\\\\n`")
|
||||
clip = clip.replace("\x0A","\\x0A")
|
||||
clip = escape(clip)
|
||||
echo "CLIP : ", clip
|
||||
return strip(clip)
|
||||
|
||||
proc unescapeClip(str: string): string =
|
||||
var clip = str
|
||||
try:
|
||||
clip = unescape(clip)
|
||||
if contains(clip,"\\x0A"):
|
||||
echo "NEWLINE FOUND"
|
||||
let idx = find(clip, "\\x0A") - 1
|
||||
clip = clip[0 .. idx] & " ... more ..."
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
return strip(clip)
|
||||
|
||||
proc readClipFile(): seq[string] =
|
||||
var clips: seq[string] = @[]
|
||||
# let db = openDBConn()
|
||||
try:
|
||||
let db = openDBConn()
|
||||
defer: db.close()
|
||||
for row in db.fastRows(sql"select distinct(clip) from clip_items order by timestamp desc LIMIT ?", KEEP_ITEMS):
|
||||
var str = unescapeClip(row[0])
|
||||
clips.add(str)
|
||||
except:
|
||||
echo "Error Reading Clip File : " & getCurrentExceptionMsg()
|
||||
return clips
|
||||
|
||||
proc addClip(str: var string) =
|
||||
if str == "":
|
||||
return
|
||||
elif str[0] == '\x89':
|
||||
var t = str[1..3]
|
||||
echo "Is a ", $t, " file , not storing"
|
||||
str = "[" & t & " Image] (not stored)"
|
||||
try:
|
||||
str = escapeClip(str)
|
||||
echo "clipboard content : ", str
|
||||
let db = openDBConn()
|
||||
defer: db.close()
|
||||
db.exec(sql"""BEGIN""")
|
||||
db.exec(sql"""insert into clip_items (timestamp, clip)
|
||||
values (CURRENT_TIMESTAMP, ?)
|
||||
""", str)
|
||||
db.exec(sql"""COMMIT""")
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
return
|
||||
|
||||
proc getFullClipboardContent(str: string): string =
|
||||
var full = ""
|
||||
try:
|
||||
let db = openDBConn()
|
||||
defer: db.close()
|
||||
let text = "\"" & replace(str," ... more ...", "%") & "\""
|
||||
let stmt = """
|
||||
select clip
|
||||
from clip_items
|
||||
where clip like ?
|
||||
order by timestamp desc
|
||||
LIMIT 1"""
|
||||
var prep = db.prepare(stmt)
|
||||
prep.bindParams(text)
|
||||
let res = db.getAllRows(prep)
|
||||
for r in res:
|
||||
# may need to switch to a getRow or getValue method here as this is messy
|
||||
full = unescape(r[0])
|
||||
full = replace(full, "\\x0A","\x0A")
|
||||
break
|
||||
finalize(prep)
|
||||
except:
|
||||
echo "Error Reading Clip File : " & getCurrentExceptionMsg()
|
||||
|
||||
|
||||
return full
|
||||
|
||||
proc showClips() =
|
||||
let clips = readClipFile()
|
||||
let info = newInfo("Clipurr")
|
||||
let option = outputData(info, clips)
|
||||
if option != "":
|
||||
if contains(option, "... more ..."):
|
||||
let full = getFullClipboardContent(option)
|
||||
copyToClipboard(full)
|
||||
else:
|
||||
copyToClipboard(option)
|
||||
return
|
||||
|
||||
proc main() =
|
||||
for idx, arg in args:
|
||||
if arg == "daemon":
|
||||
killOldRunningProcesses()
|
||||
runDaemon()
|
||||
return
|
||||
if arg == "set":
|
||||
var content = getCurrentClipboardContent()
|
||||
addClip(content)
|
||||
return
|
||||
if arg == "clear":
|
||||
clearHistory()
|
||||
return
|
||||
showClips()
|
||||
return
|
||||
|
||||
block start:
|
||||
if isMainModule:
|
||||
main()
|
||||
|
||||
maintainDB()
|
13
archive/i3_wurrkspaces/i3_wurrkspaces.nimble
Normal file
13
archive/i3_wurrkspaces/i3_wurrkspaces.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Displays open windows in i3 workspaces"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["i3_wurrkspaces"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
173
archive/i3_wurrkspaces/src/i3_wurrkspaces.nim
Normal file
173
archive/i3_wurrkspaces/src/i3_wurrkspaces.nim
Normal file
|
@ -0,0 +1,173 @@
|
|||
import ../../globurrl
|
||||
import std/[osproc,json,strutils]
|
||||
|
||||
const I3_WORKSPACES = "i3-msg -t get_workspaces"
|
||||
const SWAY_WORKSPACES = "swaymsg -t get_workspaces"
|
||||
let WORKSPACES = if wayland: SWAY_WORKSPACES else: I3_WORKSPACES
|
||||
const I3_TREE = "i3-msg -t get_tree"
|
||||
const SWAY_TREE = "swaymsg -t get_tree"
|
||||
let TREE = if wayland: SWAY_TREE else: I3_TREE
|
||||
const VISIBLE = "#"
|
||||
const URGENT = "!"
|
||||
const FOCUSED = "%"
|
||||
|
||||
type
|
||||
Workspace = object
|
||||
num: int
|
||||
name: string
|
||||
focused: bool
|
||||
visible: bool
|
||||
output: string
|
||||
urgent: bool
|
||||
display_string: string
|
||||
apps: seq[string]
|
||||
applications: seq[Application]
|
||||
application: Application
|
||||
Application = object
|
||||
title: string
|
||||
class: string
|
||||
focused: bool
|
||||
urgent: bool
|
||||
|
||||
var my_workspaces: seq[Workspace]
|
||||
var current_workspace: int = 0
|
||||
|
||||
proc showWorkspaces()
|
||||
|
||||
proc buildString(ws: Workspace): string =
|
||||
var str = $ws.num & " |"
|
||||
# if ws.urgent or ws.application.urgent:
|
||||
if ws.application.urgent:
|
||||
str &= URGENT
|
||||
else:
|
||||
str &= " "
|
||||
if ws.focused or ws.application.focused:
|
||||
current_workspace = ws.num
|
||||
str &= FOCUSED
|
||||
# elif ws.visible:
|
||||
# str &= VISIBLE
|
||||
else:
|
||||
str &= " "
|
||||
str &= "| " & ws.output & " | "
|
||||
if ws.application.class != "":
|
||||
str &= ws.application.class & " " & ws.application.title & " | "
|
||||
else:
|
||||
str = ""
|
||||
# for app in ws.applications:
|
||||
# str &= app.class & " " & app.title & " | "
|
||||
return str
|
||||
|
||||
proc findWorkspace(workspace: string): Workspace =
|
||||
for ws in my_workspaces:
|
||||
if workspace == ws.display_string:
|
||||
return ws
|
||||
|
||||
proc switchWorkspace(workspace: string) =
|
||||
if workspace.contains("%"):
|
||||
return
|
||||
let ws = findWorkspace(workspace)
|
||||
if ws.num == current_workspace:
|
||||
return
|
||||
if wayland:
|
||||
let cmd = "swaymsg workspace " & $ws.num
|
||||
discard execCmd(cmd)
|
||||
else:
|
||||
let cmd = "i3-msg workspace " & $ws.num
|
||||
discard execCmd(cmd)
|
||||
showWorkspaces()
|
||||
|
||||
proc getApplication(node: JsonNode, ws: Workspace = Workspace()): Application =
|
||||
var app = Application()
|
||||
let window = node["window_properties"]
|
||||
app.title = window["title"].getStr()
|
||||
app.class = window["class"].getStr()
|
||||
app.focused = node["focused"].getBool()
|
||||
app.urgent = node["urgent"].getBool()
|
||||
#echo ws.num
|
||||
#echo app.title & " " & app.class
|
||||
return app
|
||||
|
||||
proc newWorkspace(node: JsonNode): Workspace =
|
||||
return Workspace(
|
||||
num: node["num"].getInt(),
|
||||
name: node["name"].getStr(),
|
||||
focused: node["focused"].getBool(),
|
||||
#visible: w["visible"].getBool(),
|
||||
urgent: node["urgent"].getBool(),
|
||||
output: node["output"].getStr(),
|
||||
)
|
||||
|
||||
proc findWorkspacesTree(node: JsonNode, parent: Workspace = Workspace()) =
|
||||
for channel in node["nodes"].getElems():
|
||||
### move this into for loop if want separate entry per window
|
||||
var ws: Workspace = Workspace()
|
||||
if parent.num > 0:
|
||||
ws = parent
|
||||
elif node{"type"}.getStr() == "workspace":
|
||||
if node["output"].getStr() == "__i3":
|
||||
return
|
||||
ws = newWorkspace(node)
|
||||
echo ws
|
||||
###
|
||||
echo channel
|
||||
if channel{"window_properties"} != nil:
|
||||
#or (wayland and `something that is the same as window_properties'):
|
||||
let app = getApplication(channel,ws)
|
||||
echo app
|
||||
if ws.name != "":
|
||||
#if app.focused:
|
||||
# ws.focused = true
|
||||
ws.applications.add(app)
|
||||
ws.application = app
|
||||
elif ws.num > 0 and len(channel{"nodes"}) > 0:
|
||||
findWorkspacesTree(channel,ws)
|
||||
else:
|
||||
findWorkspacesTree(channel)
|
||||
### move this into for loop if want separate entry per window
|
||||
if ws.name != "":
|
||||
ws.display_string = ws.buildString()
|
||||
if ws.display_string != "":
|
||||
my_workspaces.add(ws)
|
||||
###
|
||||
return
|
||||
|
||||
proc getTree() =
|
||||
let cur_workspaces = execCmdEx(TREE)
|
||||
if cur_workspaces.output != "":
|
||||
let root = parseJson(cur_workspaces.output)
|
||||
findWorkspacesTree(root)
|
||||
return
|
||||
|
||||
proc getWorkspaces(): seq[Workspace] =
|
||||
let cur_workspaces = execCmdEx(WORKSPACES)
|
||||
if cur_workspaces.output != "":
|
||||
let ws = parseJson(cur_workspaces.output)
|
||||
for w in ws:
|
||||
var space = Workspace(
|
||||
num: w["num"].getInt(),
|
||||
name: w["name"].getStr(),
|
||||
focused: w["focused"].getBool(),
|
||||
visible: w["visible"].getBool(),
|
||||
urgent: w["urgent"].getBool(),
|
||||
output: w["output"].getStr()
|
||||
)
|
||||
space.display_string = buildString(space)
|
||||
my_workspaces.add(space)
|
||||
return my_workspaces
|
||||
|
||||
proc showWorkspaces() =
|
||||
my_workspaces = @[]
|
||||
getTree()
|
||||
var info = newInfo("Wurrkspaces")
|
||||
var args: seq[string] = @[]
|
||||
for ws in my_workspaces:
|
||||
args.add(ws.display_string)
|
||||
let output = outputData(info,args)
|
||||
if output in args:
|
||||
switchWorkspace(output)
|
||||
|
||||
proc main() =
|
||||
showWorkspaces()
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
batturry/batturry.nimble
Normal file
13
batturry/batturry.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Shows battery percentage using dmenu"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["batturry"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,8 +1,5 @@
|
|||
import strutils
|
||||
|
||||
import ../common
|
||||
import ../common/colours
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[strutils,os]
|
||||
|
||||
const battery = "BAT0"
|
||||
const ok_fg = lightgreen
|
||||
|
@ -46,7 +43,7 @@ proc getCharge(): int =
|
|||
echo "Error getting battery level : " & getCurrentExceptionMsg()
|
||||
return charge
|
||||
|
||||
proc getDesign(charge: int, state: bool): string =
|
||||
proc getDesign(charge: int, state: bool): (string, string, string, string, string) =
|
||||
var icon = " "
|
||||
var icon_colour = ok_fg
|
||||
var col = default_fg
|
||||
|
@ -84,25 +81,46 @@ proc getDesign(charge: int, state: bool): string =
|
|||
icon = "x "
|
||||
|
||||
let main_text = icon & " " & $charge & "%"
|
||||
# This next line is here for i3bar purposes
|
||||
let html_text = "<span foreground=\"" & icon_colour & "\">" & icon & "</span>" & $charge & "%"
|
||||
|
||||
return main_text
|
||||
return (html_text,main_text, col, bg, border)
|
||||
|
||||
proc getOutput(charge: int, state: bool): Info =
|
||||
let main_text = get_design(charge, state)
|
||||
let (html_text,main_text,col,bg_col,highlight_col) = get_design(charge, state)
|
||||
var data = newInfo("Batturry")
|
||||
# TODO check if html text works with rofi
|
||||
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 getBatteryInfo() =
|
||||
var last_charge = -1
|
||||
var last_state = false
|
||||
while true:
|
||||
let charge = getCharge()
|
||||
let state = isCharging()
|
||||
if charge != last_charge or state != last_state:
|
||||
let data = getoutput(charge, state)
|
||||
outputData(data)
|
||||
last_charge = charge
|
||||
last_state = state
|
||||
if stoploop:
|
||||
break
|
||||
sleep(1000)
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
if batteryExists():
|
||||
getBatteryInfo()
|
||||
else:
|
||||
switchTwmMode()
|
||||
|
||||
if isMainModule:
|
||||
main()
|
||||
|
13
brightnurrs/brightnurrs.nimble
Normal file
13
brightnurrs/brightnurrs.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Shows and controls laptop brightness"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["brightnurrs"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
116
brightnurrs/src/brightnurrs.nim
Normal file
116
brightnurrs/src/brightnurrs.nim
Normal file
|
@ -0,0 +1,116 @@
|
|||
import ../../globurrl
|
||||
import std/[os,strutils,osproc,math]
|
||||
|
||||
const backlight = "intel_backlight"
|
||||
const default_bg = yellow
|
||||
const default_fg = black
|
||||
const BACKLIGHT_CMD = "xbacklight"
|
||||
const UP_X = BACKLIGHT_CMD & " -inc %v" # %v is amount by
|
||||
const DOWN_X = BACKLIGHT_CMD & " -dec %v" # %v is amount by
|
||||
const SET_X = BACKLIGHT_CMD & " -set %v" # %v is amount by
|
||||
const BACKLIGHT_CMD_WL = "brightnessctl"
|
||||
const UP_WL = BACKLIGHT_CMD_WL & " set %v%+"
|
||||
const DOWN_WL = BACKLIGHT_CMD_WL & " set %v%-"
|
||||
const SET_WL = BACKLIGHT_CMD_WL & " set %v%"
|
||||
var CMD = BACKLIGHT_CMD
|
||||
var UP = UP_X
|
||||
var DOWN = DOWN_X
|
||||
var SET = SET_X
|
||||
const default_value = "5"
|
||||
|
||||
proc getLimit(): int =
|
||||
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 = "🌑"
|
||||
case pcnt:
|
||||
of 85..100:
|
||||
icon = "🌕"
|
||||
of 75..85:
|
||||
icon = "🌖"
|
||||
of 50..75:
|
||||
icon = "🌗"
|
||||
of 35..50:
|
||||
icon = "🌘"
|
||||
else:
|
||||
icon = "🌑"
|
||||
let percent = toInt(round(pcnt,0))
|
||||
let text = icon & " " & $percent & "%"
|
||||
return text
|
||||
|
||||
proc brightnessUp() =
|
||||
let cmd = replace(UP,"%v",default_value)
|
||||
discard execCmd(cmd)
|
||||
proc brightnessDown() =
|
||||
let cmd = replace(DOWN,"%v",default_value)
|
||||
discard execCmd(cmd)
|
||||
|
||||
proc getBrightness*(run_once: bool = false) =
|
||||
var last_pcnt: float = 0
|
||||
while true:
|
||||
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("Brightnurrs")
|
||||
data.full_text = text
|
||||
data.selected_bg = default_fg
|
||||
data.selected_fg = default_bg
|
||||
# i3bar stuff
|
||||
data.border = default_fg
|
||||
let args = @["up", "down"]
|
||||
let option = outputData(data,args)
|
||||
if option in args:
|
||||
case option:
|
||||
of "up":
|
||||
brightnessUp()
|
||||
getBrightness(true)
|
||||
of "down":
|
||||
brightnessDown()
|
||||
getBrightness(true)
|
||||
else:
|
||||
try:
|
||||
let i = parseInt(option)
|
||||
let cmd = replace(SET,"%v",$i)
|
||||
discard execCmd(cmd)
|
||||
getBrightness(true)
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
if run_once:
|
||||
break
|
||||
if stoploop:
|
||||
break
|
||||
last_pcnt = pcnt
|
||||
sleep(1000)
|
||||
|
||||
proc main() =
|
||||
if limit == -1:
|
||||
switchTwmMode()
|
||||
return
|
||||
getBrightness()
|
||||
|
||||
if isMainModule:
|
||||
block start:
|
||||
if wayland:
|
||||
CMD = BACKLIGHT_CMD_WL
|
||||
UP = UP_WL
|
||||
DOWN = DOWN_WL
|
||||
SET = SET_WL
|
||||
for arg in args:
|
||||
case arg:
|
||||
of "up":
|
||||
brightnessUp()
|
||||
break start
|
||||
of "down":
|
||||
brightnessDown()
|
||||
break start
|
||||
|
||||
main()
|
13
calculaturr/calculaturr.nimble
Normal file
13
calculaturr/calculaturr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A simple dmenu calculator"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["calculaturr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,14 +1,9 @@
|
|||
import osproc
|
||||
import strutils
|
||||
import sequtils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[osproc,strutils,sequtils]
|
||||
|
||||
# using qalc as it has a lot of nice inbuilt features
|
||||
# may be nice to make it totally non-dependant on other things though
|
||||
|
||||
const exitSeq = @["---","exit"]
|
||||
proc doCalculation(calc: string) =
|
||||
var info = newInfo("Calculaturr")
|
||||
let ans_cmd_terse = "echo \"" & calc & "\" | qalc +u8 -terse -color=never | awk '!/^>/ && !/^$/ {gsub(/^[ \\t]+|[ \\t]+$/, \"\", $0); print}'"
|
||||
|
@ -19,16 +14,17 @@ proc doCalculation(calc: string) =
|
|||
ans_terse.output.stripLineEnd()
|
||||
let answers = @[strip(ans_full.output),
|
||||
strip(ans_terse.output)]
|
||||
let args = concat(answers,exitSeq)
|
||||
let args = concat(answers,@["exit"])
|
||||
var cmd = outputData(info, args)
|
||||
cmd.stripLineEnd()
|
||||
if cmd in answers:
|
||||
copyToClipboard(cmd)
|
||||
elif cmd in exitSeq or cmd == "":
|
||||
elif cmd == "exit" or cmd == "":
|
||||
return
|
||||
else:
|
||||
doCalculation(cmd)
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
var info = newInfo("Calculaturr")
|
||||
let args = @["exit"]
|
||||
let cmd = outputData(info, args)
|
||||
|
@ -36,3 +32,5 @@ proc go*() =
|
|||
doCalculation(cmd)
|
||||
return
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
calendurr/calendurr.nimble
Normal file
13
calendurr/calendurr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Displays the date in dmenu"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["calendurr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,10 +1,8 @@
|
|||
import times
|
||||
import osproc
|
||||
import re
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[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"
|
||||
|
@ -12,6 +10,9 @@ const cal_pos_y = "20"
|
|||
proc getObject(date: string): Info =
|
||||
var data = newInfo("Calendurr")
|
||||
data.full_text = date
|
||||
data.border = default_bg
|
||||
data.selected_bg = default_bg
|
||||
data.selected_fg = default_fg
|
||||
return data
|
||||
|
||||
proc newCalendar(): string =
|
||||
|
@ -23,7 +24,13 @@ proc newCalendar(): string =
|
|||
"""
|
||||
return c
|
||||
|
||||
proc openCalendar() =
|
||||
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", cal_pos_x)
|
||||
c = replace(c,re"%pos_y", cal_pos_y)
|
||||
|
@ -34,9 +41,12 @@ proc getDate*() =
|
|||
let data = getObject(date_today)
|
||||
let output = outputData(data)
|
||||
if output == date_today:
|
||||
openCalendar()
|
||||
dmenuCalendar()
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
getDate()
|
||||
|
||||
|
||||
if isMainModule:
|
||||
main()
|
||||
|
13
cmd_wrappurr/cmd_wrappurr.nimble
Normal file
13
cmd_wrappurr/cmd_wrappurr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A Command wrapper thing - i.e. run clipmenu/passmenu into dmenu with styling, sucks really"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["cmd_wrappurr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
22
cmd_wrappurr/src/cmd_wrappurr.nim
Normal file
22
cmd_wrappurr/src/cmd_wrappurr.nim
Normal file
|
@ -0,0 +1,22 @@
|
|||
import ../../globurrl
|
||||
import std/[strutils,osproc]
|
||||
|
||||
# Basically just a wrapper to style passmenu nicely
|
||||
proc main() =
|
||||
var info = newInfo(capitalizeAscii(run_command))
|
||||
let cmd = genMenuCmd(info)
|
||||
discard execCmd(cmd)
|
||||
return
|
||||
|
||||
if isMainModule:
|
||||
globurrl.wrappurr = true
|
||||
for idx, arg in args:
|
||||
case arg:
|
||||
of "-r", "--run":
|
||||
run_command = args[idx + 1]
|
||||
break
|
||||
else:
|
||||
echo "No command given, please run again with `[-r|--run] __cmd__`"
|
||||
|
||||
if run_command != "":
|
||||
main()
|
26
compile_urrl.sh
Executable file
26
compile_urrl.sh
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
build () {
|
||||
dir="$1"
|
||||
i="$2"
|
||||
cd "./$dir" || exit
|
||||
f=$(echo "$dir" | sed 's/\.\///')
|
||||
nimble install -y
|
||||
if [[ $i == "install" ]]; then
|
||||
cp -v "$f" "$HOME/.local/bin/$f"
|
||||
fi
|
||||
cd ../
|
||||
}
|
||||
|
||||
if [[ $2 != "" ]]; then
|
||||
build "$2" "$1"
|
||||
exit
|
||||
fi
|
||||
for dir in ./*; do
|
||||
if [ -d "$dir" ]; then
|
||||
if [[ "$dir" == "./" ]]; then
|
||||
continue
|
||||
fi
|
||||
build "$dir" "$1"
|
||||
fi
|
||||
done
|
13
emurrji/emurrji.nimble
Normal file
13
emurrji/emurrji.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "An emoji picker for dmenu/rofi"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["emurrji"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,10 +1,8 @@
|
|||
import ../lib/emurrjilist
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import lib/emurrjilist
|
||||
import std/[re]
|
||||
|
||||
import re
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
var info = newInfo("Emurrji")
|
||||
var args = getEmoji()
|
||||
args.add("exit")
|
||||
|
@ -18,3 +16,5 @@ proc go*() =
|
|||
copyToClipboard(emoji)
|
||||
return
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
furrytime/furrytime.nimble
Normal file
13
furrytime/furrytime.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Displays the fuzzy time in dmenu"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["furrytime"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,7 +1,28 @@
|
|||
import times
|
||||
import ../../globurrl
|
||||
import std/[times]
|
||||
|
||||
import ../model/info
|
||||
import ../output
|
||||
const default_bg = lightblue
|
||||
const default_fg = black
|
||||
|
||||
proc getHour(hr: int): string
|
||||
proc getMinute(min: int): string
|
||||
|
||||
proc getFuzzyTime(): string =
|
||||
let tm = now()
|
||||
var hr = tm.hour()
|
||||
let min = tm.minute()
|
||||
var link = "past"
|
||||
if min > 32 :
|
||||
link = "to"
|
||||
case hr:
|
||||
of 23:
|
||||
hr = 0
|
||||
else:
|
||||
hr = hr + 1
|
||||
if min >= 58 or min <= 02:
|
||||
return getHour(hr) & " " & getMinute(min)
|
||||
else:
|
||||
return getMinute(min) & " " & link & " " & getHour(hr)
|
||||
|
||||
proc getHour(hr: int): string =
|
||||
case hr:
|
||||
|
@ -35,7 +56,7 @@ proc getHour(hr: int): string =
|
|||
proc getMinute(min: int): string =
|
||||
case min:
|
||||
of 58,59,0,1,2:
|
||||
return "oclock"
|
||||
return "o'clock"
|
||||
of 3,4,5,6,7,53,54,55,56,57:
|
||||
return "five"
|
||||
of 8,9,10,11,12,48,49,50,51,52:
|
||||
|
@ -51,26 +72,14 @@ proc getMinute(min: int): string =
|
|||
else:
|
||||
return "error"
|
||||
|
||||
proc getFuzzyTime(): string =
|
||||
let tm = now()
|
||||
var hr = tm.hour()
|
||||
let min = tm.minute()
|
||||
var link = "past"
|
||||
if min > 32 :
|
||||
link = "to"
|
||||
case hr:
|
||||
of 23:
|
||||
hr = 0
|
||||
else:
|
||||
hr = hr + 1
|
||||
if min >= 58 or min <= 02:
|
||||
return getHour(hr) & " " & getMinute(min)
|
||||
else:
|
||||
return getMinute(min) & " " & link & " " & getHour(hr)
|
||||
|
||||
proc getObject(time: string): Info =
|
||||
var data = newInfo("Furry Time")
|
||||
data.full_text = time
|
||||
data.selected_bg = default_bg
|
||||
data.selected_fg = default_fg
|
||||
#i3bar stuff
|
||||
data.color = default_fg
|
||||
data.border = default_fg
|
||||
return data
|
||||
|
||||
proc show(time: string, next_fuzzy: bool = false) =
|
||||
|
@ -85,7 +94,10 @@ proc show(time: string, next_fuzzy: bool = false) =
|
|||
let t = now().format("HH:mm:ss")
|
||||
show(t, true)
|
||||
|
||||
proc go*() =
|
||||
|
||||
proc main() =
|
||||
let time = getFuzzyTime()
|
||||
show(time)
|
||||
|
||||
if isMainModule:
|
||||
main()
|
278
globurrl.nim
Normal file
278
globurrl.nim
Normal file
|
@ -0,0 +1,278 @@
|
|||
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
|
||||
args*: seq[string]
|
||||
Menu = object
|
||||
command: string
|
||||
bottom: string
|
||||
grab_kb: string
|
||||
i_case: string
|
||||
lines_shown: string
|
||||
monitor: string
|
||||
prompt: string
|
||||
font: string
|
||||
norm_bg: string
|
||||
norm_fg: string
|
||||
sel_bg: string
|
||||
sel_fg: string
|
||||
extra_cmd: string
|
||||
Tool* = enum
|
||||
ROFI = "rofi", DMENU = "dmenu"
|
||||
|
||||
const WM_TOOLS_DIR* = getHomeDir() & ".wm_tools/"
|
||||
const WM_TOOLS_SYNC_DIR = getHomeDir() & "/Nextcloud/.wm_tools_sync/"
|
||||
const background* = "#000000"
|
||||
const backgroundalt* = "#bb222222"
|
||||
const backgroundalt2* = "#bb333333"
|
||||
const foreground* = "#dfdfdf"
|
||||
const foregroundalt* = "#777"
|
||||
const foregroundalt2* = "#ccc"
|
||||
const black* = "#000000"
|
||||
const white* = "#FFFFFF"
|
||||
const yellow* = "#ffb52a"
|
||||
const red* = "#e60053"
|
||||
const purple* = "#9f78e1"
|
||||
const blue* = "#0a6cf5"
|
||||
const lightblue* = "#7296EF"
|
||||
const lighterblue* = "#B5DDF7"
|
||||
const green* = "#4b9901"
|
||||
const lightgreen* = "#00ff00"
|
||||
const grey* = "#dfdfdf"
|
||||
const darkgrey* = "#444"
|
||||
const primary* = yellow
|
||||
const secondary* = red
|
||||
const alert* = "#bd2c40"
|
||||
const font = "Hermit-12"
|
||||
const MAX_LINES = 20
|
||||
var loop* = false
|
||||
var stoploop* = true
|
||||
var tool* = ROFI
|
||||
var wrappurr* = false
|
||||
var run_command* = ""
|
||||
var wayland* = false
|
||||
|
||||
proc newInfo*(str: string = "Info"): Info =
|
||||
var title = str
|
||||
if tool == ROFI:
|
||||
title = title & " : "
|
||||
return Info(
|
||||
title: title,
|
||||
selected_fg: black,
|
||||
selected_bg: white,
|
||||
unselected_fg: white,
|
||||
unselected_bg: black,
|
||||
# next few are for i3bar use
|
||||
border: white,
|
||||
background: black,
|
||||
color: foreground,
|
||||
)
|
||||
|
||||
proc newMenuConfig(cmd: Tool = ROFI): Menu =
|
||||
var run = $cmd
|
||||
var menu = Menu()
|
||||
menu.command = run
|
||||
if cmd == ROFI:
|
||||
menu.command &= " -dmenu"
|
||||
menu.prompt = "-p"
|
||||
menu.i_case = "-i"
|
||||
menu.lines_shown = "-l"
|
||||
return menu
|
||||
|
||||
proc newRofiConfig(cmd: Tool = ROFI): Menu =
|
||||
var run = cmd
|
||||
var menu = newMenuConfig(run)
|
||||
#menu.extra_cmd = "-markup-rows" #-kb-row-select \"Tab\" -kb-row-tab \"\""
|
||||
return menu
|
||||
|
||||
proc newDmenuConfig(cmd: Tool = DMENU): Menu =
|
||||
var run = cmd
|
||||
var menu = newMenuConfig(run)
|
||||
menu.bottom = "-b"
|
||||
menu.grabkb = "-f"
|
||||
menu.monitor = "-m"
|
||||
menu.font = "-fn"
|
||||
menu.norm_bg = "-nb"
|
||||
menu.norm_fg = "-nf"
|
||||
menu.sel_bg = "-sb"
|
||||
menu.sel_fg = "-sf"
|
||||
return menu
|
||||
|
||||
proc newMenu(): Menu =
|
||||
#if wrappurr:
|
||||
# return newDmenuConfig(run_command)
|
||||
case tool:
|
||||
of ROFI:
|
||||
return newRofiConfig()
|
||||
of DMENU:
|
||||
return newDmenuConfig()
|
||||
return newMenuConfig()
|
||||
|
||||
proc debugLog*(str: string) =
|
||||
let f = open("/tmp/debug.txt",fmAppend)
|
||||
defer: f.close()
|
||||
f.writeLine(str)
|
||||
|
||||
proc checkWayland() =
|
||||
if getEnv("XDG_SESSION_TYPE") == "wayland":
|
||||
wayland = true
|
||||
|
||||
proc XisRunning*(): bool =
|
||||
if getEnv("XAUTHORITY") != "":
|
||||
echo "X IS RUNNING"
|
||||
echo getEnv("XAUTHORITY")
|
||||
return true
|
||||
return false
|
||||
|
||||
proc clearInput*(count: int = 1) =
|
||||
for x in countup(1, count):
|
||||
discard readLineFromStdin("")
|
||||
|
||||
proc getArguments*(): seq[string] =
|
||||
let args = commandLineParams()
|
||||
return args
|
||||
|
||||
proc stripQuotes*(str: string): string =
|
||||
return replace(str,"\"",""")
|
||||
|
||||
proc quote*(str: string): string =
|
||||
var text = str
|
||||
# May need to put some further work to escape some special chars here
|
||||
text = stripQuotes(text)
|
||||
|
||||
# Put leading and ending quote marks in
|
||||
return " \"" & text & "\" "
|
||||
# ^ Add a spaces ^ so the previous flag isn't touching
|
||||
|
||||
|
||||
proc markup(str: string): string =
|
||||
var text = str
|
||||
|
||||
return text
|
||||
|
||||
proc genMenuCmd*(data: Info, opts: varargs[string], rofi: bool = false): string =
|
||||
# Build dmenu/rofi command
|
||||
var cmd = ""
|
||||
var x_lines = len(opts) + 1
|
||||
# if the text is empty, we don't want to create a menu item of it
|
||||
if data.full_text != "":
|
||||
let text = markup(data.full_text)
|
||||
cmd &= text & "\n"
|
||||
else:
|
||||
x_lines -= 1
|
||||
for opt in opts:
|
||||
let text = markup(opt)
|
||||
cmd = cmd & text & "\n"
|
||||
cmd.removeSuffix("\n")
|
||||
|
||||
if x_lines > MAX_LINES:
|
||||
x_lines = MAX_LINES
|
||||
|
||||
cmd = "echo -e" & quote(cmd) & " | "
|
||||
|
||||
var menu = newMenu()
|
||||
cmd = cmd & menu.command & " "
|
||||
cmd = cmd & menu.extra_cmd & " "
|
||||
cmd = cmd & menu.i_case & " "
|
||||
cmd = cmd & menu.lines_shown & " " & $x_lines & " "
|
||||
cmd = cmd & menu.prompt & quote(data.title)
|
||||
cmd = cmd & menu.norm_bg & quote(data.unselected_bg)
|
||||
cmd = cmd & menu.norm_fg & quote(data.unselected_fg)
|
||||
cmd = cmd & menu.sel_bg & quote(data.selected_bg)
|
||||
cmd = cmd & menu.sel_fg & quote(data.selected_fg)
|
||||
cmd = cmd & menu.font & quote(font)
|
||||
echo cmd
|
||||
return cmd
|
||||
|
||||
|
||||
|
||||
proc runMenu*(data: Info, opts: varargs[string], dmenu: bool = false): string =
|
||||
let cmd = genMenuCmd(data, opts, dmenu)
|
||||
#echo cmd
|
||||
#
|
||||
# Run command and get output
|
||||
var output = execCmdEx(cmd)
|
||||
output.output.stripLineEnd()
|
||||
return output.output
|
||||
|
||||
proc copyToClipboard*(str: string) =
|
||||
if wayland:
|
||||
discard execCmd("wl-copy " & str)
|
||||
else:
|
||||
discard execCmd("echo -n " & quote(str) & " | xclip -selection clipboard")
|
||||
|
||||
proc getCurrentClipboardContent*(): string =
|
||||
var str = ""
|
||||
if wayland:
|
||||
let cur = execCmdEx("wl-paste")
|
||||
if cur.exitcode == 0:
|
||||
str = cur[0]
|
||||
else:
|
||||
echo cur
|
||||
else:
|
||||
let cur = execCmdEx("xsel -o -b")
|
||||
if cur.exitcode == 0:
|
||||
str = cur[0]
|
||||
else:
|
||||
echo cur
|
||||
return strip(str)
|
||||
|
||||
proc outputData*(data: Info, args: varargs[string]): string {.discardable.} =
|
||||
var output = ""
|
||||
if tool == DMENU:
|
||||
output = runMenu(data,args, dmenu = true)
|
||||
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 = runMenu(data,args)
|
||||
return output
|
||||
|
||||
proc getSyncDir*(): string =
|
||||
if existsOrCreateDir(WM_TOOLS_SYNC_DIR):
|
||||
echo "Sync Dir already exists"
|
||||
return WM_TOOLS_SYNC_DIR
|
||||
return WM_TOOLS_SYNC_DIR
|
||||
|
||||
proc checkCacheDir() =
|
||||
if not dirExists(WM_TOOLS_DIR):
|
||||
createDir(WM_TOOLS_DIR)
|
||||
|
||||
# At Start up:
|
||||
checkCacheDir()
|
||||
|
||||
|
||||
let args* = getArguments()
|
||||
for idx, arg in args:
|
||||
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
|
||||
tool = DMENU
|
||||
of "rofi":
|
||||
stoploop = true
|
||||
tool = ROFI
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
nimble install -y
|
||||
cp -v "wmtools" "$HOME/.local/bin/wmtools"
|
13
netwurrk/netwurrk.nimble
Normal file
13
netwurrk/netwurrk.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Display NIC IP address and link to manage NICs"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["netwurrk"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,12 +1,10 @@
|
|||
import os
|
||||
import osproc
|
||||
import strutils
|
||||
import sequtils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[os,osproc,strutils,sequtils]
|
||||
|
||||
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 getIP(nic: string): string =
|
||||
let cmd = "ifconfig " & nic & " | grep inet | awk -F\" \" '{print $2}' | head -1 | awk '{print $1}'"
|
||||
|
@ -31,6 +29,10 @@ proc getConnState(nic: string): (string, string) =
|
|||
|
||||
proc getObject(): Info =
|
||||
var data = newInfo("Netwurrk")
|
||||
data.selected_bg = default_bg
|
||||
data.selected_fg = default_fg
|
||||
# i3bar stuff
|
||||
data.border = default_bg
|
||||
return data
|
||||
|
||||
proc getNetInfo*(my_nics: seq[string]) =
|
||||
|
@ -57,6 +59,8 @@ proc getNics*(): seq[string] =
|
|||
return my_nics
|
||||
return @["no-nic"]
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
getNetInfo(getNics())
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
passwurrd/passwurrd.nimble
Normal file
13
passwurrd/passwurrd.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A new awesome nimble package"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["passwurrd"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,10 +1,5 @@
|
|||
import os
|
||||
import osproc
|
||||
import re
|
||||
import strutils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl.nim
|
||||
import std/[os,osproc,re,strutils]
|
||||
|
||||
const pw_store = getHomeDir() & ".password-store/"
|
||||
var passwords: seq[string] = @[]
|
||||
|
@ -25,9 +20,12 @@ proc getPasswords(): seq[string] =
|
|||
proc passwordToClipboard(password: string) =
|
||||
discard execCmd("pass show -c " & password)
|
||||
|
||||
proc go*() =
|
||||
proc main() =
|
||||
var info = newInfo("Passwurrd")
|
||||
var pws = getPasswords()
|
||||
let output = outputData(info,pws)
|
||||
if output in passwords:
|
||||
passwordToClipboard(output)
|
||||
|
||||
when isMainModule:
|
||||
main()
|
13
pingclurrk/pingclurrk.nimble
Normal file
13
pingclurrk/pingclurrk.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A ping clock - display current ping time"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["pingclurrk"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,11 +1,15 @@
|
|||
import osproc
|
||||
import re
|
||||
import strutils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[osproc, re, strutils]
|
||||
|
||||
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
|
||||
|
@ -43,13 +47,39 @@ proc getObject(ping: float): Info =
|
|||
var data = newInfo("Ping Clurrk")
|
||||
data.full_text = text
|
||||
# i3bar stuff
|
||||
data.color = default_fg
|
||||
data.border = default_bg
|
||||
data.background = black
|
||||
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 go*() =
|
||||
proc main() =
|
||||
let ping = get_ping()
|
||||
let data = getObject(ping)
|
||||
let output = outputData(data)
|
||||
if output == data.full_text:
|
||||
go()
|
||||
main()
|
||||
|
||||
if isMainModule:
|
||||
main()
|
4
pw_generaturr/nimbledeps/nimbledata2.json
Normal file
4
pw_generaturr/nimbledeps/nimbledata2.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 1,
|
||||
"reverseDeps": {}
|
||||
}
|
13
pw_generaturr/pw_generaturr.nimble
Normal file
13
pw_generaturr/pw_generaturr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A new awesome nimble package"
|
||||
license = "AGPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["pw_generaturr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 2.0.0"
|
65
pw_generaturr/src/pw_generaturr.nim
Normal file
65
pw_generaturr/src/pw_generaturr.nim
Normal file
|
@ -0,0 +1,65 @@
|
|||
|
||||
#import ../../globurrl
|
||||
|
||||
import httpclient
|
||||
import json
|
||||
import strutils
|
||||
import random
|
||||
import parseopt
|
||||
import os
|
||||
|
||||
var length = 4
|
||||
var number = 10
|
||||
var word_len = 5
|
||||
|
||||
proc getNumber(size: int = 4): string =
|
||||
var num = ""
|
||||
for _ in countup(1,size):
|
||||
randomize()
|
||||
let roll = rand(0..9)
|
||||
num &= $roll
|
||||
return num
|
||||
|
||||
proc parsePw(body: string) =
|
||||
let j = body.parseJson
|
||||
for pass in j.getElems:
|
||||
var p = pass.getStr.capitalizeAscii
|
||||
p &= getNumber(length)
|
||||
echo p
|
||||
|
||||
proc getPW() =
|
||||
var c = newHttpClient()
|
||||
try:
|
||||
let url = "https://random-word-api.herokuapp.com/word?number=" & $number & "&length=" & $word_len
|
||||
echo url
|
||||
let resp = c.get(url)
|
||||
if resp.status == $Http200:
|
||||
parsePw(resp.body)
|
||||
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
proc parseArgs() =
|
||||
var p = initOptParser(commandLineParams())
|
||||
while true:
|
||||
p.next()
|
||||
case p.kind
|
||||
of cmdEnd: break
|
||||
of cmdShortOption, cmdLongOption:
|
||||
if p.val == "":
|
||||
#echo "Option: ", p.key
|
||||
discard
|
||||
else:
|
||||
#echo "Option and value: ", p.key, ", ", p.val
|
||||
case p.key
|
||||
of "length":
|
||||
word_len = parseInt(p.val)
|
||||
of "number":
|
||||
number = parseInt(p.val)
|
||||
of cmdArgument:
|
||||
#echo "Argument: ", p.key
|
||||
discard
|
||||
|
||||
if isMainModule:
|
||||
parseArgs()
|
||||
getPW()
|
14
remmina_choosurr/remmina_choosurr.nimble
Normal file
14
remmina_choosurr/remmina_choosurr.nimble
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A Remmina client tool and opener"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["remmina_choosurr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
||||
requires "configparser >= 0.1.0"
|
|
@ -1,18 +1,20 @@
|
|||
import os
|
||||
import osproc
|
||||
import tables
|
||||
import algorithm
|
||||
|
||||
import ../../globurrl
|
||||
import std/[os,osproc,tables,algorithm]
|
||||
import configparser
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
|
||||
const REMMINA_DIR = getHomeDir() & ".local/share/remmina"
|
||||
const SWITCH_WS = false
|
||||
const REMMINA_WS = "4"
|
||||
|
||||
var sessions = initTable[string,string]()
|
||||
var names: seq[string] = @[]
|
||||
|
||||
proc main()
|
||||
|
||||
proc switchWorkspace() =
|
||||
if SWITCH_WS and REMMINA_WS != "":
|
||||
discard execCmd("i3-msg workspace number " & REMMINA_WS)
|
||||
|
||||
proc getRemminaFiles(): seq[string] =
|
||||
if len(names) < 1:
|
||||
for file in walkFiles(REMMINA_DIR & "/*.remmina"):
|
||||
|
@ -36,8 +38,6 @@ proc startRemmina(conn: string) =
|
|||
let session = sessions[conn]
|
||||
discard execCmd("remmina -c " & quote(session))
|
||||
|
||||
proc go*() # adding as need to refer back to it in selectRemmina
|
||||
|
||||
proc selectRemmina(conn: string) =
|
||||
var info = newInfo("Remmina Choosurr : " & conn)
|
||||
let args = @["connect", "edit", "back"]
|
||||
|
@ -51,9 +51,11 @@ proc selectRemmina(conn: string) =
|
|||
editRemmina(conn)
|
||||
#switchWorkspace()
|
||||
of "back":
|
||||
go()
|
||||
main()
|
||||
|
||||
proc go*() =
|
||||
|
||||
|
||||
proc main() =
|
||||
var info = newInfo("Remmina Choosurr")
|
||||
var args: seq[string] = getRemminaFiles()
|
||||
args.add("new")
|
||||
|
@ -66,3 +68,7 @@ proc go*() =
|
|||
elif output in names:
|
||||
selectRemmina(output)
|
||||
return
|
||||
return
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
screenshurrt/screenshurrt.nimble
Normal file
13
screenshurrt/screenshurrt.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "A screenshot client, works on both X11 and Wayland"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["screenshurrt"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,21 +1,23 @@
|
|||
import times
|
||||
import os
|
||||
import osproc
|
||||
import strutils
|
||||
import sequtils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../parser
|
||||
import ../model/screenshot
|
||||
import ../../globurrl
|
||||
import std/[times,os,osproc,strutils,sequtils]
|
||||
|
||||
var screenshot_type = ""
|
||||
const TYPES = @["region", "fullscreen", "window"]
|
||||
const DATE_FORMAT = "yyyyMMdd-hhmmss"
|
||||
const FILENAME = "Screenshot-%d.png"
|
||||
const TEMP_DIR = "/tmp/"
|
||||
const SCREENSHOT_CMD = "maim -u %s --format png %f"
|
||||
var RUN_CMD = SCREENSHOT_CMD
|
||||
let DATE_STR = now().format(DATE_FORMAT)
|
||||
# where %s is an extra flag or process, i.e. xdotool for getting active window
|
||||
const ACTIVE_WINDOW_CMD = "-i $(xdotool getactivewindow)"
|
||||
const REGION_FLAG = "-s"
|
||||
var REGION_CMD = REGION_FLAG
|
||||
const CLIPBOARD_CMD = "xclip -selection clipboard -t image/png"
|
||||
var CLIP_CMD = CLIPBOARD_CMD
|
||||
|
||||
proc saveToClipboard(filename: string) =
|
||||
let cmd = "cat " & filename & " | " & CLIPBOARD_CMD
|
||||
let cmd = "cat " & filename & " | " & CLIP_CMD
|
||||
let status = execCmd(cmd)
|
||||
if status == 0 and fileExists(filename):
|
||||
removeFile(filename)
|
||||
|
@ -52,44 +54,42 @@ proc showScreenshotSaveSel(filename: string) =
|
|||
openFile(filename)
|
||||
return
|
||||
|
||||
proc showScreenshotSizeSel(): ScreenshotSize =
|
||||
proc showScreenshotTypeSel() =
|
||||
let info = newInfo("Screenshurrt type")
|
||||
let args = concat(ScreenshotSizes(),@["---","exit"])
|
||||
let args = concat(TYPES,@["---","exit"])
|
||||
let choice = outputData(info,args)
|
||||
if choice.isScreenshotSize():
|
||||
return choice.toScreenshotSize()
|
||||
if choice in TYPES:
|
||||
screenshot_type = choice
|
||||
elif choice == "---":
|
||||
return showScreenshotSizeSel()
|
||||
showScreenshotTypeSel()
|
||||
elif choice == "exit":
|
||||
quit(0)
|
||||
else:
|
||||
quit(0)
|
||||
return
|
||||
return
|
||||
|
||||
proc takeScreenshot(ss: Screenshot) =
|
||||
proc takeScreenshot() =
|
||||
let filename = TEMP_DIR & FILENAME.replace("%d",DATE_STR)
|
||||
var cmd = ss.tool.command
|
||||
case ss.size:
|
||||
of Window:
|
||||
cmd = ss.tool.activeWindowCommand()
|
||||
of Region:
|
||||
cmd = ss.tool.regionCommand()
|
||||
var cmd = RUN_CMD.replace("%f",filename)
|
||||
case screenshot_type:
|
||||
of "window":
|
||||
cmd = cmd.replace("%s",ACTIVE_WINDOW_CMD)
|
||||
of "region":
|
||||
cmd = cmd.replace("%s",REGION_CMD)
|
||||
else: #fullscreen
|
||||
cmd = cmd.replace("%s","")
|
||||
# sleep for a bit otherwise the screen shot could grabs dmenu as well
|
||||
# sleep for a bit otherwise the screen shot grabs dmenu as well
|
||||
sleep(1*500)
|
||||
cmd = cmd.replace("%f",filename)
|
||||
echo "Running command:\n" & cmd
|
||||
|
||||
let status = execCmd(cmd)
|
||||
if status == 0:
|
||||
showScreenshotSaveSel(filename)
|
||||
return
|
||||
|
||||
proc go*() =
|
||||
var ss = parseScreenshotArgs()
|
||||
if ss.size == None:
|
||||
ss.size = showScreenshotSizeSel()
|
||||
if ss.size != None:
|
||||
ss.takeScreenshot()
|
||||
|
||||
if isMainModule:
|
||||
go()
|
||||
for arg in args:
|
||||
if arg in TYPES:
|
||||
screenshot_type = arg
|
||||
break
|
||||
if screenshot_type == "":
|
||||
showScreenshotTypeSel()
|
||||
if screenshot_type != "":
|
||||
takeScreenshot()
|
|
@ -1,11 +0,0 @@
|
|||
import model/config
|
||||
import model/tool
|
||||
import model/info
|
||||
|
||||
export config
|
||||
export tool
|
||||
export info
|
||||
|
||||
var myConfig* = newConfig()
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
const background* = "#000000"
|
||||
const backgroundalt* = "#bb222222"
|
||||
const backgroundalt2* = "#bb333333"
|
||||
const foreground* = "#dfdfdf"
|
||||
const foregroundalt* = "#777"
|
||||
const foregroundalt2* = "#ccc"
|
||||
const black* = "#000000"
|
||||
const white* = "#FFFFFF"
|
||||
const yellow* = "#ffb52a"
|
||||
const red* = "#e60053"
|
||||
const purple* = "#9f78e1"
|
||||
const blue* = "#0a6cf5"
|
||||
const lightblue* = "#7296EF"
|
||||
const lighterblue* = "#B5DDF7"
|
||||
const green* = "#4b9901"
|
||||
const lightgreen* = "#00ff00"
|
||||
const grey* = "#dfdfdf"
|
||||
const darkgrey* = "#444"
|
||||
const primary* = yellow
|
||||
const secondary* = red
|
||||
const alert* = "#bd2c40"
|
|
@ -1,55 +0,0 @@
|
|||
|
||||
import common
|
||||
import util/furrytime
|
||||
import util/pingclock
|
||||
import util/batturry
|
||||
import util/volurrme
|
||||
import util/netwurrk
|
||||
import util/wirelurrs
|
||||
import util/emurrji
|
||||
import util/calendurr
|
||||
import util/remminurr
|
||||
import util/passwurrd
|
||||
import util/pw_generaturr
|
||||
import util/temperaturr
|
||||
import util/screenshurrt
|
||||
import util/calculaturr
|
||||
import util/brightnurrs
|
||||
import util/tideurrl
|
||||
|
||||
proc dispatch*(cfg: Config) =
|
||||
case cfg.run
|
||||
of FurryTime:
|
||||
furrytime.go()
|
||||
of PingClock:
|
||||
pingclock.go()
|
||||
of Batturry:
|
||||
batturry.go()
|
||||
of Volurrme:
|
||||
volurrme.go()
|
||||
of Netwurrk:
|
||||
netwurrk.go()
|
||||
of Wirelurrs:
|
||||
wirelurrs.go()
|
||||
of Emurrji:
|
||||
emurrji.go()
|
||||
of Calendurr:
|
||||
calendurr.go()
|
||||
of Remminurr:
|
||||
remminurr.go()
|
||||
of Passwurrd:
|
||||
passwurrd.go()
|
||||
of PasswurrdGeneraturr:
|
||||
pw_generaturr.go()
|
||||
of Temperaturr:
|
||||
temperaturr.go()
|
||||
of Screenshurrt:
|
||||
screenshurrt.go()
|
||||
of Calculaturr:
|
||||
calculaturr.go()
|
||||
of Brightnurrs:
|
||||
brightnurrs.go()
|
||||
of Tideurrl:
|
||||
tideurrl.go()
|
||||
else:
|
||||
echo "No valid run command given"
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
type
|
||||
BrightnessArg* = enum
|
||||
None,
|
||||
BrightUp,
|
||||
BrightDown
|
|
@ -1,49 +0,0 @@
|
|||
import os
|
||||
import parsetoml
|
||||
|
||||
import tool
|
||||
import screenshot
|
||||
|
||||
type
|
||||
Config* = ref object
|
||||
exec*: string
|
||||
run*: Tool
|
||||
max_lines*: int
|
||||
prepend*: bool
|
||||
screenshot_tool*: ScreenshotTool
|
||||
|
||||
let config_dir* = getHomeDir() & ".config/wm_tools/"
|
||||
let config_file* = config_dir & "config.toml"
|
||||
|
||||
proc `$`(c: Config): string =
|
||||
var str = "exec = \"" & c.exec & "\"\n"
|
||||
str &= "prepend = " & $c.prepend & "\n"
|
||||
str &= "screenshot_tool = \"" & $c.screenshot_tool & "\"\n"
|
||||
str &= "max_lines = " & $c.max_lines
|
||||
str &= "\n"
|
||||
return str
|
||||
|
||||
proc newConfig*(): Config =
|
||||
var cfg = Config()
|
||||
cfg.exec = "rofi -dmenu"
|
||||
cfg.prepend = true
|
||||
cfg.screenshot_tool = Maim
|
||||
cfg.max_lines = 20
|
||||
|
||||
discard existsOrCreateDir(config_dir)
|
||||
if not fileExists(config_file):
|
||||
writeFile(config_file,$cfg)
|
||||
else:
|
||||
let content = readFile(config_file)
|
||||
try:
|
||||
let toml = parseString(content)
|
||||
if toml.hasKey("exec"):
|
||||
cfg.exec = toml["exec"].getStr
|
||||
if toml.hasKey("max_lines"):
|
||||
cfg.max_lines = toml["max_lines"].getInt
|
||||
if toml.hasKey("screenshot_tool"):
|
||||
cfg.screenshot_tool = toml["screenshot_tool"].getStr.toScreenshotTool
|
||||
except:
|
||||
echo "Error with Config File:"
|
||||
echo getCurrentExceptionMsg()
|
||||
return cfg
|
|
@ -1,11 +0,0 @@
|
|||
type
|
||||
Info* = object
|
||||
title*: string
|
||||
full_text*: string
|
||||
html_text*: string
|
||||
short_text*: string
|
||||
args*: seq[string]
|
||||
|
||||
proc newInfo*(str: string = "Info"): Info =
|
||||
var title = str
|
||||
return Info(title: title)
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
type
|
||||
PWGen* = object
|
||||
to_terminal*: bool
|
||||
word_len*: int
|
||||
digits*: int
|
||||
number*: int
|
||||
|
||||
proc newPWGen*(): PWGen =
|
||||
var pw = PWGen()
|
||||
pw.word_len = 5
|
||||
pw.digits = 4
|
||||
pw.number = 10
|
||||
return pw
|
|
@ -1,72 +0,0 @@
|
|||
|
||||
import sequtils
|
||||
import strutils
|
||||
|
||||
type
|
||||
Screenshot* = object
|
||||
size*: ScreenshotSize
|
||||
tool*: ScreenshotTool
|
||||
ScreenshotSize* = enum
|
||||
None = ""
|
||||
Region = "region",
|
||||
Full = "fullscreen",
|
||||
Window = "window"
|
||||
ScreenshotTool* = enum
|
||||
None = ""
|
||||
Maim = "maim"
|
||||
|
||||
proc newScreenshot*(): Screenshot =
|
||||
var ss = Screenshot()
|
||||
ss.tool = Maim
|
||||
ss.size = None
|
||||
return ss
|
||||
|
||||
proc toScreenshotSize*(str: string): ScreenshotSize =
|
||||
case str
|
||||
of "region": return Region
|
||||
of "fullscreen": return Full
|
||||
of "window": return Window
|
||||
else: return None
|
||||
|
||||
proc isScreenshotSize*(str: string): bool =
|
||||
return str.toScreenshotSize != None
|
||||
|
||||
proc ScreenshotSizes*(): seq[string] =
|
||||
var sizes: seq[string] = @[]
|
||||
for item in ScreenshotSize.toSeq:
|
||||
if item != None:
|
||||
sizes.add($item)
|
||||
return sizes
|
||||
|
||||
proc toScreenshotTool*(str: string): ScreenshotTool =
|
||||
case str
|
||||
of "maim": return Maim
|
||||
else: return None
|
||||
|
||||
proc isScreenshotTool*(str: string): bool =
|
||||
return str.toScreenshotTool != None
|
||||
|
||||
proc command*(tool: ScreenshotTool): string =
|
||||
case tool
|
||||
of Maim: return "maim -u %s --format png %f"
|
||||
else: return ""
|
||||
|
||||
proc activeWindowCommand*(tool: ScreenshotTool): string =
|
||||
var cmd = tool.command()
|
||||
# where %s is an extra flag or process, i.e. xdotool for getting active window
|
||||
case tool
|
||||
of Maim:
|
||||
cmd = cmd.replace("%s","-i $(xdotool getactivewindow)")
|
||||
else: return cmd
|
||||
return cmd
|
||||
|
||||
proc regionCommand*(tool: ScreenshotTool): string =
|
||||
var cmd = tool.command()
|
||||
case tool
|
||||
of Maim:
|
||||
cmd = cmd.replace("%s","-s")
|
||||
else: return cmd
|
||||
return cmd
|
||||
|
||||
const CLIPBOARD_CMD* = "xclip -selection clipboard -t image/png"
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import times
|
||||
|
||||
const TIDE_URL* = "https://www.tidetimes.org.uk/%LOC-tide-times"
|
||||
const DEFAULT_LOC* = "exmouth-dock"
|
||||
|
||||
type
|
||||
Tide* = ref object
|
||||
state*: string
|
||||
time*: string
|
||||
height*: string
|
||||
tomorrow*: bool
|
||||
TideList* = ref object
|
||||
tides*: seq[Tide]
|
||||
url*: string
|
||||
last_updated*: DateTime
|
||||
location*: string
|
||||
|
||||
proc newTideList*(): TideList =
|
||||
var tl = TideList()
|
||||
tl.url = TIDE_URL
|
||||
tl.location = DEFAULT_LOC
|
||||
return tl
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
type
|
||||
Tool* = enum
|
||||
None,
|
||||
FurryTime,
|
||||
PingClock,
|
||||
Batturry,
|
||||
Volurrme,
|
||||
Netwurrk,
|
||||
Wirelurrs,
|
||||
Emurrji,
|
||||
Calendurr,
|
||||
Remminurr,
|
||||
Passwurrd,
|
||||
PasswurrdGeneraturr,
|
||||
Temperaturr,
|
||||
Screenshurrt,
|
||||
Calculaturr,
|
||||
Brightnurrs,
|
||||
Tideurrl
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
type
|
||||
VolArg* = enum
|
||||
None, VolUp, VolDown, VolMute
|
|
@ -1,63 +0,0 @@
|
|||
import osproc
|
||||
import strutils
|
||||
|
||||
import common
|
||||
|
||||
proc stripQuotes(str: string): string =
|
||||
var text = replace(str,"\"",""")
|
||||
return text
|
||||
|
||||
proc quote*(str: string): string =
|
||||
var text = str
|
||||
# May need to put some further work to escape some special chars here
|
||||
text = stripQuotes(text)
|
||||
|
||||
# Put leading and ending quote marks in
|
||||
return " \"" & text & "\" "
|
||||
# ^ Add a spaces ^ so the previous flag isn't touching
|
||||
|
||||
proc markup(str: string): string =
|
||||
# Placeholder proc for future use
|
||||
var text = stripQuotes(str)
|
||||
return text
|
||||
|
||||
proc copyToClipboard*(str: string): bool {.discardable.} =
|
||||
let ok = execCmd("echo -n " & quote(str) & " | xclip -selection clipboard")
|
||||
return ok == 0
|
||||
|
||||
proc genMenuCmd(data: Info, opts: varargs[string]): string =
|
||||
var cmd = ""
|
||||
var x_lines = len(opts) + 1
|
||||
# if the text is empty, we don't want to create a menu item of it
|
||||
if data.full_text != "":
|
||||
let text = markup data.full_text
|
||||
cmd &= text & "\n"
|
||||
else:
|
||||
x_lines -= 1
|
||||
for opt in opts:
|
||||
let text = markup opt
|
||||
cmd &= text & "\n"
|
||||
|
||||
cmd.removeSuffix("\n")
|
||||
|
||||
if x_lines > myConfig.max_lines: x_lines = myConfig.max_lines
|
||||
|
||||
if myConfig.prepend:
|
||||
cmd = "echo -e" & quote(cmd) & "| "
|
||||
cmd &= myConfig.exec
|
||||
cmd &= " -i" # set case insensitive
|
||||
cmd &= " -p" & quote(data.title)
|
||||
cmd &= "-l " & $x_lines
|
||||
echo "Sending command:\n" & cmd
|
||||
return cmd
|
||||
|
||||
proc runExec(data: Info, opts: varargs[string]): string =
|
||||
let cmd = genMenuCmd(data, opts)
|
||||
var output = execCmdEx(cmd)
|
||||
echo "Output:\n" & $output
|
||||
output.output.stripLineEnd()
|
||||
return output.output
|
||||
|
||||
proc outputData*(data: Info, args: varargs[string,`$`]): string {.discardable.} =
|
||||
var output = runExec(data,args)
|
||||
return output
|
179
src/parser.nim
179
src/parser.nim
|
@ -1,179 +0,0 @@
|
|||
import os
|
||||
|
||||
import argparse
|
||||
|
||||
import common
|
||||
import model/pwgen
|
||||
import model/volume
|
||||
import model/brightness
|
||||
import model/screenshot
|
||||
import model/tides
|
||||
|
||||
proc parseArgs*() =
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("WMTools : a set of tools to output option to your program of choice i.e. Rofi")
|
||||
arg("input",help="the tool to run, i.e. furrytime, pingclock, volurrme, etc.")
|
||||
arg("others", nargs = -1)
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
case opts.input
|
||||
of "furrytime", "fuzzytime", "time":
|
||||
myConfig.run = FurryTime
|
||||
of "pingclock", "pingclurrk", "ping":
|
||||
myConfig.run = PingClock
|
||||
of "batturry", "battery", "bat":
|
||||
myConfig.run = Batturry
|
||||
of "volurrme", "volume", "vol":
|
||||
myConfig.run = Volurrme
|
||||
of "netwurrk", "network", "net":
|
||||
myConfig.run = Netwurrk
|
||||
of "wirelurrs", "wireless", "wifi":
|
||||
myConfig.run = Wirelurrs
|
||||
of "emurrji", "emoji":
|
||||
myConfig.run = Emurrji
|
||||
of "calendurr", "calender", "cal":
|
||||
myConfig.run = Calendurr
|
||||
of "remminurr", "remmina", "rdp", "rem":
|
||||
myConfig.run = Remminurr
|
||||
of "passwurrd", "password", "pw":
|
||||
myConfig.run = Passwurrd
|
||||
of "passwurrdgeneraturr", "passwordgenerator", "pwgen":
|
||||
myConfig.run = PasswurrdGeneraturr
|
||||
of "temperaturr", "temperature", "temp":
|
||||
myConfig.run = Temperaturr
|
||||
of "screenshurrt", "screenshot", "screeny":
|
||||
myConfig.run = Screenshurrt
|
||||
of "calculaturr", "calculator", "calc":
|
||||
myConfig.run = Calculaturr
|
||||
of "brightnurrs", "brightness", "bright":
|
||||
myConfig.run = Brightnurrs
|
||||
of "tideurrl", "tides":
|
||||
myConfig.run = Tideurrl
|
||||
else:
|
||||
echo p.help
|
||||
quit(1)
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
|
||||
proc parseVolArgs*(): VolArg =
|
||||
var arg: VolArg
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("Args for volurrme")
|
||||
arg("volurrme",help="can only ever be 'volurrme' as you won't have gotten this far otherwise")
|
||||
arg("adjust",help="up, down, or mute",default=some(""))
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
case opts.adjust
|
||||
of "volup", "up":
|
||||
arg = VolUp
|
||||
of "voldown", "down":
|
||||
arg = VolDown
|
||||
of "mute","volmute":
|
||||
arg = VolMute
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
return arg
|
||||
|
||||
proc parseBrightnessArgs*(): BrightnessArg =
|
||||
var arg: BrightnessArg
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("Args for volurrme")
|
||||
arg("brightnurrs",help="can only ever be 'brightnurrs' as you won't have gotten this far otherwise")
|
||||
arg("adjust",help="up, down, or mute",default=some(""))
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
case opts.adjust
|
||||
of "up":
|
||||
arg = BrightUp
|
||||
of "down":
|
||||
arg = BrightDown
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
return arg
|
||||
|
||||
proc parsePWGenArgs*(): PWGen =
|
||||
var gen = newPWGen()
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("Args for pw_generaturr")
|
||||
arg("pwgen",help="can only ever be 'pwgen' as you won't have gotten this far otherwise")
|
||||
flag("-o","--output",help="outputs to terminal instead of something else")
|
||||
option("-l","--length",help="Length of the word part of the password")
|
||||
option("-d","--digits",help="Length of the number part of the password",default=some(""))
|
||||
option("-n","--number",help="Number of passwords to return")
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
if opts.length != "":
|
||||
gen.word_len = parseInt(opts.length)
|
||||
if opts.digits != "":
|
||||
gen.digits = parseInt(opts.digits)
|
||||
if opts.number != "":
|
||||
gen.number = parseInt(opts.number)
|
||||
gen.to_terminal = not opts.output
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
return gen
|
||||
|
||||
proc parseScreenshotArgs*(): Screenshot =
|
||||
var ss = newScreenshot()
|
||||
ss.tool = myConfig.screenshot_tool
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("Args for screenshurrt")
|
||||
arg("screenshurrt",help="can only ever be 'screenshurrt' as you won't have gotten this far otherwise")
|
||||
option("-s","--size",help="size/region i.e. region, fullscreen or window")
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
if opts.size != "":
|
||||
ss.size = opts.size.toScreenshotSize()
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
return ss
|
||||
|
||||
proc parseTideurrlArgs*(): TideList =
|
||||
var t = newTideList()
|
||||
let params = commandLineParams()
|
||||
var p = newParser:
|
||||
help("Args for tideurrl")
|
||||
arg("tideurrl",help="can only ever be 'tideurrl' as you won't have gotten this far otherwise")
|
||||
option("-l","--loc",help="location name")
|
||||
try:
|
||||
var opts = p.parse(params)
|
||||
if opts.loc != "":
|
||||
t.location = opts.loc
|
||||
except ShortCircuit as err:
|
||||
if err.flag == "argparse_help":
|
||||
echo err.help
|
||||
quit(1)
|
||||
except UsageError:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
return t
|
|
@ -1,98 +0,0 @@
|
|||
import os
|
||||
import strutils
|
||||
import osproc
|
||||
import math
|
||||
|
||||
import ../common
|
||||
import ../parser
|
||||
import ../model/brightness
|
||||
import ../output
|
||||
|
||||
#const backlight = "intel_backlight"
|
||||
const BACKLIGHT_CMD = "xbacklight"
|
||||
const UP = BACKLIGHT_CMD & " -inc %v" # %v is amount by
|
||||
const DOWN = BACKLIGHT_CMD & " -dec %v" # %v is amount by
|
||||
const SET = BACKLIGHT_CMD & " -set %v" # %v is amount by
|
||||
const default_value = "5"
|
||||
|
||||
proc getBacklight(): string =
|
||||
for dir in walkDir("/sys/class/backlight"):
|
||||
echo dir.path
|
||||
var bl = dir.path.replace("/sys/class/backlight/","")
|
||||
echo bl
|
||||
return bl
|
||||
|
||||
proc getLimit(backlight: string): int =
|
||||
try:
|
||||
if backlight != "":
|
||||
let back_l = readFile("/sys/class/backlight/" & backlight & "/max_brightness")
|
||||
return parseInt(strip(back_l))
|
||||
except:
|
||||
echo "Error getting backlight max : ", getCurrentExceptionMsg()
|
||||
return -1
|
||||
|
||||
|
||||
proc getDesign(pcnt: float): string =
|
||||
var icon = "🌑"
|
||||
case pcnt:
|
||||
of 85..100:
|
||||
icon = "🌕"
|
||||
of 75..85:
|
||||
icon = "🌖"
|
||||
of 50..75:
|
||||
icon = "🌗"
|
||||
of 35..50:
|
||||
icon = "🌘"
|
||||
else:
|
||||
icon = "🌑"
|
||||
let percent = toInt(round(pcnt,0))
|
||||
let text = icon & " " & $percent & "%"
|
||||
return text
|
||||
|
||||
proc brightnessUp() =
|
||||
let cmd = replace(UP,"%v",default_value)
|
||||
discard execCmd(cmd)
|
||||
proc brightnessDown() =
|
||||
let cmd = replace(DOWN,"%v",default_value)
|
||||
discard execCmd(cmd)
|
||||
|
||||
proc getBrightness*(backlight: string) =
|
||||
var data = newInfo("Brightnurrs")
|
||||
if backlight == "":
|
||||
data.full_text = "No Backlight Found"
|
||||
discard outputData(data)
|
||||
quit(1)
|
||||
let limit = getLimit(backlight)
|
||||
let current = parseInt(strip(readFile("/sys/class/backlight/" & backlight & "/actual_brightness")))
|
||||
let pcnt = (current/limit)*100
|
||||
let text = getDesign(pcnt)
|
||||
data.full_text = text
|
||||
let args = @["up", "down"]
|
||||
let option = outputData(data,args)
|
||||
if option in args:
|
||||
case option:
|
||||
of "up":
|
||||
brightnessUp()
|
||||
backlight.getBrightness()
|
||||
of "down":
|
||||
brightnessDown()
|
||||
backlight.getBrightness()
|
||||
else:
|
||||
try:
|
||||
let i = parseInt(option)
|
||||
let cmd = replace(SET,"%v",$i)
|
||||
discard execCmd(cmd)
|
||||
backlight.getBrightness()
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
proc go*() =
|
||||
let backlight = getBacklight()
|
||||
let barg = parseBrightnessArgs()
|
||||
case barg:
|
||||
of BrightUp:
|
||||
brightnessUp()
|
||||
of BrightDown:
|
||||
brightnessDown()
|
||||
else:
|
||||
backlight.getBrightness()
|
|
@ -1,65 +0,0 @@
|
|||
|
||||
import httpclient
|
||||
import json
|
||||
import strutils
|
||||
import random
|
||||
|
||||
import ../parser
|
||||
import ../model/pwgen
|
||||
import ../common
|
||||
import ../output
|
||||
|
||||
var passwords: seq[string]
|
||||
proc getNumber(size: int = 4): string =
|
||||
var num = ""
|
||||
for _ in countup(1,size):
|
||||
randomize()
|
||||
let roll = rand(0..9)
|
||||
num &= $roll
|
||||
return num
|
||||
|
||||
proc parsePasswords(body: string, digits: int) =
|
||||
passwords = @[]
|
||||
let j = body.parseJson
|
||||
for pass in j.getElems:
|
||||
var p = pass.getStr.capitalizeAscii
|
||||
p &= getNumber(digits)
|
||||
passwords.add(p)
|
||||
|
||||
proc getPasswords(pwgen: PWGen) =
|
||||
var c = newHttpClient()
|
||||
try:
|
||||
let url = "https://random-word-api.herokuapp.com/word?number=" & $pwgen.number & "&length=" & $pwgen.word_len
|
||||
let resp = c.get(url)
|
||||
if resp.status == $Http200:
|
||||
parsePasswords(resp.body, pwgen.digits)
|
||||
except:
|
||||
stderr.writeLine getCurrentExceptionMsg()
|
||||
|
||||
proc getOutput(): Info =
|
||||
var data = newInfo("PW Generaturr")
|
||||
data.full_text = "Refresh"
|
||||
return data
|
||||
|
||||
proc goOutput(args: PWGen) =
|
||||
let data = getoutput()
|
||||
let selected = outputData(data,passwords)
|
||||
if selected in passwords:
|
||||
copyToClipboard(selected)
|
||||
elif selected == "Refresh":
|
||||
getPasswords(args)
|
||||
goOutput(args)
|
||||
|
||||
proc go*() =
|
||||
echo "Getting passwords..."
|
||||
let args = parsePWGenArgs()
|
||||
getPasswords(args)
|
||||
if args.to_terminal:
|
||||
for pw in passwords:
|
||||
echo pw
|
||||
else:
|
||||
echo "Outputting to app"
|
||||
goOutput(args)
|
||||
|
||||
if isMainModule:
|
||||
go()
|
|
@ -1,54 +0,0 @@
|
|||
import os
|
||||
import re
|
||||
import math
|
||||
import strutils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
|
||||
proc getThermalZones(): seq[string] =
|
||||
var zones: seq[string] = @[]
|
||||
let dirname_re = re("thermal_zone[\\d]+")
|
||||
let enabled_re = re("enabled")
|
||||
for file in walkDir("/sys/class/thermal/"):
|
||||
if file.path.contains(dirname_re):
|
||||
let state = readFile(file.path & "/mode")
|
||||
if state.contains(enabled_re):
|
||||
zones.add(file.path)
|
||||
return zones
|
||||
|
||||
proc getTemp(zone: string): int =
|
||||
let temp = strip(readFile(zone & "/temp"))
|
||||
return parseInt(temp)
|
||||
|
||||
proc getAverageTemp(zones: seq[string]): float =
|
||||
var temps: int = 0
|
||||
for zone in zones:
|
||||
let temp = getTemp(zone)
|
||||
temps += temp
|
||||
let avgtemp = ceil((temps / len(zones))/1000)
|
||||
return round(avgtemp,2)
|
||||
|
||||
proc getObject(temp: float): Info =
|
||||
var icon = ""
|
||||
case temp:
|
||||
of 40..59:
|
||||
icon = ""
|
||||
of 60.. 200:
|
||||
icon = ""
|
||||
else:
|
||||
icon = ""
|
||||
let main_text = icon & " " & $temp & "°C"
|
||||
var data = newInfo("Temperaturr")
|
||||
data.full_text = main_text
|
||||
return data
|
||||
|
||||
proc go*() =
|
||||
let zones = getThermalZones()
|
||||
let temp = getAverageTemp(zones)
|
||||
let data = getObject(temp)
|
||||
let option = outputData(data)
|
||||
if option == data.full_text:
|
||||
# Refresh
|
||||
go()
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
#curl https://www.tidetimes.org.uk/exmouth-dock-tide-times-20190101 | grep -E -o ">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))"
|
||||
|
||||
import re
|
||||
import httpclient
|
||||
import times
|
||||
import osproc
|
||||
import sequtils
|
||||
|
||||
import ../common
|
||||
import ../parser
|
||||
import ../output
|
||||
import ../model/tides
|
||||
|
||||
const icon: string = "🌊 "
|
||||
|
||||
proc sortTides(tides: seq[Tide], is_tomorrow: bool = false): seq[Tide] =
|
||||
let timenow = now()
|
||||
var reltides: seq[Tide]
|
||||
for tide in tides:
|
||||
if timenow.format("HH:MM") <= tide.time and not is_tomorrow:
|
||||
reltides.add(tide)
|
||||
elif is_tomorrow:
|
||||
reltides.add(tide)
|
||||
return reltides
|
||||
|
||||
|
||||
proc getTideData(mytides: TideList, get_tomorrow: bool = false): seq[Tide] =
|
||||
var tides: seq[Tide]
|
||||
let fnd = re">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))"
|
||||
var client = newHttpClient(timeout = 10000)
|
||||
var link = replace(mytides.url,re"\%LOC",mytides.location)
|
||||
if get_tomorrow:
|
||||
let tomdate = now() + initTimeInterval(days = 1)
|
||||
link &= "-" & tomdate.format("yyyyMMdd")
|
||||
try:
|
||||
# Remember to compile with -d:ssl else this won't work
|
||||
let resp = client.request(link)
|
||||
if resp.status != $Http200 or resp.body == "":
|
||||
var data = newInfo("Tideurrl")
|
||||
data.full_text = "Error Response: " & resp.status & ":\nBody:" & resp.body
|
||||
discard outputData(data)
|
||||
return @[]
|
||||
let data = resp.body
|
||||
let times = findAll(data,fnd)
|
||||
var tide: Tide
|
||||
var column = 0
|
||||
for idx,time in times:
|
||||
if idx == 12:
|
||||
break
|
||||
let l = len(time) - 1
|
||||
if time == ">High" or time == ">Low":
|
||||
tide = Tide()
|
||||
tide.state = time[1..l]
|
||||
column = 1
|
||||
continue
|
||||
elif column == 1:
|
||||
tide.time = time[1..l]
|
||||
column = 2
|
||||
continue
|
||||
elif column == 2:
|
||||
tide.height = time[1..l]
|
||||
tides.add(tide)
|
||||
column = 0
|
||||
continue
|
||||
except:
|
||||
var data = newInfo("Tideurrl")
|
||||
data.full_text = "Unable to get Tide Data : " & getCurrentExceptionMsg()
|
||||
discard outputData(data)
|
||||
return tides
|
||||
|
||||
proc getDesign(tl: TideList): Info =
|
||||
var my_tides: seq[string] = @[]
|
||||
my_tides.add(tl.location)
|
||||
let tides = tl.tides
|
||||
for tide in tides:
|
||||
let str = icon & tide.state[0] & " " & tide.time & " " & tide.height
|
||||
my_tides.add(str)
|
||||
var data = newInfo("Tideurrl")
|
||||
data.args = my_tides
|
||||
return data
|
||||
|
||||
proc getTides*(mytides: var TideList, get_tomorrow: bool = false) =
|
||||
mytides.tides = mytides.getTideData(get_tomorrow)
|
||||
mytides.tides = sortTides(mytides.tides, get_tomorrow)
|
||||
if len(mytides.tides) == 0:
|
||||
return
|
||||
let data = getDesign(mytides)
|
||||
var opt_tomorrow = "tomorrow"
|
||||
if get_tomorrow:
|
||||
opt_tomorrow = "back"
|
||||
let args = concat(data.args,@["---",opt_tomorrow])
|
||||
let output = outputData(data,args)
|
||||
if output == "tomorrow":
|
||||
getTides(mytides,true)
|
||||
elif output == "back":
|
||||
getTides(mytides)
|
||||
elif output == "---" or output == "":
|
||||
return
|
||||
elif output in args:
|
||||
let url = replace(mytides.url,re"\%LOC",mytides.location)
|
||||
discard execCmd("xdg-open " & url)
|
||||
else:
|
||||
mytides.location = output
|
||||
getTides(mytides)
|
||||
|
||||
|
||||
proc go*() =
|
||||
var mytides = parseTideurrlArgs()
|
||||
getTides(mytides)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# This is just an example to get you started. A typical binary package
|
||||
# uses this file as the main entry point of the application.
|
||||
#
|
||||
|
||||
import common
|
||||
import parser
|
||||
import dispatcher
|
||||
|
||||
when isMainModule:
|
||||
parseArgs()
|
||||
dispatch myConfig
|
72
temperaturr/src/temperaturr.nim
Normal file
72
temperaturr/src/temperaturr.nim
Normal file
|
@ -0,0 +1,72 @@
|
|||
import ../../globurrl
|
||||
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] = @[]
|
||||
let dirname = re("thermal_zone[\\d]+")
|
||||
for file in walkDir("/sys/class/thermal/"):
|
||||
if contains(file.path,dirname):
|
||||
let state = readFile(file.path & "/mode")
|
||||
if contains(state,re"enabled"):
|
||||
zones.add(file.path)
|
||||
return zones
|
||||
|
||||
proc getTemp(zone: string): int =
|
||||
let temp = strip(readFile(zone & "/temp"))
|
||||
return parseInt(temp)
|
||||
|
||||
proc getAverageTemp(zones: seq[string]): int =
|
||||
var temps: int = 0
|
||||
for zone in zones:
|
||||
let temp = getTemp(zone)
|
||||
temps += temp
|
||||
let avgtemp = ceil((temps / len(zones))/1000)
|
||||
return toInt(round(avgtemp,0))
|
||||
|
||||
proc getObject(temp: int): Info =
|
||||
var icon = ""
|
||||
var bg_col = default_bg
|
||||
var fg_col = default_fg
|
||||
case temp:
|
||||
of 40..59:
|
||||
bg_col = alert_bg
|
||||
fg_col = alert_fg
|
||||
icon = ""
|
||||
of 60.. 200:
|
||||
bg_col = warning_bg
|
||||
fg_col = warning_fg
|
||||
icon = ""
|
||||
else:
|
||||
bg_col = default_bg
|
||||
fg_col = default_fg
|
||||
icon = ""
|
||||
let text = "<span foreground='" & bg_col & "'>" & icon & "</span> " & $temp & "°C"
|
||||
let main_text = icon & " " & $temp & "°C"
|
||||
var data = newInfo("Temperaturr")
|
||||
data.full_text = main_text
|
||||
data.selected_bg = bg_col
|
||||
data.selected_fg = fg_col
|
||||
# i3bar stuff
|
||||
data.html_text = text
|
||||
data.color = bg_col
|
||||
data.border = bg_col
|
||||
return data
|
||||
|
||||
proc main() =
|
||||
let zones = getThermalZones()
|
||||
let temp = getAverageTemp(zones)
|
||||
let data = getObject(temp)
|
||||
let option = outputData(data)
|
||||
if option == data.full_text:
|
||||
# Refresh
|
||||
main()
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
temperaturr/temperaturr.nimble
Normal file
13
temperaturr/temperaturr.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Display temp in dmenu"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["temperaturr"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
106
tideurrl/src/tideurrl.nim
Normal file
106
tideurrl/src/tideurrl.nim
Normal file
|
@ -0,0 +1,106 @@
|
|||
#curl https://www.tidetimes.org.uk/exmouth-dock-tide-times-20190101 | grep -E -o ">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))"
|
||||
import ../../globurrl
|
||||
import std/[re,httpclient,times,osproc,sequtils]
|
||||
|
||||
# TODO:
|
||||
# Pass location in as variable
|
||||
|
||||
const url* = "https://www.tidetimes.org.uk/%LOC-tide-times"
|
||||
const loc* = "exmouth-dock"
|
||||
const icon: string = "🌊 "
|
||||
|
||||
type
|
||||
Tide = ref object
|
||||
State: string
|
||||
Time: string
|
||||
Height: string
|
||||
Tomorrow: bool
|
||||
TideList = ref object
|
||||
Tides: seq[Tide]
|
||||
LastUpdated: DateTime
|
||||
|
||||
proc sortTides(tides: seq[Tide], is_tomorrow: bool = false): seq[Tide] =
|
||||
let timenow = now()
|
||||
var reltides: seq[Tide]
|
||||
for tide in tides:
|
||||
if timenow.format("HH:MM") <= tide.Time and not is_tomorrow:
|
||||
reltides.add(tide)
|
||||
elif is_tomorrow:
|
||||
reltides.add(tide)
|
||||
return reltides
|
||||
|
||||
|
||||
proc getTideData(get_tomorrow: bool = false): seq[Tide] =
|
||||
var tides: seq[Tide]
|
||||
let fnd = re">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))"
|
||||
var client = newHttpClient()
|
||||
var link = replace(url,re"\%LOC",loc)
|
||||
if get_tomorrow:
|
||||
let tomdate = now() + initTimeInterval(days = 1)
|
||||
link &= "-" & tomdate.format("yyyyMMdd")
|
||||
try:
|
||||
# Remember to compile with -d:ssl else this won't work
|
||||
let data = client.getContent(link)
|
||||
let times = findAll(data,fnd)
|
||||
var tide: Tide
|
||||
var column = 0
|
||||
for idx,time in times:
|
||||
if idx == 12:
|
||||
break
|
||||
let l = len(time) - 1
|
||||
if time == ">High" or time == ">Low":
|
||||
tide = Tide()
|
||||
tide.State = time[1..l]
|
||||
column = 1
|
||||
continue
|
||||
elif column == 1:
|
||||
tide.Time = time[1..l]
|
||||
column = 2
|
||||
continue
|
||||
elif column == 2:
|
||||
tide.Height = time[1..l]
|
||||
tides.add(tide)
|
||||
column = 0
|
||||
continue
|
||||
except:
|
||||
echo "Unable to get Tide Data : " & getCurrentExceptionMsg()
|
||||
return tides
|
||||
|
||||
proc getDesign(tides: seq[Tide]): Info =
|
||||
var my_tides: seq[string] = @[]
|
||||
for tide in tides:
|
||||
let str = icon & tide.State[0] & " " & tide.Time & " " & tide.Height
|
||||
my_tides.add(str)
|
||||
var data = newInfo("Tideurrl")
|
||||
data.border = black
|
||||
data.args = my_tides
|
||||
return data
|
||||
|
||||
proc getTides*(get_tomorrow: bool = false) =
|
||||
var mytides = TideList()
|
||||
mytides.Tides = getTideData(get_tomorrow)
|
||||
mytides.Tides = sortTides(mytides.Tides, get_tomorrow)
|
||||
if len(mytides.Tides) == 0:
|
||||
getTides(true)
|
||||
return
|
||||
let data = getDesign(mytides.Tides)
|
||||
var opt_tomorrow = "tomorrow"
|
||||
if get_tomorrow:
|
||||
opt_tomorrow = "back"
|
||||
let args = concat(data.args,@["---",opt_tomorrow])
|
||||
let output = outputData(data,args)
|
||||
if output == "tomorrow":
|
||||
getTides(true)
|
||||
elif output == "back":
|
||||
getTides()
|
||||
elif output == "---":
|
||||
return
|
||||
elif output in args:
|
||||
let url = replace(url,re"\%LOC",loc)
|
||||
discard execCmd("xdg-open " & url)
|
||||
|
||||
proc main() =
|
||||
getTides()
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
tideurrl/tideurrl.nimble
Normal file
13
tideurrl/tideurrl.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Display local tides in dmenu"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["tideurrl"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
1
translaturr/nim.cfg
Normal file
1
translaturr/nim.cfg
Normal file
|
@ -0,0 +1 @@
|
|||
-d:ssl
|
|
@ -1,12 +1,5 @@
|
|||
import os
|
||||
import strutils
|
||||
import sequtils
|
||||
import osproc
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../parser
|
||||
import ../model/volume
|
||||
import ../../globurrl
|
||||
import std/[os,strutils,sequtils,osproc]
|
||||
|
||||
const audio_tools = @["ncpamixer", "pavucontrol"]
|
||||
const vol_cmd = "pamixer"
|
||||
|
@ -17,14 +10,11 @@ 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 getCurrentVolume(): string =
|
||||
let mute = execCmdEx(vol_get_mute)
|
||||
if strip(mute.output) == "true":
|
||||
return "muted"
|
||||
let vol = execCmdEx(vol_get)
|
||||
return vol.output
|
||||
proc getCurrentVolume(): string {.gcsafe.}
|
||||
|
||||
proc checkVolume(volume: string): string =
|
||||
var vol = volume
|
||||
|
@ -34,11 +24,11 @@ proc checkVolume(volume: string): string =
|
|||
vol = checkVolume(vol)
|
||||
return vol
|
||||
|
||||
proc getDesign(volume: string): string =
|
||||
proc getDesign(volume: string): (string,string) =
|
||||
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:
|
||||
|
@ -52,7 +42,15 @@ proc getDesign(volume: string): string =
|
|||
else:
|
||||
icon = " "
|
||||
let main_text = icon & $pcnt & "%"
|
||||
return main_text
|
||||
let text = "<span size=\"x-large\">" & icon & "</span>" & $pcnt & "%"
|
||||
return (text, main_text)
|
||||
|
||||
proc getCurrentVolume(): string =
|
||||
let mute = execCmdEx(vol_get_mute)
|
||||
if strip(mute.output) == "true":
|
||||
return "muted"
|
||||
let vol = execCmdEx(vol_get)
|
||||
return vol.output
|
||||
|
||||
proc volumeUp() =
|
||||
let cmd = replace(vol_up, "%v", vol_default_by)
|
||||
|
@ -65,11 +63,18 @@ proc volumeDown() =
|
|||
proc volumeMute() =
|
||||
discard execCmd(vol_mute)
|
||||
|
||||
proc getVolume*() =
|
||||
proc getVolume*(run_once: bool = false) =
|
||||
let vol = getCurrentVolume()
|
||||
let main_text = getDesign(vol)
|
||||
let (text, main_text) = getDesign(vol)
|
||||
var data = newInfo("Volurrme")
|
||||
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 == "":
|
||||
|
@ -96,20 +101,26 @@ proc getVolume*() =
|
|||
try:
|
||||
let vol = parseInt(option)
|
||||
let cmd = replace(vol_set, "%v", $vol)
|
||||
discard execCmd(cmd)
|
||||
let x = execCmd(cmd)
|
||||
getVolume()
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
getVolume()
|
||||
|
||||
proc go*() =
|
||||
let arg = parseVolArgs()
|
||||
case arg
|
||||
of VolUp:
|
||||
volumeUp()
|
||||
of VolDown:
|
||||
volumeDown()
|
||||
of VolMute:
|
||||
volumeMute()
|
||||
else:
|
||||
proc main() =
|
||||
getVolume()
|
||||
|
||||
if isMainModule:
|
||||
block start:
|
||||
for arg in args:
|
||||
case arg:
|
||||
of "up":
|
||||
volumeUp()
|
||||
break start
|
||||
of "down":
|
||||
volumeDown()
|
||||
break start
|
||||
of "mute":
|
||||
volumeMute()
|
||||
break start
|
||||
main()
|
13
volurrme/volurrme.nimble
Normal file
13
volurrme/volurrme.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Display and control volume with dmenu"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["volurrme"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,11 +1,9 @@
|
|||
import os
|
||||
import osproc
|
||||
import strutils
|
||||
import sequtils
|
||||
|
||||
import ../common
|
||||
import ../output
|
||||
import ../../globurrl
|
||||
import std/[os,osproc,strutils,sequtils]
|
||||
|
||||
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"
|
||||
|
||||
|
@ -30,6 +28,9 @@ proc getWifi(nic: string): (string, string) =
|
|||
|
||||
proc getObject(): Info =
|
||||
var data = newInfo("Wirelurrs")
|
||||
data.border = purple
|
||||
data.selected_bg = default_bg
|
||||
data.selected_fg = default_fg
|
||||
return data
|
||||
|
||||
proc getWifiInfo*(nics: seq[string]) =
|
||||
|
@ -40,8 +41,6 @@ proc getWifiInfo*(nics: seq[string]) =
|
|||
let data = getObject()
|
||||
let args = concat(lst,@["---", "manage","exit"])
|
||||
let output = outputData(data, args)
|
||||
if output in lst:
|
||||
discard execCmd(mng_cmd)
|
||||
case output:
|
||||
of "manage":
|
||||
discard execCmd(mng_cmd)
|
||||
|
@ -50,20 +49,16 @@ proc getWifiInfo*(nics: seq[string]) =
|
|||
of "---":
|
||||
return
|
||||
|
||||
proc getWiFiNICs(): seq[string] =
|
||||
proc main() =
|
||||
var my_nics: seq[string] = @[]
|
||||
for path in walkDir("/sys/class/net/"):
|
||||
if dirExists(path.path & "/wireless"):
|
||||
let nic = path.path.replace("/sys/class/net/","")
|
||||
for nic in wlan_nics:
|
||||
if dirExists("/sys/class/net/" & nic):
|
||||
my_nics.add(nic)
|
||||
return my_nics
|
||||
|
||||
proc go*() =
|
||||
let my_nics = getWiFiNICs()
|
||||
if len(my_nics) > 0:
|
||||
getWifiInfo(my_nics)
|
||||
else:
|
||||
var data = getObject()
|
||||
data.full_text = "No WLAN"
|
||||
discard outputData(data)
|
||||
switchTwmMode()
|
||||
echo "No WLAN"
|
||||
|
||||
if isMainModule:
|
||||
main()
|
13
wirelurrs/wirelurrs.nimble
Normal file
13
wirelurrs/wirelurrs.nimble
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Paul Wilde"
|
||||
description = "Display and control WLAN state with dmenu"
|
||||
license = "GPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["wirelurrs"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.6.6"
|
|
@ -1,16 +0,0 @@
|
|||
# Package
|
||||
|
||||
version = "2.0.1"
|
||||
author = "Paul Wilde"
|
||||
description = "A set of informational tools"
|
||||
license = "AGPL-3.0-or-later"
|
||||
srcDir = "src"
|
||||
bin = @["wmtools"]
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 2.0.0"
|
||||
requires "parsetoml >= 0.7.1"
|
||||
requires "argparse"
|
||||
requires "configparser"
|
Loading…
Reference in a new issue