diff --git a/i3_workspaces.nim b/i3_workspaces.nim new file mode 100644 index 0000000..798d256 --- /dev/null +++ b/i3_workspaces.nim @@ -0,0 +1,185 @@ +import base +import std/[osproc,json,strutils] + +const I3_WORKSPACES = "i3-msg -t get_workspaces" +const I3_TREE = "i3-msg -t get_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] + +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: + str &= FOCUSED +# elif ws.visible: +# str &= VISIBLE + else: + str &= " " + str &= "| " & ws.output & " | " + 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) + let cmd = "i3-msg workspace " & $ws.num + discard execCmd(cmd) + showWorkspaces() + +# proc getApplications(node: JsonNode): (seq[string],bool) = +# var apps: seq[string] = @[] +# var focused = false +# for item in node["nodes"].getElems(): +# var name = "" +# if item["focused"].getBool(): +# focused = true +# if item{"window_properties"} != nil : +# let prop = item["window_properties"] +# name = prop["class"].getStr() +# name &= " " & prop["title"].getStr() +# echo "Adding application : " & name +# apps.add(name) +# return (apps, focused) +# +proc getApplication(node: JsonNode): 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() + return app + +# proc findWorkspaces(node: JsonNode) = +# for channel in node["nodes"].getElems(): +# case channel["type"].getStr(): +# of "workspace": +# if channel["output"].getStr() == "__i3": +# continue +# let w = channel +# let apps = getApplications(channel) +# var space = Workspace( +# num: w["num"].getInt(), +# name: w["name"].getStr(), +# focused: apps[1], +# #visible: w["visible"].getBool(), +# urgent: w["urgent"].getBool(), +# output: w["output"].getStr(), +# apps: apps[0] +# ) +# space.display_string = buildString(space) +# my_workspaces.add(space) +# else: +# echo "finding workspaces..." +# findWorkspaces(channel) +# return + +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) = + for channel in node["nodes"].getElems(): + ### move this into for loop if want separate entry per window + var ws: Workspace = Workspace() + if node{"type"}.getStr() == "workspace": + if node["output"].getStr() == "__i3": + return + ws = newWorkspace(node) + ### + if channel{"window_properties"} != nil: + let app = getApplication(channel) + if ws.name != "": + #if app.focused: + # ws.focused = true + ws.applications.add(app) + ws.application = app + else: + findWorkspacesTree(channel) + ### move this into for loop if want separate entry per window + if ws.name != "": + ws.display_string = ws.buildString() + my_workspaces.add(ws) + ### + return + +proc getTree() = + let cur_workspaces = execCmdEx(I3_TREE) + if cur_workspaces.output != "": + let root = parseJson(cur_workspaces.output) + findWorkspacesTree(root) + return + +proc getWorkspaces(): seq[Workspace] = + let cur_workspaces = execCmdEx(I3_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("Workspaces") + 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()