User:Tomwm/.awesomerc
From RHLUG
I primarily run the Awesome window manager, a simple tiling WM, along with select bits of Gnome. Unfortunately, the packages in the Ubuntu repositories are old (version 2.0 instead of 2.3), so it needs to be built from source. I also include my ~/.Xsession file and widget update scripts below. (.Xsession is a Debianism, I believe.)
Contents |
[edit] .Xsession
File: ~/.Xsession
#!/usr/bin/env bash
export PATH=$PATH:~/.local/bin
export AWT_TOOLKIT=MToolkit # Fix Java apps
# General background stuff
gnome-settings-daemon &
xbindkeys &
# The tray and stuff that depends on it
(
stalonetray --geometry=200x20-0+0 \
--grow-gravity=W --icon-gravity=E \
--max-width=200 --max-height=20 \
--background='#000000' &
sleep 1 # Let stalonetray start
gnome-power-manager &
padevchooser &
bluetooth-applet &
nm-applet &
) &
# Conky needs to be started up a bit later or the text size is wrong
( sleep 10 && conky ) &
# Update awesome statusbar
( sleep 1 && awesome-clock.py ) &
( sleep 1 && awesome-exaile.py ) &
exec /usr/local/bin/awesome
[edit] cache-menu.sh
This script generates the ~/.local/menu-cache file from which my awesome-menu autocompletes. This file contains all of the binary names that I might want to launch graphically.
File: ~/.local/bin/cache-menu.sh
#!/bin/sh TEMP=`tempfile` ls /usr/bin > $TEMP ls /usr/local/bin >> $TEMP ls /usr/games >> $TEMP ls ~/.local/bin >> $TEMP cat $TEMP | sort | uniq > ~/.local/menu-cache
[edit] .awesomerc
File: ~/.awesomerc
# Tom's .awesomerc
# This file has radically different keybindings than the default one.
# Notably:
# * Tags are named after the keys qwertasdf instead of the number keys.
# * Super + Escape is used to kill windows.
# * The number keys 1-4 are used to set the number of master windows
# (add Shift to set the number of columns)
# * Super + Space and Super + Shift + Space switch among windows, instead
# of j and k.
# * Super + z does zooming.
# * Super + x toggles scratch; add Shift to set it.
# * Alt + Space to seek among windows (Shift to reverse)
# * Super + Space to swap windows (Shift to reverse)
# * Super + X to toggle scratch; Super + Shift + X to set scratch
screen 0 {
general {
border = 3
sloppy_focus = true
sloppy_focus_raise = false
new_get_focus = true
new_become_master = true
resize_hints = false
}
styles {
normal {
font = "Inconsolata 10"
fg = "#bbbbbb"
bg = "#000000"
border = "#262524"
}
focus { fg = "#000000" bg = "#728BA2" border = "#993126" }
urgent { fg = "#111111" bg = "#ff4500" border = "#ff4500" }
}
titlebar {
position = "top"
text_align = "center"
height = "14"
styles {
normal { bg = "#262524" }
focus { fg = "#ffffff" bg = "#262524" }
urgent { fg = "#ffffff" bg = "#ff4500" }
}
}
tags
{
tag q { }
tag w { layout = "tilebottom" mwfact = .5 }
tag e { mwfact = .85 nmaster = 1 }
tag r { layout = "tileleft" }
tag t { }
tag a { }
tag s { }
tag d { nmaster = 2 }
tag f { layout = "floating" }
}
layouts
{
layout tile { image = "/usr/local/share/awesome/icons/layouts/tilew.png" }
layout tileleft { image = "/usr/local/share/awesome/icons/layouts/tileleftw.png" }
layout tilebottom { image = "/usr/local/share/awesome/icons/layouts/tilebottomw.png" }
layout tiletop { image = "/usr/local/share/awesome/icons/layouts/tiletopw.png" }
#layout max { image = "/usr/local/share/awesome/icons/layouts/maxw.png" }
#layout spiral { image = "/usr/local/share/awesome/icons/layouts/spiralw.png" }
#layout floating { image = "/usr/local/share/awesome/icons/layouts/floatingw.png" }
}
statusbar topbar
{
position = "top"
taglist thetags {
mouse { button = "1" command = "tag_view" }
mouse { button = "3" command = "tag_toggleview" }
mouse { button = "4" command = "tag_viewnext" }
mouse { button = "5" command = "tag_viewprev" }
}
layoutinfo mylayoutinfo {
mouse { button = "1" command = "tag_setlayout" arg = "+1" }
mouse { button = "4" command = "tag_setlayout" arg = "+1" }
mouse { button = "3" command = "tag_setlayout" arg = "-1" }
mouse { button = "5" command = "tag_setlayout" arg = "-1" }
}
emptybox clockspacer { align = "left" width = 40 }
textbox clock { align = "left" }
emptybox countdownspacer { align = "left" width = 20 }
textbox countdown { align = "left" }
textbox music { align = "right" }
emptybox musicspacer { align = "right" width = 20 }
progressbar musicprogress {
width = 100
align = "right"
data track {
bordercolor = "#666666"
fg = "#333333"
}
}
emptybox cpuspacer { align = "right" width = 20 }
textbox cpulabel { align = "right" text = "CPU" }
graph cpu {
width = 200
align = "right"
bordercolor = "#000000"
grow = "right"
data cpu0 {
max = 100.0
scale = false
fg = "#940808"
draw_style = "line"
}
data cpu1 {
max = 100.0
scale = false
fg = "#084994"
draw_style = "line"
}
}
emptybox diskrootspacer { align = "right" width = 20 }
textbox diskrootlabel { align = "right" text = "/ " }
progressbar diskroot {
width = 100
align = "right"
data root {
bordercolor = "#666666"
fg = "#333333"
}
}
textbox diskrootwarning { align = "right" style { fg = "#FF0000" } }
emptybox diskhomespacer { align = "right" width = 20 }
textbox diskhomelabel { align = "right" text = "/home " }
progressbar diskhome {
width = 100
align = "right"
data home {
bordercolor = "#666666"
fg = "#333333"
}
}
textbox diskhomewarning { align = "right" style { fg = "#FF0000" } }
emptybox endspacer { align = "right" width = 5 }
}
}
rules {
rule { name = "Gimp" float = true }
rule { name = "MPlayer" float = true }
rule { name = "Acroread" float = true }
rule { name = "pinentry" float = true }
rule { name = "Authorize Passphrase Access" float = true }
rule { name = "Add-ons" float = true }
rule { name = "Guake" float = true }
rule {
name = "rdesktop: ts[123].rose-hulman.edu"
tags = "f"
titlebar { position = off }
}
rule {
name = "Mozilla Thunderbird" # The main window on startup
tags = "w"
}
rule {
name = "Exaile"
tags = "e"
master = true
}
rule {
name = "Buddy List"
tags = "e"
titlebar { position = off }
}
rule {
name = "stalonetray"
float = true
titlebar { position = off }
}
rule {
name = "WASTE"
tags = "d"
}
rule {
name = "Totem|VirtualBox OSE|Pidgin|SciTE|Terminal|VLC media player"
titlebar { position = off }
}
}
mouse {
client {
modkey = {"Mod4"}
button = "1"
command = "client_movemouse"
}
client {
modkey = {"Mod4"}
button = "2"
command = "client_zoom"
}
client {
modkey = {"Mod4"}
button = "3"
command = "client_resizemouse"
}
titlebar {
button = "1"
command = "client_movemouse"
}
titlebar {
button = "3"
command = "client_resizemouse"
}
}
keys {
key {
key = "F1"
command = "spawn"
arg = "gnome-terminal"
}
key {
modkey = {"Mod4"}
key = "F2"
command = "spawn"
arg = "cat ~/.local/menu-cache | awesome-menu -e 'exec ' Execute:"
}
key {
modkey = {"Mod4"}
key = "F3"
command = "spawn"
arg = "cut -d' ' -f1 ~/.ssh/known_hosts | cut -d, -f1 | awesome-menu -e 'gnome-terminal -e ssh ' 'ssh to:'"
}
key {
modkey = {"Mod4"}
key = "Return"
command = "spawn"
arg = "exec gnome-terminal"
}
key {
modkey = {"Mod4"}
key = "u"
command = "tag_setlayout"
arg = "+1"
}
key {
modkey = {"Mod4", "Shift"}
key = "u"
command = "tag_setlayout"
arg = "-1"
}
key {
modkey = {"Mod4"}
key = "b"
command = "statusbar_toggle"
}
key {
modkey = {"Mod1"}
key = "space"
command = "client_focusnext"
}
key {
modkey = {"Mod1", "Shift"}
key = "space"
command = "client_focusprev"
}
key {
modkey = {"Mod4"}
key = "Tab"
command = "focus_history"
arg = "-1"
}
key {
modkey = {"Mod4"}
key = "space"
command = "client_swapnext"
}
key {
modkey = {"Mod4", "Shift"}
key = "space"
command = "client_swapprev"
}
key {
modkey = {"Mod4", "Control"}
key = "j"
command = "screen_focus"
arg = "+1"
}
key {
modkey = {"Mod4", "Control"}
key = "k"
command = "screen_focus"
arg = "-1"
}
key {
modkey = {"Mod4"}
key = "h"
command = "tag_setmwfact"
arg = "-0.05"
}
key {
modkey = {"Mod4"}
key = "l"
command = "tag_setmwfact"
arg = "+0.05"
}
keylist {
modkey = {"Mod4"}
command = "tag_setnmaster"
keylist = { 1, 2, 3, 4 }
arglist = { 1, 2, 3, 4 }
}
keylist {
modkey = {"Mod4", "Shift"}
command = "tag_setncol"
keylist = { 1, 2, 3, 4 }
arglist = { 1, 2, 3, 4 }
}
key {
modkey = {"Mod4"}
key = "backspace"
command = "tag_prev_selected"
}
key {
modkey = {"Mod4"}
key = "Left"
command = "tag_viewprev"
}
key {
modkey = {"Mod4"}
key = "Right"
command = "tag_viewnext"
}
key {
modkey = {"Mod4"}
key = "m"
command = "client_togglemax"
}
key {
modkey = {"Mod4"}
key = "z"
command = "client_zoom"
}
key {
modkey = {"Mod4"}
key = "v"
command = "client_togglefloating"
}
key {
modkey = {"Mod4"}
key = "x"
command = "client_togglescratch"
}
key {
modkey = {"Mod4"}
key = "n"
command = "spawn"
arg = "nautilus --no-desktop"
}
key {
modkey = {"Mod4", "Shift"}
key = "x"
command = "client_setscratch"
}
key {
modkey = {"Mod4"}
key = "Escape"
command = "client_kill"
}
key {
modkey = {"Mod4", "Control", "Shift"}
key = "Escape"
command = "restart"
}
key {
modkey = {"Mod4"}
key = "0"
command = "tag_view"
}
keylist {
modkey = {"Mod4"}
command = "tag_view"
keylist = { q, w, e, r, t, a, s, d, f }
arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
}
key {
modkey = {"Mod4", "Control"}
key = "0"
command = "tag_toggleview"
}
keylist {
modkey = {"Mod4", "Control"}
command = "tag_toggleview"
keylist = { q, w, e, r, t, a, s, d, f }
arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
}
key {
modkey = {"Mod4", "Shift"}
key = "0"
command = "client_tag"
}
keylist {
modkey = {"Mod4", "Shift"}
command = "client_tag"
keylist = { q, w, e, r, t, a, s, d, f }
arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
}
key {
modkey = {"Mod4", "Shift", "Control"}
key = "0"
command = "client_toggletag"
}
keylist {
modkey = {"Mod4", "Shift", "Control"}
command = "client_toggletag"
keylist = { q, w, e, r, t, a, s, d, f }
arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
}
}
# vim: filetype=conf
[edit] awesome-clock.py
This increasingly poorly-named script is responsible for updating the clock, countdown, CPU graph, and disk usage widgets.
File: awesome-clock.py
#!/usr/bin/python
from __future__ import with_statement, division
import os
import sys
import signal
import atexit
import itertools
from time import sleep
from subprocess import Popen, PIPE
from datetime import time, date, datetime
CPU_COUNT = 2
CLOCK_FORMAT = '0 widget_tell topbar clock text %s\n\n'
COUNTDOWN_FORMAT = '0 widget_tell topbar countdown text %s until %s\n\n'
CPU_FORMAT = '0 widget_tell topbar cpu data cpu%d %d\n'
DISK_FORMAT = '0 widget_tell topbar disk%s data %s %d\n'
DISK_WARNING_FORMAT = '0 widget_tell topbar disk%swarning text %s\n'
is_weekday = lambda d,t: (d.weekday() < 6)
is_tuesday = lambda d,t: (d.weekday() == 1)
is_wednesday = lambda d,t: (d.weekday() == 2)
is_thursday = lambda d,t: (d.weekday() == 3)
is_weekday_not_wed = lambda d,t: (is_weekday(d,t) and not is_wednesday(d,t))
is_sunday = lambda d,t: (d.weekday() == 6)
events = [
# No class until 3rd period this quarter!
#(time( 8, 5), 'start of 1st period', is_weekday),
#(time( 8, 55), 'end of 1st period', is_weekday),
#(time( 9, 0), 'start of 2nd period', is_weekday),
#(time( 9, 50), 'end of 2nd period', is_weekday),
(time( 9, 55), 'start of 3rd period', is_weekday_not_wed),
(time(10, 45), 'end of 3rd period', is_weekday_not_wed),
(time(10, 50), 'start of 4th period', is_weekday_not_wed),
(time(11, 40), 'end of 4th period', is_weekday_not_wed),
(time(11, 45), 'start of 5th period', is_weekday_not_wed),
(time(12, 35), 'end of 5th period', is_weekday_not_wed),
(time(12, 40), 'start of 6th period', is_weekday_not_wed),
(time(13, 30), 'end of 6th period', is_weekday_not_wed),
(time(13, 35), 'start of 7th period', is_weekday_not_wed),
(time(14, 25), 'end of 7th period', is_weekday_not_wed),
(time(14, 30), 'start of 8th period', is_weekday_not_wed),
(time(15, 00), 'start of RT all-team meeting', is_sunday),
(time(15, 20), 'end of 8th period', is_weekday_not_wed),
#(time(16, 25), 'start of 9th period', is_weekday_not_wed),
#(time(17, 15), 'end of 9th period', is_weekday_not_wed),
#(time(17, 20), 'start of 10th period', is_weekday_not_wed),
#(time(18, 10), 'end of 10th period', is_weekday_not_wed),
(time(17, 15), 'start of LUG meeting', is_thursday),
(time(17, 30), 'start of Thorn meeting', is_wednesday),
(time(19, 30), 'start of RT administrative meeting', is_tuesday),
(time(21, 00), 'start of RT software meeting', is_wednesday),
(time(23, 59, 59), 'midnight', lambda d,t: True)
]
events.sort()
def format_datetime(dt):
'Format a datetime to a nice, pretty string.'
return dt.strftime('%A %d %B %Y %l:%M:%S %p'
).replace('AM', 'a.m.').replace('PM', 'p.m.')
def pluralize(s, v):
return s % (v, 's' if v != 1 else '')
def interval(time1, time2):
'Convert a duration to humanized text.'
dt1 = datetime.combine(date.today(), time1)
dt2 = datetime.combine(date.today(), time2)
seconds = (dt2 - dt1).seconds
s = []
if seconds > (60 * 60):
s.append('%dh' % (seconds // (60 * 60),))
seconds %= (60 * 60)
if seconds > 60:
s.append('%dm' % (seconds // 60,))
seconds %= 60
if not s:
s.append('%ds' % seconds)
return ', '.join(s)
def update(s):
client.stdin.write(s)
def clock_update():
now = datetime.now()
update(CLOCK_FORMAT % format_datetime(now))
for time, event, test in events:
if time > now.time() and test(now.date(), now.time()):
break
update(COUNTDOWN_FORMAT % (interval(now.time(), time), event))
def cpu_update():
with open('/proc/stat') as stat:
stat.readline() # overall usage; we don't care
for i in range(CPU_COUNT):
perc = cpu_line_calc(i, stat.readline())
update(CPU_FORMAT % (i, perc))
_old_lines = [(0, 0, 0)] * CPU_COUNT
def cpu_line_calc(i, line):
user, nice, system, idle = map(int, line.strip().split()[1:5])
total = user + nice + system + idle
old_system, old_user, old_total = _old_lines[i]
_old_lines[i] = (system, user, total)
return (100 * (system - old_system + user - old_user) / (total - old_total))
DISKS = [
('root', '/'),
('home', '/home'),
]
def disk_update(name, mount_point):
df = Popen(['df', mount_point, '-h'], stdout=PIPE)
df.stdout.readline() # headers; don't care
avail, use = df.stdout.readline().split()[3:5]
df.stdout.close()
use = int(use[:-1])
update(DISK_FORMAT % (name, name, use))
if use >= 99:
update(DISK_WARNING_FORMAT % (name, ' ONLY %s LEFT!!!' % avail))
else:
update(DISK_WARNING_FORMAT % (name, ''))
if __name__ == '__main__':
pid_file = '/tmp/awesome-clock-%s.pid' % os.getuid()
# Kill any running awesome-clock.py
try:
pid = int(open(pid_file, 'r').read())
os.kill(pid, signal.SIGINT)
except (IOError, OSError, ValueError):
pass
with open(pid_file, 'w') as f:
f.write(str(os.getpid()))
atexit.register(lambda: os.unlink(pid_file))
client = Popen(['awesome-client'], stdin=PIPE, bufsize=1)
cpu_skip = itertools.cycle(range(4)).next
disk_skip = itertools.cycle(range(40)).next
while True:
clock_update()
if not cpu_skip():
cpu_update()
if not disk_skip():
for name, mount_point in DISKS:
disk_update(name, mount_point)
client.stdin.write('\n')
client.stdin.flush()
sleep(.25)
[edit] awesome-exaile.py
Updates the music widgets by communicating with Exaile via d-bus.
File: awesome-exaile.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import time
import dbus
import subprocess
# The widget to update
TEXT_PREFIX = '0 widget_tell topbar music text '
PROG_PREFIX = '0 widget_tell topbar musicprogress data track'
status_symbol_map = {
'playing': u'▶',
'stopped': u'▆',
'paused': u'▍▍',
}
bus = dbus.SessionBus()
client = subprocess.Popen(['awesome-client'],
stdin=subprocess.PIPE, bufsize=0)
def update(*s):
client.stdin.write(u' '.join(s).encode('utf-8'))
client.stdin.write('\n\n')
client.stdin.flush()
while True:
try:
exaile = bus.get_object('org.exaile.DBusInterface',
'/DBusInterfaceObject')
exaile_if = dbus.Interface(exaile, 'org.exaile.DBusInterface')
while True:
status = exaile_if.status()
if status != 'stopped':
title = exaile_if.get_title()
artist = exaile_if.get_artist()
album = exaile_if.get_album()
if album:
album = u" %s" % album
length = exaile_if.get_length()
pos = ord(str(exaile_if.current_position()))
status_symbol = status_symbol_map.get(status, status.capitalize())
update(TEXT_PREFIX, status_symbol, u" ", title, u" ",
artist, album, u" %d%% of %s" % (pos, length))
update(PROG_PREFIX, str(pos))
else:
update(TEXT_PREFIX, "Stopped")
update(PROG_PREFIX, '0')
time.sleep(1)
except dbus.exceptions.DBusException, e:
update(TEXT_PREFIX, '')
update(PROG_PREFIX, '0')
time.sleep(10)
continue

