wmtools/i3_workspaces.nim

200 lines
5.5 KiB
Nim

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]
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
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()