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 & " | " 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) 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, 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 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, 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) ### if channel{"window_properties"} != nil: let app = getApplication(channel,ws) 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(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()