diff --git a/.config/qtile/autostart.sh b/.config/qtile/autostart.sh
new file mode 100755
index 00000000..59e853b1
--- /dev/null
+++ b/.config/qtile/autostart.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+nitrogen --restore &
+lxsession &
+xsetroot -cursor_name left_ptr
+imwheel -b 45
diff --git a/.config/qtile/config.org b/.config/qtile/config.org
new file mode 100644
index 00000000..ee4a0e66
--- /dev/null
+++ b/.config/qtile/config.org
@@ -0,0 +1,256 @@
++TITLE: Custom Qtile Config
+#+PROPERTY: header-args :tangle config.py
+
+* Table of Contents
+:PROPERTIES:
+:TOC: :include all :depth 3
+:END:
+:CONTENTS:
+:END:
+* Imports
+
+Import needed python modules.
+
+#+begin_src python
+from typing import List # noqa: F401
+from libqtile import bar, layout, widget, hook
+from libqtile.config import Click, Drag, Group, Key, Match, Screen
+from libqtile.lazy import lazy
+from libqtile.utils import guess_terminal
+import os
+import subprocess
+#+end_src
+* Variables
+
+Set variable used later in the config, often a handful of times.
+
+#+begin_src python
+
+# Use the "Windows" key for mod
+mod = "mod4"
+# Determine terminal with this nifty function
+terminal = guess_terminal()
+# Define workspace names
+groups = [Group(i) for i in "123456789"]
+# Generate group binding hotkeys
+dgroups_key_binder = None
+# List of rule objects (currently empty)
+dgroups_app_rules = []
+# Set mouse functionality
+follow_mouse_focus = True
+bring_front_click = True
+cursor_warp = False
+# Set fullscreen options
+auto_fullscreen = True
+focus_on_window_activation = "smart"
+# Set floating layout options
+floating_layout = layout.Floating(float_rules=[
+ {'wmclass': 'Wine'},
+ {'wmclass': 'Steam'},
+])
+
+#+end_src
+
+* Keys
+** Window Management Binds
+
+#+begin_src python
+# Start keys block
+keys = [
+ # Close focused window
+ Key([mod], "q", lazy.window.kill(), desc="Kill focused window"),
+ # Rotate through the available layout algorithms
+ Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"),
+ # Switch between windows
+ Key([mod], "h", lazy.layout.left(), desc="Move focus to left"),
+ Key([mod], "l", lazy.layout.right(), desc="Move focus to right"),
+ Key([mod], "j", lazy.layout.down(), desc="Move focus down"),
+ Key([mod], "k", lazy.layout.up(), desc="Move focus up"),
+ Key([mod], "space", lazy.layout.next(),
+ desc="Move window focus to other window"),
+ # Navigate between windows on screen
+ Key([mod, "shift"], "h", lazy.layout.shuffle_left(),
+ desc="Move window to the left"),
+ Key([mod, "shift"], "l", lazy.layout.shuffle_right(),
+ desc="Move window to the right"),
+ Key([mod, "shift"], "j", lazy.layout.shuffle_down(),
+ desc="Move window down"),
+ Key([mod, "shift"], "k", lazy.layout.shuffle_up(),
+ desc="Move window up"),
+ # Resize windows on screen
+ Key([mod, "shift"], "h", lazy.layout.grow_left(),
+ desc="Grow window to the left"),
+ Key([mod, "shift"], "l", lazy.layout.grow_right(),
+ desc="Grow window to the right"),
+ Key([mod, "shift"], "j", lazy.layout.grow_down(),
+ desc="Grow window down"),
+ Key([mod, "shift"], "k", lazy.layout.grow_up(),
+ desc="Grow window up"),
+ # Return sizes to default
+ Key([mod], "n", lazy.layout.normalize(),
+ desc="Reset all window sizes"),
+ # Toggle between split and unsplit sides of stack.
+ # Split = all windows displayed
+ # Unsplit = 1 window displayed, like Max layout, but still with
+ # multiple stack panes
+ Key([mod, "shift"], "Return", lazy.layout.toggle_split(),
+ desc="Toggle between split and unsplit sides of stack"),
+ # Toggle between physical screens
+ Key([mod], "comma", lazy.to_screen(0),
+ desc="Toggle between split and unsplit sides of stack"),
+ Key([mod], "period", lazy.to_screen(1),
+ desc="Toggle between split and unsplit sides of stack"),
+ # Toggle fullscreen
+ Key([mod], "f", lazy.window.toggle_fullscreen(),
+ desc="Toggle fullscreen"),
+ # Toggle floating
+ Key([mod], "t", lazy.window.toggle_floating(),
+ desc="Toggle floating"),
+#+end_src
+
+** Open Binds
+
+#+begin_src python
+ # Spawn terminal
+ Key([mod], "Return", lazy.spawn(terminal),
+ desc="Launch terminal"),
+ # Spawn rofi drun
+ Key([mod], "w", lazy.spawn("rofi -show drun"),
+ desc="Launch rofi -drun"),
+ # Spawn rofi window
+ Key([mod, "shift"], "w", lazy.spawn("rofi -show window"),
+ desc="Launch rofi -window"),
+
+#+end_src
+
+** System Utility Binds
+#+begin_src python
+ # Recompile and restart qtile
+ Key([mod, "control"], "r", lazy.restart(), desc="Restart Qtile"),
+ # Quit qtile
+ Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),
+ # Qtile's in-built launcher
+ Key([mod], "r", lazy.spawncmd(),
+ desc="Spawn a command using a prompt widget"),
+ # Start gamemoded
+ Key([mod], "g", lazy.spawn("gamemoded -r"),
+ desc="Start gamemode"),
+ # Stop gamemoded
+ Key([mod, "shift"], "g", lazy.spawn("killall gamemoded"),
+ desc="Stop gamemode"),
+]
+#+end_src
+** Mouse Binds
+#+begin_src python
+# Drag floating layouts.
+mouse = [
+ Drag([mod], "Button1", lazy.window.set_position_floating(),
+ start=lazy.window.get_position()),
+ Drag([mod], "Button3", lazy.window.set_size_floating(),
+ start=lazy.window.get_size()),
+ Click([mod], "Button2", lazy.window.bring_to_front()),
+]
+#+end_src
+* Groups
+#+begin_src python
+for i in groups:
+ keys.extend([
+ # mod1 + letter of group = switch to group
+ Key([mod], i.name, lazy.group[i.name].toscreen(),
+ desc="Switch to group {}".format(i.name)),
+
+ # mod1 + shift + letter of group = switch to & move focused window to group
+ Key([mod, "shift"], i.name, lazy.window.togroup(i.name),
+ desc="Switch to & move focused window to group {}".format(i.name)),
+ # Or, use below if you prefer not to switch to that group.
+ # # mod1 + shift + letter of group = move focused window to group
+ # Key([mod, "shift"], i.name, lazy.window.togroup(i.name),
+ # desc="move focused window to group {}".format(i.name)),
+ ])
+#+end_src
+* Layouts
+#+begin_src python
+layouts = [
+ layout.Columns(border_focus_stack='#d75f5f', margin=2),
+ layout.Max(),
+ # Try more layouts by unleashing below layouts.
+ # layout.Stack(num_stacks=2),
+ # layout.Bsp(),
+ # layout.Matrix(),
+ # layout.MonadTall(),
+ # layout.MonadWide(),
+ # layout.RatioTile(),
+ # layout.Tile(),
+ # layout.TreeTab(),
+ # layout.VerticalTile(),
+ # layout.Zoomy(),
+]
+#+end_src
+
+* Defaults
+#+begin_src python
+widget_defaults = dict(
+ font='JetBrains Mono Nerd Font',
+ fontsize=11,
+ padding=3,
+)
+extension_defaults = widget_defaults.copy()
+#+end_src
+
+* Screens
+#+begin_src python
+colors = [["#282c34", "#282c34"], # panel background
+ ["#434758", "#434758"], # background for current screen tab
+ ["#ffffff", "#ffffff"], # font color for group names
+ ["#ff5555", "#ff5555"], # border line color for current tab
+ ["#8d62a9", "#8d62a9"], # border line color for other tab and odd widgets
+ ["#668bd7", "#668bd7"], # color for the even widgets
+ ["#e1acff", "#e1acff"]] # window name
+
+screens = [
+ Screen(
+ top=bar.Bar(
+ [
+ widget.GroupBox(
+ fontsize = 9,
+ margin_y = 3,
+ margin_x = 0,
+ padding_y = 5,
+ padding_x = 3,
+ borderwidth = 3,
+ active = colors[2],
+ inactive = colors[2],
+ rounded = False,
+ highlight_color = colors[1],
+ highlight_method = "line",
+ this_current_screen_border = colors[3],
+ this_screen_border = colors [4],
+ other_current_screen_border = colors[0],
+ other_screen_border = colors[0],
+ foreground = colors[2],
+ background = colors[0],
+ hide_unused=True),
+ widget.TextBox('|'),
+ widget.WindowName(),
+ widget.Prompt(),
+
+
+ widget.TextBox('|'),
+ widget.CPUGraph(frequency=1, samples=30, type='box'),
+ widget.TextBox('|'),
+ widget.Clock(format='%Y-%m-%d %a %I:%M %p'),
+ ],
+ 24,
+ ),
+ ),
+]
+#+end_src
+* Autostart
+#+begin_src python
+
+@hook.subscribe.startup_once
+def autostart():
+ home = os.path.expanduser('~/.config/qtile/autostart.sh')
+ subprocess.call([home])
+
+#+end_src
diff --git a/.config/qtile/config.py b/.config/qtile/config.py
new file mode 100644
index 00000000..c1ef22a6
--- /dev/null
+++ b/.config/qtile/config.py
@@ -0,0 +1,205 @@
+from typing import List # noqa: F401
+from libqtile import bar, layout, widget, hook
+from libqtile.config import Click, Drag, Group, Key, Match, Screen
+from libqtile.lazy import lazy
+from libqtile.utils import guess_terminal
+import os
+import subprocess
+
+# Use the "Windows" key for mod
+mod = "mod4"
+# Determine terminal with this nifty function
+terminal = guess_terminal()
+# Define workspace names
+groups = [Group(i) for i in "123456789"]
+# Generate group binding hotkeys
+dgroups_key_binder = None
+# List of rule objects (currently empty)
+dgroups_app_rules = []
+# Set mouse functionality
+follow_mouse_focus = True
+bring_front_click = True
+cursor_warp = False
+# Set fullscreen options
+auto_fullscreen = True
+focus_on_window_activation = "smart"
+# Set floating layout options
+floating_layout = layout.Floating(float_rules=[
+ {'wmclass': 'Wine'},
+ {'wmclass': 'Steam'},
+])
+
+# Start keys block
+keys = [
+ # Close focused window
+ Key([mod], "q", lazy.window.kill(), desc="Kill focused window"),
+ # Rotate through the available layout algorithms
+ Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"),
+ # Switch between windows
+ Key([mod], "h", lazy.layout.left(), desc="Move focus to left"),
+ Key([mod], "l", lazy.layout.right(), desc="Move focus to right"),
+ Key([mod], "j", lazy.layout.down(), desc="Move focus down"),
+ Key([mod], "k", lazy.layout.up(), desc="Move focus up"),
+ Key([mod], "space", lazy.layout.next(),
+ desc="Move window focus to other window"),
+ # Navigate between windows on screen
+ Key([mod, "shift"], "h", lazy.layout.shuffle_left(),
+ desc="Move window to the left"),
+ Key([mod, "shift"], "l", lazy.layout.shuffle_right(),
+ desc="Move window to the right"),
+ Key([mod, "shift"], "j", lazy.layout.shuffle_down(),
+ desc="Move window down"),
+ Key([mod, "shift"], "k", lazy.layout.shuffle_up(),
+ desc="Move window up"),
+ # Resize windows on screen
+ Key([mod, "shift"], "h", lazy.layout.grow_left(),
+ desc="Grow window to the left"),
+ Key([mod, "shift"], "l", lazy.layout.grow_right(),
+ desc="Grow window to the right"),
+ Key([mod, "shift"], "j", lazy.layout.grow_down(),
+ desc="Grow window down"),
+ Key([mod, "shift"], "k", lazy.layout.grow_up(),
+ desc="Grow window up"),
+ # Return sizes to default
+ Key([mod], "n", lazy.layout.normalize(),
+ desc="Reset all window sizes"),
+ # Toggle between split and unsplit sides of stack.
+ # Split = all windows displayed
+ # Unsplit = 1 window displayed, like Max layout, but still with
+ # multiple stack panes
+ Key([mod, "shift"], "Return", lazy.layout.toggle_split(),
+ desc="Toggle between split and unsplit sides of stack"),
+ # Toggle between physical screens
+ Key([mod], "comma", lazy.to_screen(0),
+ desc="Toggle between split and unsplit sides of stack"),
+ Key([mod], "period", lazy.to_screen(1),
+ desc="Toggle between split and unsplit sides of stack"),
+ # Toggle fullscreen
+ Key([mod], "f", lazy.window.toggle_fullscreen(),
+ desc="Toggle fullscreen"),
+ # Toggle floating
+ Key([mod], "t", lazy.window.toggle_floating(),
+ desc="Toggle floating"),
+
+ # Spawn terminal
+ Key([mod], "Return", lazy.spawn(terminal),
+ desc="Launch terminal"),
+ # Spawn rofi drun
+ Key([mod], "w", lazy.spawn("rofi -show drun"),
+ desc="Launch rofi -drun"),
+ # Spawn rofi window
+ Key([mod, "shift"], "w", lazy.spawn("rofi -show window"),
+ desc="Launch rofi -window"),
+
+ # Recompile and restart qtile
+ Key([mod, "control"], "r", lazy.restart(), desc="Restart Qtile"),
+ # Quit qtile
+ Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),
+ # Qtile's in-built launcher
+ Key([mod], "r", lazy.spawncmd(),
+ desc="Spawn a command using a prompt widget"),
+ # Start gamemoded
+ Key([mod], "g", lazy.spawn("gamemoded -r"),
+ desc="Start gamemode"),
+ # Stop gamemoded
+ Key([mod, "shift"], "g", lazy.spawn("killall gamemoded"),
+ desc="Stop gamemode"),
+]
+
+# Drag floating layouts.
+mouse = [
+ Drag([mod], "Button1", lazy.window.set_position_floating(),
+ start=lazy.window.get_position()),
+ Drag([mod], "Button3", lazy.window.set_size_floating(),
+ start=lazy.window.get_size()),
+ Click([mod], "Button2", lazy.window.bring_to_front()),
+]
+
+for i in groups:
+ keys.extend([
+ # mod1 + letter of group = switch to group
+ Key([mod], i.name, lazy.group[i.name].toscreen(),
+ desc="Switch to group {}".format(i.name)),
+
+ # mod1 + shift + letter of group = switch to & move focused window to group
+ Key([mod, "shift"], i.name, lazy.window.togroup(i.name),
+ desc="Switch to & move focused window to group {}".format(i.name)),
+ # Or, use below if you prefer not to switch to that group.
+ # # mod1 + shift + letter of group = move focused window to group
+ # Key([mod, "shift"], i.name, lazy.window.togroup(i.name),
+ # desc="move focused window to group {}".format(i.name)),
+ ])
+
+layouts = [
+ layout.Columns(border_focus_stack='#d75f5f', margin=2),
+ layout.Max(),
+ # Try more layouts by unleashing below layouts.
+ # layout.Stack(num_stacks=2),
+ # layout.Bsp(),
+ # layout.Matrix(),
+ # layout.MonadTall(),
+ # layout.MonadWide(),
+ # layout.RatioTile(),
+ # layout.Tile(),
+ # layout.TreeTab(),
+ # layout.VerticalTile(),
+ # layout.Zoomy(),
+]
+
+widget_defaults = dict(
+ font='JetBrains Mono Nerd Font',
+ fontsize=11,
+ padding=3,
+)
+extension_defaults = widget_defaults.copy()
+
+colors = [["#282c34", "#282c34"], # panel background
+ ["#434758", "#434758"], # background for current screen tab
+ ["#ffffff", "#ffffff"], # font color for group names
+ ["#ff5555", "#ff5555"], # border line color for current tab
+ ["#8d62a9", "#8d62a9"], # border line color for other tab and odd widgets
+ ["#668bd7", "#668bd7"], # color for the even widgets
+ ["#e1acff", "#e1acff"]] # window name
+
+screens = [
+ Screen(
+ top=bar.Bar(
+ [
+ widget.GroupBox(
+ fontsize = 9,
+ margin_y = 3,
+ margin_x = 0,
+ padding_y = 5,
+ padding_x = 3,
+ borderwidth = 3,
+ active = colors[2],
+ inactive = colors[2],
+ rounded = False,
+ highlight_color = colors[1],
+ highlight_method = "line",
+ this_current_screen_border = colors[3],
+ this_screen_border = colors [4],
+ other_current_screen_border = colors[0],
+ other_screen_border = colors[0],
+ foreground = colors[2],
+ background = colors[0],
+ hide_unused=True),
+ widget.TextBox('|'),
+ widget.WindowName(),
+ widget.Prompt(),
+
+
+ widget.TextBox('|'),
+ widget.CPUGraph(frequency=1, samples=30, type='box'),
+ widget.TextBox('|'),
+ widget.Clock(format='%Y-%m-%d %a %I:%M %p'),
+ ],
+ 24,
+ ),
+ ),
+]
+
+@hook.subscribe.startup_once
+def autostart():
+ home = os.path.expanduser('~/.config/qtile/autostart.sh')
+ subprocess.call([home])
diff --git a/.config/xmobar/xmobarrc b/.config/xmobar/xmobarrc
index e6bf5fb1..785b1a74 100755
--- a/.config/xmobar/xmobarrc
+++ b/.config/xmobar/xmobarrc
@@ -3,6 +3,8 @@ Config { font = "xft:Mononoki Nerd Font:pixelsize=12:antialias=true:hinting=true
, fgColor = "#ebdbb2"
, position = Static {xpos = 0, ypos = 0, width = 2560, height = 20}
, iconRoot = "X"
+ , allDesktops = False
+ , overrideRedirect = False
, commands = [ Run Cpu ["-t", " %","-H", "2"] 10
, Run Memory ["-t", "%"] 10
, Run Network "enp4s0" [ "-t", "kb/kb" ] 10
diff --git a/.config/xmobar/xmobarrc1 b/.config/xmobar/xmobarrc1
new file mode 100755
index 00000000..ef7c7f4a
--- /dev/null
+++ b/.config/xmobar/xmobarrc1
@@ -0,0 +1,19 @@
+Config { font = "xft:Mononoki Nerd Font:pixelsize=12:antialias=true:hinting=true"
+ , bgColor = "#282828"
+ , fgColor = "#ebdbb2"
+ , position = Static {xpos = 0, ypos = 0, width = 2560, height = 20}
+ , iconRoot = "X"
+ , allDesktops = False
+ , commands = [ Run Cpu ["-t", " %","-H", "2"] 10
+ , Run Memory ["-t", "%"] 10
+ , Run Network "enp4s0" [ "-t", "kb/kb" ] 10
+ , Run Com "/home/tstarr/.config/xmobar/volume" [] "volume" 10
+ , Run Com "/home/tstarr/.config/xmobar/gamemode" [] "gamemode" 10
+ , Run Date " %a %d/%m/%y %H:%M:%S" "date" 10
+ , Run MPD ["-M","15","-t", " (/)"] 10
+ , Run StdinReader
+ ]
+ , sepChar = "%"
+ , alignSep = "}{"
+ , template = " %StdinReader%}%date%{%enp4s0% | %mpd% | %volume% | 閭%cpu% | %memory% |%gamemode% "
+ }
diff --git a/.doom.d/init.el b/.doom.d/init.el
index 3bb3925c..d655af66 100644
--- a/.doom.d/init.el
+++ b/.doom.d/init.el
@@ -43,7 +43,7 @@
ophints ; highlight the region an operation acts on
(popup +defaults) ; tame sudden yet inevitable temporary windows
;;tabs ; a tab bar for Emacs
- ;;treemacs ; a project drawer, like neotree but cooler
+ treemacs ; a project drawer, like neotree but cooler
;;unicode ; extended unicode support for various languages
vc-gutter ; vcs diff in the fringe
vi-tilde-fringe ; fringe tildes to mark beyond EOB
diff --git a/.gitignore b/.gitignore
index d86f1459..940fcaf5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,5 +36,10 @@
/.config/retroarch/*
!/.config/retroarch/retroarch.cfg
-
+### ~/.config/retroarch
+!/.config/qtile
+/.config/qtile/*
+!/.config/qtile/autostart.sh
+!/.config/qtile/config.org
+!/.config/qtile/config.py
diff --git a/.xinitrc b/.xinitrc
index 77183c57..33a63a7b 100644
--- a/.xinitrc
+++ b/.xinitrc
@@ -1 +1 @@
-exec xmonad
+exec qtile
diff --git a/.xmonad/xmonad.hs b/.xmonad/xmonad.hs
index 6724cd76..02cf13b3 100644
--- a/.xmonad/xmonad.hs
+++ b/.xmonad/xmonad.hs
@@ -27,12 +27,16 @@ import XMonad.Util.NamedScratchpad
import XMonad.Util.EZConfig (additionalKeysP, removeKeys)
-- Actions
+import XMonad.Actions.CycleWS (moveTo, shiftTo, WSType(..), nextScreen, prevScreen)
import XMonad.Actions.DynamicProjects
import XMonad.Actions.DynamicWorkspaces
-- Prompt
import XMonad.Prompt
+-- Data
+import Data.Maybe (isJust)
+
-- Terminal to use
myTerminal = "alacritty"
@@ -173,10 +177,10 @@ myKeys home =
, ("M-l", sendMessage Expand)
-- Push window back into tiling
, ("M-t", withFocused $ windows . W.sink)
- -- Increment the number of windows in the master area
- , ("M-,", sendMessage (IncMasterN 1))
- -- Deincrement the number of windows in the master area
- , ("M-.", sendMessage (IncMasterN (-1)))
+ , ("M-.", nextScreen) -- Switch focus to next monitor
+ , ("M-,", prevScreen) -- Switch focus to prev monitor
+ , ("M-S-", shiftTo Next nonNSP >> moveTo Next nonNSP) -- Shifts focused window to next ws
+ , ("M-S-", shiftTo Prev nonNSP >> moveTo Prev nonNSP) -- Shifts focused window to prev ws
-- Spawn terminal
, ("M-" , spawn "alacritty")
@@ -219,6 +223,8 @@ myKeys home =
-- Stop gamemode
, ("M-x S-g", spawn "killall gamemoded")
]
+ where nonNSP = WSIs (return (\ws -> W.tag ws /= "nsp"))
+ nonEmptyNonNSP = WSIs (return (\ws -> isJust (W.stack ws) && W.tag ws /= "nsp"))
rmKeys :: String -> [(KeyMask, KeySym)]
rmKeys keys =
diff --git a/.xmonad/xmonad.org b/.xmonad/xmonad.org
index 660ba5b1..7cb0b73d 100644
--- a/.xmonad/xmonad.org
+++ b/.xmonad/xmonad.org
@@ -62,12 +62,16 @@ import XMonad.Util.NamedScratchpad
import XMonad.Util.EZConfig (additionalKeysP, removeKeys)
-- Actions
+import XMonad.Actions.CycleWS (moveTo, shiftTo, WSType(..), nextScreen, prevScreen)
import XMonad.Actions.DynamicProjects
import XMonad.Actions.DynamicWorkspaces
-- Prompt
import XMonad.Prompt
+-- Data
+import Data.Maybe (isJust)
+
#+end_src
* Variables
@@ -273,11 +277,10 @@ myKeys home =
, ("M-l", sendMessage Expand)
-- Push window back into tiling
, ("M-t", withFocused $ windows . W.sink)
- -- Increment the number of windows in the master area
- , ("M-,", sendMessage (IncMasterN 1))
- -- Deincrement the number of windows in the master area
- , ("M-.", sendMessage (IncMasterN (-1)))
-
+ , ("M-.", nextScreen) -- Switch focus to next monitor
+ , ("M-,", prevScreen) -- Switch focus to prev monitor
+ , ("M-S-", shiftTo Next nonNSP >> moveTo Next nonNSP) -- Shifts focused window to next ws
+ , ("M-S-", shiftTo Prev nonNSP >> moveTo Prev nonNSP) -- Shifts focused window to prev ws
#+end_src
@@ -350,6 +353,8 @@ myKeys home =
-- Stop gamemode
, ("M-x S-g", spawn "killall gamemoded")
]
+ where nonNSP = WSIs (return (\ws -> W.tag ws /= "nsp"))
+ nonEmptyNonNSP = WSIs (return (\ws -> isJust (W.stack ws) && W.tag ws /= "nsp"))
#+end_src