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 type i3BarInput* = object button*: int x*: int y*: int const font = "Hermit-10" 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" var loop* = false var stoploop* = true var dmenu* = true var rofi* = false proc newInfo*(title: string = "Info"): Info = 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 debugLog*(str: string) = let f = open("/tmp/debug.txt",fmAppend) defer: f.close() f.writeLine(str) proc switchTwmMode*(mode: string = "default") = # 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 \"" & mode & "\"") proc parseInput*(): i3BarInput = let input = readLineFromStdin("") try: let jsonNode = parseJson(input) let i3input = to(jsonNode, i3BarInput) return i3input except: return i3BarInput() proc clearInput*(count: int = 1) = for x in countup(1, count): discard readLineFromStdin("") proc getArguments*(): seq[string] = let args = commandLineParams() return args proc runDMenu*(data: Info, opts: varargs[string], rofi: bool = false): string = # 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: cmd = cmd & opt & "\n" cmd.removeSuffix("\n") 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 \"" & $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 outputData*(data: Info, args: varargs[string]): string {.discardable.} = var output = "" if rofi: output = runDmenu(data,args, rofi = 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 = runDmenu(data,args) return output # At Start up: # Switch bindsym mode back to default as it could be being used. switchTwmMode() 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