added i3 workspace switcher/task viewer

This commit is contained in:
Paul Wilde 2022-05-14 21:01:29 +01:00
parent 386c8cd1ac
commit 28319104cd

185
i3_workspaces.nim Normal file
View file

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