added i3 workspace switcher/task viewer
This commit is contained in:
parent
386c8cd1ac
commit
28319104cd
1 changed files with 185 additions and 0 deletions
185
i3_workspaces.nim
Normal file
185
i3_workspaces.nim
Normal 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()
|
Loading…
Reference in a new issue