aboutsummaryrefslogtreecommitdiffstats
path: root/.i3
diff options
context:
space:
mode:
Diffstat (limited to '.i3')
-rw-r--r--.i3/config362
-rw-r--r--.i3/images/wallpaper.pngbin0 -> 87684 bytes
-rw-r--r--.i3/py3status.conf78
-rw-r--r--.i3/py3status/10-mpd.py117
-rw-r--r--.i3/py3status/20-volume.py112
-rw-r--r--.i3/py3status/25-microphone.py105
-rw-r--r--.i3/py3status/30-touchpad.py86
-rw-r--r--.i3/py3status/40-power.py73
-rw-r--r--.i3/py3status/50-battery.py106
-rw-r--r--.i3/py3status/80-datetime.py76
-rw-r--r--.i3/py3status/backup/dpms.py44
-rw-r--r--.i3/py3status/backup/empty_class.py41
-rw-r--r--.i3/py3status/backup/glpi.py52
-rw-r--r--.i3/py3status/backup/i3bar_click_events.py127
-rw-r--r--.i3/py3status/backup/netdata.py132
-rw-r--r--.i3/py3status/backup/ns_checker.py57
-rw-r--r--.i3/py3status/backup/pingdom.py59
-rw-r--r--.i3/py3status/backup/pomodoro.py123
-rw-r--r--.i3/py3status/backup/sysdata.py137
-rw-r--r--.i3/py3status/backup/weather_yahoo.py106
-rw-r--r--.i3/py3status/backup/whoami.py26
-rwxr-xr-x.i3/scripts/i3exit.sh43
22 files changed, 2062 insertions, 0 deletions
diff --git a/.i3/config b/.i3/config
new file mode 100644
index 0000000..3388538
--- /dev/null
+++ b/.i3/config
@@ -0,0 +1,362 @@
+###########################################################
+## ~/.i3/config
+##
+## i3 config file (v4)
+## Ref: http://i3wm.org/docs/userguide.html
+##
+## Weitian LI <liweitianux@gmail.com>
+## 2014/05/10
+###########################################################
+
+###### NOTES ###### {{{
+# To get a config file with the same key positions, but for your current
+# layout, use the `i3-config-wizard'
+###### NOTES ###### }}}
+
+###### variables ###### {{{
+## modifier
+# Mod1: Alt
+# Mod4: Win
+set $mod Mod1
+set $sup Mod4
+
+# variables used in this config
+set $i3_scripts ~/.i3/scripts
+set $i3_images ~/.i3/images
+
+# screenshots directory
+set $shots_dir ~/pictures/screenshots
+###### variables ###### }}}
+
+###### settings ###### {{{
+# Font for window titles. (also for bar if not specified)
+# ISO 10646: Unicode
+# Use pango to choose FreeType fonts
+#font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+#font pango:DejaVu Sans Mono 10
+font pango:Terminus, WenQuanYi Bitmap Song, Icons, FontAwesome, 10
+
+# use `Mouse+$mod' to drag floating windows
+floating_modifier $mod
+
+# focus follows mouse (default yes)
+#focus_follows_mouse no
+
+# timeout of urgency hint on workspace change (default 500ms)
+force_display_urgency_hint 1000 ms
+
+# ipc (`i3-msg' to run i3 commands)
+ipc-socket ~/.i3/i3-ipc.sock
+###### settings ###### }}}
+
+###### appearance ###### {{{
+# border style
+#new_window 1pixel
+bindsym $mod+t border normal
+bindsym $mod+y border 1pixel
+bindsym $mod+u border none
+
+# orientation for new workspaces
+default_orientation auto
+
+# hide vertical borders adjacent to the screen edge
+#hide_edge_borders vertical
+
+### colors
+## solarized colorscheme (customized) {{{
+client.background #1e2320
+# colorclass border background text indicator
+client.focused #859900 #859900 #fdf6e3 #2e9ef4
+client.focused_inactive #268bd2 #268bd2 #fdf6e3 #484e50
+client.unfocused #93a1a1 #93a1a1 #fdf6e3 #292d2e
+client.urgent #cb4b16 #cb4b16 #fdf6e3 #2e9ef4
+## colorscheme }}}
+#
+###### appearance ###### }}}
+
+###### workspace ###### {{{
+# name workspace
+set $ws1 1gentoo
+set $ws2 2term
+set $ws3 3vim
+set $ws4 4web
+set $ws5 5work
+set $ws6 6media
+set $ws7 7game
+set $ws8 8sys
+set $ws9 9misc
+set $ws0 0float
+
+# switch to workspace
+bindsym $mod+1 workspace $ws1
+bindsym $mod+2 workspace $ws2
+bindsym $mod+3 workspace $ws3
+bindsym $mod+4 workspace $ws4
+bindsym $mod+5 workspace $ws5
+bindsym $mod+6 workspace $ws6
+bindsym $mod+7 workspace $ws7
+bindsym $mod+8 workspace $ws8
+bindsym $mod+9 workspace $ws9
+bindsym $mod+0 workspace $ws0
+# auto back-and-forth when switched to the current workspace
+workspace_auto_back_and_forth yes
+
+# move focused container to workspace
+bindsym $mod+Shift+1 move container to workspace $ws1
+bindsym $mod+Shift+2 move container to workspace $ws2
+bindsym $mod+Shift+3 move container to workspace $ws3
+bindsym $mod+Shift+4 move container to workspace $ws4
+bindsym $mod+Shift+5 move container to workspace $ws5
+bindsym $mod+Shift+6 move container to workspace $ws6
+bindsym $mod+Shift+7 move container to workspace $ws7
+bindsym $mod+Shift+8 move container to workspace $ws8
+bindsym $mod+Shift+9 move container to workspace $ws9
+bindsym $mod+Shift+0 move container to workspace $ws0
+# move to provided workspace
+bindsym $mod+Shift+m exec i3-input -F 'move container to workspace "%s"' -P 'move to workspace: '
+
+# assign workspace for applications
+assign [class="Gvim"] $ws3
+assign [class="Firefox" instance="Navigator"] $ws4
+assign [class="Vlc"] $ws6
+
+# switch workspace
+bindsym $mod+Tab workspace back_and_forth
+bindsym $mod+Ctrl+Left workspace prev
+bindsym $mod+Ctrl+Right workspace next
+# also bind ThinkPad 'XF86Back' and 'XF86Forward' keys
+#bindsym XF86Back workspace prev
+#bindsym XF86Forward workspace next
+###### workspace ###### }}}
+
+###### key bindings ###### {{{
+# start a terminal
+bindsym $mod+Return exec urxvtc || i3-sensible-terminal
+
+# kill focused window
+bindsym $mod+Shift+q kill
+bindsym $mod+F4 kill
+
+# change focus (h/j/k/l)
+bindsym $mod+h focus left
+bindsym $mod+j focus down
+bindsym $mod+k focus up
+bindsym $mod+l focus right
+
+# alternatively, you can use the cursor keys:
+bindsym $mod+Left focus left
+bindsym $mod+Down focus down
+bindsym $mod+Up focus up
+bindsym $mod+Right focus right
+
+# move focused window (h/j/k/l)
+bindsym $mod+Shift+h move left
+bindsym $mod+Shift+j move down
+bindsym $mod+Shift+k move up
+bindsym $mod+Shift+l move right
+
+# alternatively, you can use the cursor keys:
+bindsym $mod+Shift+Left move left
+bindsym $mod+Shift+Down move down
+bindsym $mod+Shift+Up move up
+bindsym $mod+Shift+Right move right
+
+# split in horizontal orientation
+bindsym $mod+Shift+v split h
+
+# split in vertical orientation
+bindsym $mod+v split v
+
+# enter fullscreen mode for the focused container
+bindsym $mod+f fullscreen
+
+# change container layout (stacked, tabbed, toggle split)
+bindsym $mod+s layout stacking
+bindsym $mod+w layout tabbed
+bindsym $mod+e layout toggle split
+
+# toggle tiling / floating
+bindsym $mod+Shift+space floating toggle
+
+# change focus between tiling / floating windows
+bindsym $mod+space focus mode_toggle
+
+# focus the parent container
+bindsym $mod+a focus parent
+
+# focus the child container
+bindsym $mod+c focus child
+
+## scratchpad
+# move the currently focused window to the scratchpad
+bindsym $mod+Shift+minus move scratchpad
+# Show the next scratchpad window or hide the focused scratchpad window.
+# If there are multiple scratchpad windows, this command cycles through them.
+bindsym $mod+minus scratchpad show
+
+# reload the configuration file
+bindsym $mod+Shift+c reload
+# restart i3 inplace (preserves layout/session, can be used to upgrade i3)
+bindsym $mod+Shift+r restart
+# exit i3 (logs you out of your X session)
+bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"
+###### key bindings ###### }}}
+
+###### i3 modes ###### {{{
+# resize window (you can also use the mouse for that)
+mode "resize" {
+ # These bindings trigger as soon as you enter the resize mode
+ # Pressing left will shrink the window's width.
+ # Pressing right will grow the window's width.
+ # Pressing up will shrink the window's height.
+ # Pressing down will grow the window's height.
+ bindsym h resize shrink width 10 px or 10 ppt
+ bindsym j resize grow height 10 px or 10 ppt
+ bindsym k resize shrink height 10 px or 10 ppt
+ bindsym l resize grow width 10 px or 10 ppt
+ # same bindings, but for the arrow keys
+ bindsym Left resize shrink width 10 px or 10 ppt
+ bindsym Down resize grow height 10 px or 10 ppt
+ bindsym Up resize shrink height 10 px or 10 ppt
+ bindsym Right resize grow width 10 px or 10 ppt
+ # back to normal: Enter or Escape
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+bindsym $mod+r mode "resize"
+
+# mode_system: prompt for lock, logout, suspend, shutdown, etc.
+set $mode_system System (l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown
+mode "$mode_system" {
+ bindsym l exec --no-startup-id $i3_scripts/i3exit.sh lock, mode "default"
+ bindsym e exec --no-startup-id $i3_scripts/i3exit.sh logout, mode "default"
+ bindsym s exec --no-startup-id $i3_scripts/i3exit.sh suspend, mode "default"
+ bindsym h exec --no-startup-id $i3_scripts/i3exit.sh hibernate, mode "default"
+ bindsym r exec --no-startup-id $i3_scripts/i3exit.sh reboot, mode "default"
+ bindsym Shift+s exec --no-startup-id $i3_scripts/i3exit.sh shutdown, mode "default"
+ # back to normal: Enter or Escape
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+bindsym $mod+Ctrl+Delete mode "$mode_system"
+###### i3 modes ###### }}}
+
+###### applications bindings ###### {{{
+## NOTE: (Mod4: Win)
+## Some Mod4-keys binded for urxvt (~/.Xresources)
+## Mod4-c, Mod4-v, Mod4-Shift-v
+## Mod4-Escape, Mode4-s, Mod4-u
+
+# dmenu & i3-dmenu-desktop
+bindsym $mod+d exec --no-startup-id dmenu_run
+bindsym $mod+F2 exec --no-startup-id dmenu_run
+# `i3-dmenu-desktop' only displays applications with a .desktop file
+bindsym $mod+p exec --no-startup-id i3-dmenu-desktop
+
+# lock screen (i3lock)
+bindsym $mod+Ctrl+l exec --no-startup-id $i3_scripts/i3exit.sh lock
+# turn off display
+bindsym $mod+Ctrl+b exec --no-startup-id sleep 1 && xset dpms force off
+
+# screenshots
+bindsym Print exec --no-startup-id scrot -e 'mv $f $shots_dir/$f'
+bindsym $mod+Print exec --no-startup-id scrot -s -e 'mv $f $shots_dir/$f'
+
+# terminal
+bindsym $sup+t exec urxvtc || urxvt || i3-sensible-terminal
+# file manager
+bindsym $sup+f exec thunar
+# web browser
+bindsym $sup+w exec ~/bin/firefox || firefox
+
+## dropdown terminal
+# auto start urxvt if closed
+exec --no-startup-id "while true; do urxvt -name 'dropdown_term'; done"
+#for_window [instance="dropdown_term"] floating enable, border 1pixel
+#for_window [instance="dropdown_term"] move scratchpad; [instance="dropdown_term"] scratchpad show; resize shrink height 100px; resize grow width 626px; move position 1px 20px; move scratchpad
+for_window [instance="dropdown_term"] floating enable, border 1pixel, resize shrink height 100px, resize grow width 626px, move position 1px 20px
+for_window [instance="dropdown_term"] move scratchpad
+bindsym $mod+backslash [instance="dropdown_term"] scratchpad show
+###### applications bindings ###### }}}
+
+###### window control ###### {{{
+## floating
+for_window [window_role="pop-up"] floating enable
+for_window [class="Feh"] floating enable
+for_window [class="XFontSel"] floating enable
+for_window [class="Arandr"] floating enable
+for_window [class="Xfce4-notifyd"] floating enable
+for_window [class="Xscreensaver-demo"] floating enable
+for_window [class="Pinentry-gtk-2"] floating enable
+for_window [class="Ds9"] floating enable
+for_window [class="Toplevel"] floating enable
+for_window [class="Firefox" instance="Places"] floating enable
+for_window [class="Firefox" instance="Browser"] floating enable
+for_window [class="Firefox" instance="Update"] floating enable
+## floating by title
+# xbindkeys
+for_window [title="^XBindKey:.*Hit.*"] floating enable
+# xev
+for_window [title="^Event Tester$"] floating enable
+# thunar copy files
+for_window [title="^File Operation Progress$"] floating enable
+
+## adjust window border
+for_window [class="URxvt"] border 1pixel
+for_window [class="Firefox"] border 1pixel
+for_window [class="Xfce4-notifyd"] border none
+###### window control ###### }}}
+
+###### i3bar ###### {{{
+# i3bar (plus the system information i3status finds out, if available)
+bar {
+ #status_command py3status -c ~/.i3/py3status.conf
+ status_command py3status -s -c ~/.i3/py3status.conf
+ position top
+ # whether show the current binding mode indicator (default yes)
+ #binding_mode_indicator no
+
+ ## color theme
+ colors {
+ ## zenburn colorscheme (customized) {{{
+ background #1e2320
+ statusline #dcdccc
+ separator #94bff3
+ # colorclass border background text
+ focused_workspace #506070 #506070 #ffffff
+ active_workspace #dcdccc #506070 #ffffff
+ inactive_workspace #dcdccc #1e2320 #dcdccc
+ urgent_workspace #dcdccc #cb4b16 #dcdccc
+ ## colorscheme }}}
+ #
+ ## solarized colorscheme {{{
+ #background #073642
+ #statusline #eee8d5
+ #focused_workspace #cb4b16 #cb4b16 #eee8d5
+ #active_workspace #cb4b16 #cb4b16 #eee8d5
+ #inactive_workspace #b58900 #b58900 #eee8d5
+ ## solarized }}}
+ }
+}
+###### i3bar ###### }}}
+
+###### autostart ###### {{{
+## run applications on startup
+## if need to run command when restarting i3, use `exec_always'
+# disable bell
+exec --no-startup-id xset b off
+exec --no-startup-id xrdb -load ~/.Xresources
+exec --no-startup-id sh ~/.fehbg
+exec --no-startup-id xcompmgr
+exec --no-startup-id xbindkeys
+exec --no-startup-id urxvtd -q -o -f
+exec --no-startup-id parcellite
+exec --no-startup-id fcitx
+exec --no-startup-id nm-applet
+exec --no-startup-id xbacklight -set 80
+exec --no-startup-id xscreensaver -no-splash
+exec --no-startup-id xfce4-power-manager
+exec --no-startup-id mpd
+###### autostart ###### }}}
+
+# vim: set ts=8 sw=4 tw=0 fenc=utf-8 ft=conf: #
diff --git a/.i3/images/wallpaper.png b/.i3/images/wallpaper.png
new file mode 100644
index 0000000..468b1a9
--- /dev/null
+++ b/.i3/images/wallpaper.png
Binary files differ
diff --git a/.i3/py3status.conf b/.i3/py3status.conf
new file mode 100644
index 0000000..d19b4b8
--- /dev/null
+++ b/.i3/py3status.conf
@@ -0,0 +1,78 @@
+## ~/.i3/py3status.conf
+##
+## py3status configuration file
+## same syntax as 'i3status.conf' (man i3status)
+##
+
+# It is important that this file is edited as *UTF-8*.
+# The following line should contain a sharp s:
+# ß
+# If the above line is not correctly displayed, fix your editor first!
+
+general {
+ colors = true
+ color_good = '#dcdccc'
+ color_degraded = '#8cd0d3'
+ color_bad = '#dc8cc3'
+ interval = 3
+ # output format (i3bar|dzen2|xmobar|none)
+ output_format = 'i3bar'
+}
+
+#order += "volume master"
+#order += "ipv6"
+#order += "disk /"
+#order += "run_watch DHCP"
+#order += "run_watch VPN"
+#order += "wireless wlp3s0"
+#order += "ethernet enp0s25"
+order += "battery 0"
+order += "load"
+#order += "tztime local"
+
+volume master {
+ format = "%volume"
+ device = "default"
+ mixer = "Master"
+ mixer_idx = 0
+}
+
+wireless wlp3s0 {
+ #format_up = "W: (%quality at %essid) %ip"
+ format_up = "%essid(%ip)"
+ format_down = "down"
+}
+
+ethernet enp0s25 {
+ # if you use %speed, i3status requires root privileges
+ format_up = "E: %ip"
+ format_down = "E: down"
+}
+
+battery 0 {
+ format = "%status %percentage %remaining"
+}
+
+run_watch DHCP {
+ #pidfile = "/var/run/dhclient*.pid"
+ pidfile = "/var/run/dhcpd*.pid"
+}
+
+run_watch VPN {
+ pidfile = "/var/run/vpnc/pid"
+}
+
+tztime local {
+ #format = "%Y-%m-%d %H:%M:%S"
+ format = "%m-%d|%H:%M"
+}
+
+load {
+ format = "%1min"
+}
+
+disk "/" {
+ format = "%free"
+}
+
+# vim: set ts=8 sw=4 tw=0 fenc=utf-8 ft=conf: #
diff --git a/.i3/py3status/10-mpd.py b/.i3/py3status/10-mpd.py
new file mode 100644
index 0000000..95b7b4f
--- /dev/null
+++ b/.i3/py3status/10-mpd.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/14
+
+"""
+mpd module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import os
+import re
+import subprocess
+import time
+
+
+POSITION = 0
+# regex to match the status string of 'mpc status' output
+mpd_status_p = re.compile(r'.*\n^\[([a-z]+)\]', re.M) # multiline
+
+class Py3status:
+ """
+ MPD module to show mpd status and play info.
+
+ This module also handle click events:
+ left button: mpc toggle
+ middle button: mpc stop
+ right button: mpc next
+ """
+
+ def mpd(self, i3status_output_json, i3status_config):
+ """
+ Display MPD status and song info.
+ """
+ response = {
+ 'full_text': '',
+ 'name': 'mpd',
+ 'instance': 'first',
+ }
+ # update response fields
+ self._update_response(i3status_config)
+ if self.color:
+ response['color'] = self.color
+ response['full_text'] = self.full_text
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ Handle click events.
+ """
+ if event['button'] == 1:
+ # left button click
+ cmd = 'mpc toggle'
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 2:
+ # middle button click
+ cmd = 'mpc stop'
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 3:
+ # right button click
+ cmd = 'mpc next'
+ cmd_output = subprocess.getoutput(cmd)
+ #
+ self._update_response(i3status_config)
+ os.system('killall -USR1 py3status')
+
+ def _update_response(self, i3status_config=None):
+ ## get mpd status
+ cmd = 'mpc status'
+ cmd_out = subprocess.getstatusoutput(cmd)
+ if cmd_out[0] == 0:
+ # mpd is running
+ mpd_status_m = mpd_status_p.match(cmd_out[1])
+ if mpd_status_m:
+ self.status = mpd_status_m.group(1)
+ else:
+ self.status = 'stopped'
+ else:
+ # mpd not running (N/A)
+ self.status = 'na'
+ ## set full_text and color
+ prompt = '' # Icons: uF198 (music)
+ if self.status == 'playing':
+ status_text = ' ' # Icons: uF04B (play)
+ cmd = 'mpc status -f "%artist%-%title%" | head -n 1'
+ song_text = subprocess.getoutput(cmd)
+ if i3status_config:
+ self.color = i3status_config['color_good']
+ elif self.status == 'paused':
+ status_text = ' ' # Icons: uF04C (pause)
+ cmd = 'mpc status -f "%title%" | head -n 1'
+ song_text = subprocess.getoutput(cmd)
+ if i3status_config:
+ self.color = i3status_config['color_degraded']
+ elif self.status == 'stopped':
+ status_text = '' # Icons: uF04D (stop)
+ song_text = ''
+ if i3status_config:
+ self.color = i3status_config['color_bad']
+ else:
+ # mpd not running (N/A)
+ status_text = '' # Icons: uF00D (X)
+ song_text = ''
+ if i3status_config:
+ self.color = i3status_config['color_bad']
+ # full_text
+ self.full_text = '{0} {1}{2}'.format(prompt, status_text, song_text)
+
diff --git a/.i3/py3status/20-volume.py b/.i3/py3status/20-volume.py
new file mode 100644
index 0000000..467764c
--- /dev/null
+++ b/.i3/py3status/20-volume.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/15
+
+"""
+volume module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import os
+import re
+import subprocess
+import time
+
+
+POSITION = 0
+DEVICE = 'default'
+MIXER = 'Master'
+# regex compile to match amixer output volume info
+amixer_rep = re.compile(r'.*\[(\d+)%\]\s*\[(on|off)\]')
+
+
+class Py3status:
+ """
+ Volume module to show volume info.
+
+ This module also handle click events:
+ left button: decrease volume
+ middle button: mute/unmute toggle
+ right button: increase volume
+ """
+
+ def myvolume(self, i3status_output_json, i3status_config):
+ """
+ Display volume info.
+
+ XXX: cannot use name 'volume' ??
+ """
+ response = {
+ 'full_text': '',
+ 'name': 'myvolume',
+ 'instance': 'first',
+ }
+ # update response fields
+ self._update_response(i3status_config)
+ if self.color:
+ response['color'] = self.color
+ response['full_text'] = self.full_text
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ Handle click events.
+ """
+ if event['button'] == 1:
+ # left button click
+ cmd = 'amixer -D "{0}" sset "{1}" "5%-" unmute'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 2:
+ # middle button click
+ cmd = 'amixer -D "{0}" sset "{1}" toggle'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 3:
+ # right button click
+ cmd = 'amixer -D "{0}" sset "{1}" "5%+" unmute'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ #
+ self._update_response(i3status_config)
+ os.system('killall -USR1 py3status')
+
+ def _update_response(self, i3status_config=None):
+ """
+ update self.full_text
+ """
+ # get volume info
+ cmd = 'amixer -D "{0}" sget "{1}" | tail -n 1'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ m = amixer_rep.match(cmd_output)
+ self.volume, self.status = m.group(1, 2)
+ if int(self.volume) > 60:
+ self.level = 'high'
+ prompt = '' # Icons: uF357 (volume-high)
+ if i3status_config:
+ self.color = i3status_config['color_degraded']
+ elif int(self.volume) > 30:
+ self.level = 'medium'
+ prompt = '' # Icons: uF359 (volume-medium)
+ if i3status_config:
+ self.color = i3status_config['color_good']
+ else:
+ self.level = 'low'
+ prompt = '' # Icons: uF358 (volume-low)
+ if i3status_config:
+ self.color = i3status_config['color_good']
+ # determine icon
+ if self.status == 'off':
+ prompt = '' # Icons: uF35A (volume-off)
+ if i3status_config:
+ self.color = i3status_config['color_bad']
+ # determine display info
+ self.full_text = '{0} {1}%'.format(prompt, self.volume)
+
diff --git a/.i3/py3status/25-microphone.py b/.i3/py3status/25-microphone.py
new file mode 100644
index 0000000..379a44c
--- /dev/null
+++ b/.i3/py3status/25-microphone.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/15
+
+"""
+microphone module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import os
+import re
+import subprocess
+
+
+POSITION = 0
+DEVICE = 'default'
+MIXER = 'Capture' # Microphone
+# regex compile to match amixer output volume info
+amixer_rep = re.compile(r'.*\[(\d+)%\]\s*\[(on|off)\]')
+
+
+class Py3status:
+ """
+ Microphone module to show microphone info.
+
+ This module also handle click events:
+ left button: decrease volume
+ middle button: mute/unmute toggle
+ right button: increase volume
+ """
+
+ def microphone(self, i3status_output_json, i3status_config):
+ """
+ Display microphone info.
+ """
+ response = {
+ 'full_text': '',
+ 'name': 'microphone',
+ 'instance': 'first',
+ }
+ # update response fields
+ self._update_response(i3status_config)
+ response['full_text'] = self.full_text
+ if self.color:
+ response['color'] = self.color
+ return (POSITION, response)
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ Handle click events.
+ """
+ if event['button'] == 1:
+ # left button click
+ cmd = 'amixer -D "{0}" sset "{1}" "5%-" unmute'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 2:
+ # middle button click
+ cmd = 'amixer -D "{0}" sset "{1}" toggle'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ elif event['button'] == 3:
+ # right button click
+ cmd = 'amixer -D "{0}" sset "{1}" "5%+" unmute'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ #
+ self._update_response(i3status_config)
+ os.system('killall -USR1 py3status')
+
+ def _update_response(self, i3status_config=None):
+ """
+ update self.full_text
+ """
+ # get volume info
+ cmd = 'amixer -D "{0}" sget "{1}" | tail -n 1'.format(DEVICE, MIXER)
+ cmd_output = subprocess.getoutput(cmd)
+ m = amixer_rep.match(cmd_output)
+ self.volume, self.status = m.group(1, 2)
+ prompt = '' # Icons: uF130 (mic-on)
+ if int(self.volume) > 60:
+ self.level = 'high'
+ if i3status_config:
+ self.color = i3status_config['color_degraded']
+ elif int(self.volume) > 30:
+ self.level = 'medium'
+ if i3status_config:
+ self.color = i3status_config['color_good']
+ else:
+ self.level = 'low'
+ if i3status_config:
+ self.color = i3status_config['color_good']
+ # determine icon
+ if self.status == 'off':
+ prompt = '' # Icons: uF131 (mic-off)
+ if i3status_config:
+ self.color = i3status_config['color_bad']
+ # determine display info
+ self.full_text = '{0} {1}%'.format(prompt, self.volume)
+
diff --git a/.i3/py3status/30-touchpad.py b/.i3/py3status/30-touchpad.py
new file mode 100644
index 0000000..195d6b1
--- /dev/null
+++ b/.i3/py3status/30-touchpad.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/15
+
+"""
+touchpad module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import os
+import re
+import subprocess
+
+
+POSITION = 0
+
+
+class Py3status:
+ """
+ Touchpad module to show the status of touchpad.
+
+ Click events:
+ left button: enable touchpad
+ middle button: toggle touchpad
+ """
+
+ def __init__(self):
+ """
+ get touchpad status
+ """
+ cmd = 'synclient -l | grep -c "TouchpadOff.*=.*0"'
+ touchpad_status = subprocess.getoutput(cmd)
+ if int(touchpad_status) == 1:
+ self.status = 'on'
+ else:
+ self.status = 'off'
+
+ def touchpad(self, i3status_output_json, i3status_config):
+ """
+ Display touchpad status.
+ """
+ #prompt = '' # Icons: uF10A (ipad)
+ prompt = '' # Icons: uF3E3 (palm)
+ response = {
+ 'full_text': '',
+ 'name': 'touchpad',
+ 'instance': 'first',
+ }
+ if self.status == 'on':
+ response['color'] = i3status_config['color_good']
+ status_text = '' # Icons: uF00C (check)
+ else:
+ response['color'] = i3status_config['color_bad']
+ status_text = '' # Icons: uF00D (cross)
+ response['full_text'] = '{0} {1}'.format(prompt, status_text)
+ return (POSITION, response)
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ Handle click events.
+ """
+ if event['button'] == 1:
+ # left button click
+ cmd = 'synclient TouchpadOff=0'
+ cmd_output = subprocess.getoutput(cmd)
+ self.status = 'on'
+ elif event['button'] == 2:
+ # middle button click
+ if self.status == 'on':
+ cmd = 'synclient TouchpadOff=1'
+ self.status = 'off'
+ else:
+ cmd = 'synclient TouchpadOff=0'
+ self.status = 'on'
+ cmd_output = subprocess.getoutput(cmd)
+ #
+ os.system('killall -USR1 py3status')
+
diff --git a/.i3/py3status/40-power.py b/.i3/py3status/40-power.py
new file mode 100644
index 0000000..96b8ce5
--- /dev/null
+++ b/.i3/py3status/40-power.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/15
+
+"""
+power module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import re
+import subprocess
+import time
+
+
+POSITION = 0
+
+BAT_PRESENT = '/sys/class/power_supply/BAT0/present'
+# regex to match the '1' at the beginning
+one_p = re.compile(r'(^1).*')
+
+
+class Py3status:
+ """
+ Power module to show whether AC/battery is online.
+
+ ac_status: online, offline
+ bat_status: present, na
+ """
+
+ def power(self, i3status_output_json, i3status_config):
+ """
+ Display power status.
+ """
+ response = {
+ 'full_text': '',
+ 'name': 'power',
+ 'instance': 'first',
+ }
+ # AC online
+ ac_cmd = 'on_ac_power'
+ ac_cmd_out = subprocess.getstatusoutput(ac_cmd)
+ if ac_cmd_out[0] == 0:
+ ac_text = '' # Icons: uF237 (ac-online)
+ self.ac_status = 'online'
+ response['color'] = i3status_config['color_good']
+ else:
+ ac_text = '' # Icons: uF236 (ac-offline)
+ self.ac_status = 'offline'
+ response['color'] = i3status_config['color_bad']
+ # Battery present
+ with open(BAT_PRESENT, 'r') as bat_present_f:
+ bat_present_c = bat_present_f.read()
+ bat_m = one_p.match(bat_present_c)
+ if bat_m.group(1):
+ bat_text = ' ' # Icons: uF3CF (battery-vertical)
+ self.bat_status = 'present'
+ else:
+ bat_text = ''
+ self.bat_status = 'na'
+ #
+ response['full_text'] = '{0} {1}'.format(ac_text, bat_text)
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
diff --git a/.i3/py3status/50-battery.py b/.i3/py3status/50-battery.py
new file mode 100644
index 0000000..5e88125
--- /dev/null
+++ b/.i3/py3status/50-battery.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/17
+
+"""
+battery module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import re
+import subprocess
+import time
+
+
+POSITION = 0
+
+BAT_ID = 0
+## uevent:
+## ENERGY_NOW: energy that battery has now
+## POWER_NOW: battery current discharging/charing rate
+BAT_UEVENT = '/sys/class/power_supply/BAT{0}/uevent'.format(BAT_ID)
+
+# regex to match pattern in 'uevent' contents'
+status_p = re.compile(r'.*STATUS=(\w+)', re.S)
+present_p = re.compile(r'.*PRESENT=(\d)', re.S)
+capacity_p = re.compile(r'.*CAPACITY=(\d+)', re.S)
+energynow_p = re.compile(r'.*ENERGY_NOW=(\d+)', re.S)
+powernow_p = re.compile(r'.*POWER_NOW=(\d+)', re.S)
+
+
+class Py3status:
+ """
+ Battery module to show battery information.
+
+ battery status: Full, Discharging, Charging, Unknown
+ """
+
+ def mybattery(self, i3status_output_json, i3status_config):
+ """
+ Display battery information.
+ """
+ response = {
+ 'full_text': '',
+ 'name': 'mybattery',
+ 'instance': 'first',
+ }
+ # open battery uevent file
+ with open(BAT_UEVENT, 'r') as bat_f:
+ bat_info = bat_f.read()
+ status_m = status_p.match(bat_info)
+ capacity_m = capacity_p.match(bat_info)
+ energynow_m = energynow_p.match(bat_info)
+ powernow_m = powernow_p.match(bat_info)
+ self.status = status_m.group(1)
+ self.capacity = int(capacity_m.group(1))
+ energynow = int(energynow_m.group(1))
+ powernow = int(powernow_m.group(1))
+ #
+ bat_text = '{0}%'.format(self.capacity)
+ if self.status == 'Full':
+ prompt = '' # Icons: uF213 (battery-full)
+ color = i3status_config['color_good']
+ elif self.status == 'Charging':
+ prompt = '' # Icons: uF211 (battery-charing)
+ color = i3status_config['color_degraded']
+ elif self.status == 'Discharging':
+ if self.capacity > 80:
+ prompt = '' # Icons: uF213 (battery-full)
+ color = i3status_config['color_good']
+ elif self.capacity > 60:
+ prompt = '' # Icons: uF214 (battery-high)
+ color = i3status_config['color_degraded']
+ elif self.capacity > 30:
+ prompt = '' # Icons: uF215 (battery-low)
+ color = i3status_config['color_degraded']
+ else:
+ prompt = '' # Icons: uF212 (battery-empty)
+ color = i3status_config['color_bad']
+ # calc remaining time
+ remaining_h = energynow // powernow
+ remaining_m = int((energynow % powernow) / powernow * 60)
+ if remaining_h:
+ remaining = '{0}h{1:02d}m'.format(remaining_h, remaining_m)
+ else:
+ remaining = '{0:02d}m'.format(remaining_m)
+ bat_text = '{0} {1}'.format(bat_text, remaining)
+ else:
+ # unknown battery status
+ prompt = '' # Icons: uF215 (battery-low)
+ prompt = prompt + ' ' # Icons: uF243 (question-sign)
+ color = i3status_config['color_bad']
+ #
+ response['full_text'] = '{0} {1}'.format(prompt, bat_text)
+ response['color'] = color
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
diff --git a/.i3/py3status/80-datetime.py b/.i3/py3status/80-datetime.py
new file mode 100644
index 0000000..5d578a0
--- /dev/null
+++ b/.i3/py3status/80-datetime.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Weitian LI <liweitianux@gmail.com>
+# 2014/05/15
+
+"""
+datetime module for py3status
+"""
+
+## Get output of shell command:
+## python 3.x:
+## >>> subprocess.getoutput(cmd)
+## >>> subprocess.getstatusoutput(cmd)
+## python 2.7.x:
+## >>> subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
+
+import re
+import subprocess
+import time
+
+
+# regext to match date and time from output of 'date'
+datetime_p = re.compile(r'(^\d+/\d+)\s*(\d+:\d+)')
+
+
+class Py3status:
+ """
+ Datetime module to show current date and time.
+ """
+
+ def mydate(self, i3status_output_json, i3status_config):
+ """
+ Display current date.
+ """
+ POSITION = 0
+ response = {
+ 'full_text': '',
+ 'name': 'mydate',
+ 'instance': 'first',
+ }
+ prompt = '' # Icons: uF073 (calendar)
+ # update datetime
+ self._get_datetime()
+ response['full_text'] = '{0} {1}'.format(prompt, self.date)
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
+ def mytime(self, i3status_output_json, i3status_config):
+ """
+ Display current time.
+ """
+ POSITION = 1
+ response = {
+ 'full_text': '',
+ 'name': 'mytime',
+ 'instance': 'first',
+ }
+ prompt = '' # Icons: uF017 (clock)
+ # update datetime
+ self._get_datetime()
+ response['full_text'] = '{0} {1}'.format(prompt, self.time)
+ # cache status for 5 seconds
+ response['cached_until'] = time.time() + 5
+ return (POSITION, response)
+
+ def _get_datetime(self):
+ """
+ Get current date and time
+ """
+ cmd = 'date "+%m/%d %H:%M"'
+ datetime = subprocess.getoutput(cmd)
+ dt_m = datetime_p.match(datetime)
+ self.date, self.time = dt_m.group(1, 2)
+
diff --git a/.i3/py3status/backup/dpms.py b/.i3/py3status/backup/dpms.py
new file mode 100644
index 0000000..783c53c
--- /dev/null
+++ b/.i3/py3status/backup/dpms.py
@@ -0,0 +1,44 @@
+from os import system
+
+
+class Py3status:
+ """
+ This module allows activation and deactivation
+ of DPMS (Display Power Management Signaling)
+ by clicking on 'DPMS' in the status bar.
+
+ Written and contributed by @tasse:
+ Andre Doser <dosera AT tf.uni-freiburg.de>
+ """
+ def __init__(self):
+ """
+ Detect current state on start.
+ """
+ self.run = system('xset -q | grep -iq "DPMS is enabled"') == 0
+
+ def dpms(self, i3status_output_json, i3status_config):
+ """
+ Display a colorful state of DPMS.
+ """
+ result = {
+ 'full_text': 'DPMS',
+ 'name': 'dpms'
+ }
+ if self.run:
+ result['color'] = i3status_config['color_good']
+ else:
+ result['color'] = i3status_config['color_bad']
+ return (0, result)
+
+ def on_click(self, json, i3status_config, event):
+ """
+ Enable/Disable DPMS on left click.
+ """
+ if event['button'] == 1:
+ if self.run:
+ self.run = False
+ system("xset -dpms")
+ else:
+ self.run = True
+ system("xset +dpms")
+ system("killall -USR1 py3status")
diff --git a/.i3/py3status/backup/empty_class.py b/.i3/py3status/backup/empty_class.py
new file mode 100644
index 0000000..077269c
--- /dev/null
+++ b/.i3/py3status/backup/empty_class.py
@@ -0,0 +1,41 @@
+class Py3status:
+ """
+ Empty and basic py3status class.
+
+ NOTE: py3status will NOT execute:
+ - methods starting with '_'
+ - methods decorated by @property and @staticmethod
+
+ NOTE: reserved method names:
+ - 'kill' method for py3status exit notification
+ - 'on_click' method for click events from i3bar
+ """
+ def kill(self, i3status_output_json, i3status_config):
+ """
+ This method will be called upon py3status exit.
+ """
+ pass
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ This method will be called when a click event occurs on this module's
+ output on the i3bar.
+
+ Example 'event' json object:
+ {'y': 13, 'x': 1737, 'button': 1, 'name': 'empty', 'instance': 'first'}
+ """
+ pass
+
+ def empty(self, i3status_output_json, i3status_config):
+ """
+ This method will return an empty text message
+ so it will NOT be displayed on your i3bar.
+
+ If you want something displayed you should write something
+ in the 'full_text' key of your response.
+
+ See the i3bar protocol spec for more information:
+ http://i3wm.org/docs/i3bar-protocol.html
+ """
+ response = {'full_text': '', 'name': 'empty', 'instance': 'first'}
+ return (0, response)
diff --git a/.i3/py3status/backup/glpi.py b/.i3/py3status/backup/glpi.py
new file mode 100644
index 0000000..929749d
--- /dev/null
+++ b/.i3/py3status/backup/glpi.py
@@ -0,0 +1,52 @@
+# You need MySQL-python from http://pypi.python.org/pypi/MySQL-python
+import MySQLdb
+
+
+class Py3status:
+ """
+ This example class demonstrates how to display the current total number of
+ open tickets from GLPI in your i3bar.
+
+ It features thresholds to colorize the output and forces a low timeout to
+ limit the impact of a server connectivity problem on your i3bar freshness.
+
+ Note that we don't have to implement a cache layer as it is handled by
+ py3status automagically.
+ """
+ def count_glpi_open_tickets(self, json, i3status_config):
+ response = {'full_text': '', 'name': 'glpi_tickets'}
+
+ # user-defined variables
+ CRIT_THRESHOLD = 20
+ WARN_THRESHOLD = 15
+ MYSQL_DB = ''
+ MYSQL_HOST = ''
+ MYSQL_PASSWD = ''
+ MYSQL_USER = ''
+ POSITION = 0
+
+ mydb = MySQLdb.connect(
+ host=MYSQL_HOST,
+ user=MYSQL_USER,
+ passwd=MYSQL_PASSWD,
+ db=MYSQL_DB,
+ connect_timeout=5,
+ )
+ mycr = mydb.cursor()
+ mycr.execute('''select count(*)
+ from glpi_tickets
+ where closedate is NULL and solvedate is NULL;''')
+ row = mycr.fetchone()
+ if row:
+ open_tickets = int(row[0])
+ if i3status_config['colors']:
+ if open_tickets > CRIT_THRESHOLD:
+ response.update({'color': i3status_config['color_bad']})
+ elif open_tickets > WARN_THRESHOLD:
+ response.update(
+ {'color': i3status_config['color_degraded']}
+ )
+ response['full_text'] = '%s tickets' % open_tickets
+ mydb.close()
+
+ return (POSITION, response)
diff --git a/.i3/py3status/backup/i3bar_click_events.py b/.i3/py3status/backup/i3bar_click_events.py
new file mode 100644
index 0000000..792965c
--- /dev/null
+++ b/.i3/py3status/backup/i3bar_click_events.py
@@ -0,0 +1,127 @@
+from subprocess import Popen
+from time import time
+
+
+class Py3status:
+ """
+ This module allows you to take actions based on click events made on
+ the i3status modules. For example, thanks to this module you could
+ launch the wicd GUI when clicking on the ethernet or wireless module
+ of your i3status output !
+
+ IMPORTANT:
+ This module file name is reserved and should NOT be changed if you
+ want py3status to handle your i3status modules click events !
+
+ The behavior described above will only work if this file is named
+ 'i3bar_click_events.py' !
+ """
+ def __init__(self):
+ """
+ This is where you setup your actions based on your i3status config.
+
+ Configuration:
+ --------------
+ self.actions = {
+ "<module name and instance>": {
+ <button number>: [<function to run>, <arg1>, <arg2>],
+ }
+ }
+
+ Variables:
+ ----------
+ <button number> is an integer from 1 to 3:
+ 1 : left click
+ 2 : middle click
+ 3 : right click
+
+ <function to run> is a python function written in this module.
+ The 'external_command' function is provided for convenience if
+ you want to call an external program from this module.
+ You can of course write your own functions and have them executed
+ on a click event at will with possible arguments <arg1>, <arg2>...
+
+ <module name and instance> is a string made from the module
+ attribute 'name' and 'instance' using a space as separator:
+ For i3status modules, it's simply the name of the module as it
+ appears in the 'order' instruction of your i3status.conf.
+ Example:
+ in i3status.conf -> order += "wireless wlan0"
+ self.actions key -> "wireless wlan0"
+
+ Usage example:
+ --------------
+ - Open the wicd-gtk GUI when we LEFT click on the ethernet
+ module of i3status.
+ - Open emelfm2 to /home when we LEFT click on
+ the /home instance of disk_info
+ - Open emelfm2 to / when we LEFT click on
+ the / instance of disk_info
+
+ The related i3status.conf looks like:
+ order += "disk /home"
+ order += "disk /"
+ order += "ethernet eth0"
+
+ The resulting self.actions should be:
+ self.actions = {
+ "ethernet eth0": {
+ 1: [external_command, 'wicd-gtk', '-n'],
+ },
+ "disk_info /home": {
+ 1: [external_command, 'emelfm2', '-1', '~'],
+ },
+ "disk_info /": {
+ 1: [external_command, 'emelfm2', '-1', '/'],
+ },
+ }
+ """
+ # CONFIGURE ME PLEASE, LOVE YOU BIG TIME !
+ self.actions = {
+ }
+
+ def on_click(self, i3status_output_json, i3status_config, event):
+ """
+ If an action is configured for the given i3status module 'name' and
+ 'instance' (if present), then we'll execute the given function with
+ its arguments (if present).
+
+ Usually you SHOULD NOT modify this part of the code.
+ """
+ button = event['button']
+ key_name = '{} {}'.format(
+ event['name'],
+ event.get('instance', '')
+ ).strip()
+ if key_name in self.actions and button in self.actions[key_name]:
+ # get the function to run
+ func = self.actions[key_name][button][0]
+ assert hasattr(func, '__call__'), \
+ 'first element of the action list must be a function'
+
+ # run the function with the possibly given arguments
+ func(*self.actions[key_name][button][1:])
+
+ def i3bar_click_events(self, i3status_output_json, i3status_config):
+ """
+ Cached empty output, this module doesn't show anything.
+ """
+ response = {'full_text': '', 'name': 'i3bar_click_events'}
+ response['cached_until'] = time() + 3600
+ return (-1, response)
+
+
+def external_command(*cmd):
+ """
+ This convenience function lets you call an external program at will.
+
+ NOTE:
+ The stdout and stderr MUST be suppressed as shown here to avoid any
+ output from being caught by the i3bar (this would freeze it).
+ See issue #20 for more info.
+ """
+ Popen(
+ cmd,
+ stdout=open('/dev/null', 'w'),
+ stderr=open('/dev/null', 'w')
+ )
diff --git a/.i3/py3status/backup/netdata.py b/.i3/py3status/backup/netdata.py
new file mode 100644
index 0000000..729983b
--- /dev/null
+++ b/.i3/py3status/backup/netdata.py
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+
+# netdata
+
+# Netdata is a module uses great Py3status (i3status wrapper) to
+# display network information (Linux systems) in i3bar.
+# For more information read:
+# i3wm homepage: http://i3wm.org
+# py3status homepage: https://github.com/ultrabug/py3status
+
+# Copyright (C) <2013> <Shahin Azad [ishahinism at Gmail]>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# ----------------------------------------------------------------- #
+# Notes:
+# 1. netdata will check 'eth0' interface by default. You can
+# change it by changing 'self.net_interface' variable in 'GetData'
+# class.
+# 2. Colors are depended on strict specification in traffic/netspeed methods.
+# You can change them by manipulating conditions.
+
+import subprocess
+from time import time
+
+# Method 'netSpeed' will use this variables to calculate downloaded
+# bytes in last second. Initializing this variables globally is
+# necessary since we can't use __init__ method in Py3Status class.
+old_transmitted, old_received = 0, 0
+
+
+class GetData:
+ """Get system status
+
+ """
+ def __init__(self):
+ # You can change it to another interface.
+ # It'll be used for grabbing net interface data.
+ self.net_interface = 'eth0'
+
+ def execCMD(self, cmd, arg):
+ """Take a system command and its argument, then return the result.
+
+ Arguments:
+ - `cmd`: system command.
+ - `arg`: argument.
+ """
+ result = subprocess.check_output([cmd, arg])
+ return result
+
+ def netBytes(self):
+ """Execute 'cat /proc/net/dev', find the interface line (Default
+ 'eth0') and grab received/transmitted bytes.
+
+ """
+ net_data = self.execCMD('cat', '/proc/net/dev').decode('utf-8').split()
+ interface_index = net_data.index(self.net_interface + ':')
+ received_bytes = int(net_data[interface_index + 1])
+ transmitted_bytes = int(net_data[interface_index + 9])
+
+ return received_bytes, transmitted_bytes
+
+
+class Py3status:
+ """
+ System status in i3bar
+ """
+ def netSpeed(self, json, i3status_config):
+ """Calculate network speed ('eth0' interface) and return it. You can
+ change the interface using 'self.net_interface' variable in
+ 'GetData' class.
+
+ """
+ data = GetData()
+ response = {'full_text': '', 'name': 'net_speed'}
+
+ global old_received
+ global old_transmitted
+
+ received_bytes, transmitted_bytes = data.netBytes()
+ dl_speed = (received_bytes - old_received) / 1024.
+ up_speed = (transmitted_bytes - old_transmitted) / 1024.
+
+ if dl_speed < 30:
+ response['color'] = i3status_config['color_bad']
+ elif dl_speed < 60:
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_good']
+
+ response['full_text'] = "LAN(Kb): {:5.1f}↓ {:5.1f}↑"\
+ .format(dl_speed, up_speed)
+ response['cached_until'] = time()
+
+ old_received, old_transmitted = received_bytes, transmitted_bytes
+ return (0, response)
+
+ def traffic(self, json, i3status_config):
+ """Calculate networks used traffic. Same as 'netSpeed' method you can
+ change the interface.
+
+ """
+ data = GetData()
+ response = {'full_text': '', 'name': 'traffic'}
+
+ received_bytes, transmitted_bytes = data.netBytes()
+ download = received_bytes / 1024 / 1024.
+ upload = transmitted_bytes / 1024 / 1024.
+ total = download + upload
+
+ if total < 400:
+ response['color'] = i3status_config['color_good']
+ elif total < 700:
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_bad']
+
+ response['full_text'] = "T(Mb): {:3.0f}↓ {:3.0f}↑ {:3.0f}↕"\
+ .format(download, upload, total)
+
+ return (1, response)
diff --git a/.i3/py3status/backup/ns_checker.py b/.i3/py3status/backup/ns_checker.py
new file mode 100644
index 0000000..4a332b1
--- /dev/null
+++ b/.i3/py3status/backup/ns_checker.py
@@ -0,0 +1,57 @@
+import dns.resolver
+import socket
+
+
+class Py3status:
+ """
+ This module launch a simple query on each nameservers for the specified domain.
+ Nameservers are dynamically retrieved. The FQDN is the only one mandatory parameter.
+ It's also possible to add additional nameservers by appending them in nameservers list.
+
+ The default resolver can be overwritten with my_resolver.nameservers parameter.
+
+ Written and contributed by @nawadanp
+ """
+ def __init__(self):
+ self.domain = 'google.com'
+ self.lifetime = 0.3
+ self.resolver = []
+ self.nameservers = []
+
+ def ns_checker(self, i3status_output_json, i3status_config):
+ response = {'full_text': '', 'name': 'ns_checker'}
+ position = 0
+ counter = 0
+ error = False
+ nameservers = []
+
+ my_resolver = dns.resolver.Resolver()
+ my_resolver.lifetime = self.lifetime
+ if self.resolver:
+ my_resolver.nameservers = self.resolver
+
+ my_ns = my_resolver.query(self.domain, 'NS')
+
+ # Insert each NS ip address in nameservers
+ for ns in my_ns:
+ nameservers.append(str(socket.gethostbyname(str(ns))))
+ for ns in self.nameservers:
+ nameservers.append(str(ns))
+
+ # Perform a simple DNS query, for each NS servers
+ for ns in nameservers:
+ my_resolver.nameservers = [ns]
+ counter += 1
+ try:
+ my_resolver.query(self.domain, 'A')
+ except:
+ error = True
+
+ if error:
+ response['full_text'] = str(counter) + ' NS NOK'
+ response['color'] = i3status_config['color_bad']
+ else:
+ response['full_text'] = str(counter) + ' NS OK'
+ response['color'] = i3status_config['color_good']
+
+ return (position, response)
diff --git a/.i3/py3status/backup/pingdom.py b/.i3/py3status/backup/pingdom.py
new file mode 100644
index 0000000..cddf1a9
--- /dev/null
+++ b/.i3/py3status/backup/pingdom.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+import requests
+from time import time
+
+
+class Py3status:
+ """
+ Dynamically display the latest response time of the configured checks using
+ the Pingdom API.
+ We also verify the status of the checks and colorize if needed.
+ Pingdom API doc : https://www.pingdom.com/services/api-documentation-rest/
+
+ #NOTE: This module needs the 'requests' python module from pypi
+ https://pypi.python.org/pypi/requests
+ """
+ def pingdom_checks(self, json, i3status_config):
+ response = {'full_text': '', 'name': 'pingdom_checks'}
+
+ #NOTE: configure me !
+ APP_KEY = '' # create an APP KEY on pingdom first
+ CACHE_TIMEOUT = 600 # recheck every 10 mins
+ CHECKS = [] # checks' names you want added to your bar
+ LATENCY_THRESHOLD = 500 # when to colorize the output
+ LOGIN = '' # pingdom login
+ PASSWORD = '' # pingdom password
+ TIMEOUT = 15
+ POSITION = 0
+
+ r = requests.get(
+ 'https://api.pingdom.com/api/2.0/checks',
+ auth=(LOGIN, PASSWORD),
+ headers={'App-Key': APP_KEY},
+ timeout=TIMEOUT,
+ )
+ result = r.json()
+ if 'checks' in result:
+ for check in [
+ ck for ck in result['checks'] if ck['name'] in CHECKS
+ ]:
+ if check['status'] == 'up':
+ response['full_text'] += '{}: {}ms, '.format(
+ check['name'],
+ check['lastresponsetime']
+ )
+ if check['lastresponsetime'] > LATENCY_THRESHOLD:
+ response.update(
+ {'color': i3status_config['color_degraded']}
+ )
+ else:
+ response['full_text'] += '{}: DOWN'.format(
+ check['name'],
+ check['lastresponsetime']
+ )
+ response.update({'color': i3status_config['color_bad']})
+ response['full_text'] = response['full_text'].strip(', ')
+ response['cached_until'] = time() + CACHE_TIMEOUT
+
+ return (POSITION, response)
diff --git a/.i3/py3status/backup/pomodoro.py b/.i3/py3status/backup/pomodoro.py
new file mode 100644
index 0000000..28b5ea1
--- /dev/null
+++ b/.i3/py3status/backup/pomodoro.py
@@ -0,0 +1,123 @@
+"""
+Pomodoro countdown on i3bar originally written by @Fandekasp (Adrien Lemaire)
+"""
+from subprocess import call
+from time import time
+
+MAX_BREAKS = 4
+POSITION = 0
+TIMER_POMODORO = 25 * 60
+TIMER_BREAK = 5 * 60
+TIMER_LONG_BREAK = 15 * 60
+
+
+class Py3status:
+ """
+ """
+ def __init__(self):
+ self.__setup('stop')
+ self.alert = False
+ self.run = False
+
+ def on_click(self, json, i3status_config, event):
+ """
+ Handles click events
+ """
+ if event['button'] == 1:
+ if self.status == 'stop':
+ self.status = 'start'
+ self.run = True
+
+ elif event['button'] == 2:
+ self.__setup('stop')
+ self.run = False
+
+ elif event['button'] == 3:
+ self.__setup('pause')
+ self.run = False
+
+ @property
+ def response(self):
+ """
+ Return the response full_text string
+ """
+ return {
+ 'full_text': '{} ({})'.format(self.prefix, self.timer),
+ 'name': 'pomodoro'
+ }
+
+ def __setup(self, status):
+ """
+ Setup a step
+ """
+ self.status = status
+ if status == 'stop':
+ self.prefix = 'Pomodoro'
+ self.status = 'stop'
+ self.timer = TIMER_POMODORO
+ self.breaks = 1
+
+ elif status == 'start':
+ self.prefix = 'Pomodoro'
+ self.timer = TIMER_POMODORO
+
+ elif status == 'pause':
+ self.prefix = 'Break #%d' % self.breaks
+ if self.breaks > MAX_BREAKS:
+ self.timer = TIMER_LONG_BREAK
+ self.breaks = 1
+ else:
+ self.breaks += 1
+ self.timer = TIMER_BREAK
+
+ def __decrement(self):
+ """
+ Countdown handler
+ """
+ self.timer -= 1
+ if self.timer < 0:
+ self.alert = True
+ self.run = False
+ self.__i3_nagbar()
+ if self.status == 'start':
+ self.__setup('pause')
+ self.status = 'pause'
+ elif self.status == 'pause':
+ self.__setup('start')
+ self.status = 'start'
+
+ def __i3_nagbar(self, level='warning'):
+ """
+ Make use of i3-nagbar to display warnings to the user.
+ """
+ msg = '{} time is up !'.format(self.prefix)
+ try:
+ call(
+ ['i3-nagbar', '-m', msg, '-t', level],
+ stdout=open('/dev/null', 'w'),
+ stderr=open('/dev/null', 'w')
+ )
+ except:
+ pass
+
+ def pomodoro(self, json, i3status_config):
+ """
+ Pomodoro response handling and countdown
+ """
+ if self.run:
+ self.__decrement()
+
+ response = self.response
+ if self.alert:
+ response['urgent'] = True
+ self.alert = False
+
+ if self.status == 'start':
+ response['color'] = i3status_config['color_good']
+ elif self.status == 'pause':
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_bad']
+
+ response['cached_until'] = time()
+ return (POSITION, response)
diff --git a/.i3/py3status/backup/sysdata.py b/.i3/py3status/backup/sysdata.py
new file mode 100644
index 0000000..14aefb3
--- /dev/null
+++ b/.i3/py3status/backup/sysdata.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+
+# sysdata
+
+# Sysdata is a module uses great Py3status (i3status wrapper) to
+# display system information (RAM usage) in i3bar (Linux systems).
+# For more information read:
+# i3wm homepage: http://i3wm.org
+# py3status homepage: https://github.com/ultrabug/py3status
+
+# Copyright (C) <2013> <Shahin Azad [ishahinism at Gmail]>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import subprocess
+from time import time
+
+
+class GetData:
+ """Get system status
+
+ """
+ def execCMD(self, cmd, arg):
+ """Take a system command and its argument, then return the result.
+
+ Arguments:
+ - `cmd`: system command.
+ - `arg`: argument.
+ """
+ result = subprocess.check_output([cmd, arg])
+ return result
+
+ def cpu(self):
+ """Get the cpu usage data from /proc/stat :
+ cpu 2255 34 2290 22625563 6290 127 456 0 0
+ - user: normal processes executing in user mode
+ - nice: niced processes executing in user mode
+ - system: processes executing in kernel mode
+ - idle: twiddling thumbs
+ - iowait: waiting for I/O to complete
+ - irq: servicing interrupts
+ - softirq: servicing softirqs
+ - steal: involuntary wait
+ - guest: running a normal guest
+ - guest_nice: running a niced guest
+ These numbers identify the amount of time the CPU has spent performing
+ different kinds of work. Time units are in USER_HZ (typically hundredths of a
+ second)
+ """
+ with open('/proc/stat', 'r') as fd:
+ line = fd.readline()
+ cpu_data = line.split()
+ total_cpu_time = sum(map(int, cpu_data[1:]))
+ cpu_idle_time = int(cpu_data[4])
+
+ #return the cpu total&idle time
+ return total_cpu_time, cpu_idle_time
+
+ def memory(self):
+ """Execute 'free -m' command, grab the memory capacity and used size
+ then return; Memory size 'total_mem', Used_mem, and percentage
+ of used memory.
+
+ """
+ # Run 'free -m' command and make a list from output.
+ mem_data = self.execCMD('free', '-m').split()
+ total_mem = int(mem_data[7]) / 1024.
+ used_mem = int(mem_data[15]) / 1024.
+ # Caculate percentage
+ used_mem_percent = int(used_mem / (total_mem / 100))
+
+ # Results are in kilobyte.
+ return total_mem, used_mem, used_mem_percent
+
+
+class Py3status:
+ """
+ System status in i3bar
+ """
+ def __init__(self):
+ self.data = GetData()
+ self.cpu_total = 0
+ self.cpu_idle = 0
+
+ def cpuInfo(self, json, i3status_config):
+ """calculate the CPU status and return it.
+
+ """
+ response = {'full_text': '', 'name': 'cpu_usage'}
+ cpu_total, cpu_idle = self.data.cpu()
+ used_cpu_percent = 1 - float(cpu_idle-self.cpu_idle)/float(cpu_total-self.cpu_total)
+ self.cpu_total = cpu_total
+ self.cpu_idle = cpu_idle
+
+ if used_cpu_percent <= 40:
+ response['color'] = i3status_config['color_good']
+ elif used_cpu_percent <= 75:
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_bad']
+
+ response['full_text'] = "CPU: %.2f%%" % (used_cpu_percent*100)
+ #cache the status for 10 seconds
+ response['cached_until'] = time() + 10
+
+ return (0, response)
+
+ def ramInfo(self, json, i3status_config):
+ """calculate the memory (RAM) status and return it.
+
+ """
+ response = {'full_text': '', 'name': 'ram_info'}
+ total_mem, used_mem, used_mem_percent = self.data.memory()
+
+ if used_mem_percent <= 40:
+ response['color'] = i3status_config['color_good']
+ elif used_mem_percent <= 75:
+ response['color'] = i3status_config['color_degraded']
+ else:
+ response['color'] = i3status_config['color_bad']
+
+ response['full_text'] = "RAM: %.2f/%.2f GB (%d%%)" % \
+ (used_mem, total_mem, used_mem_percent)
+ response['cached_until'] = time()
+
+ return (0, response)
diff --git a/.i3/py3status/backup/weather_yahoo.py b/.i3/py3status/backup/weather_yahoo.py
new file mode 100644
index 0000000..6b91b04
--- /dev/null
+++ b/.i3/py3status/backup/weather_yahoo.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+from time import time
+import requests
+
+
+class Py3status:
+ """
+ Display current day + 3 days weather forecast as icons on your i3bar
+ Based on Yahoo! Weather. forecast, thanks guys !
+ See: http://developer.yahoo.com/weather/
+ """
+ def __init__(self):
+ """
+ Basic configuration
+ Find your city code using:
+ http://answers.yahoo.com/question/index?qid=20091216132708AAf7o0g
+ The city_code in this example is for Paris, France
+ """
+ self.cache_timeout = 1800
+ self.city_code = 'FRXX0076'
+ self.request_timeout = 10
+
+ def _get_forecast(self):
+ """
+ Ask Yahoo! Weather. for a forecast
+ """
+ r = requests.get(
+ 'http://query.yahooapis.com/v1/public/yql?q=select item from weather.forecast where location="%s"&format=json' % self.city_code,
+ timeout=self.request_timeout
+ )
+
+ result = r.json()
+ status = r.status_code
+ forecasts = []
+
+ if status == 200:
+ forecasts = result['query']['results']['channel']['item']['forecast']
+ # reset today
+ forecasts[0] = result['query']['results']['channel']['item']['condition']
+ else:
+ raise Exception('got status {}'.format(status))
+
+ # return current today + 3 days forecast
+ return forecasts[:4]
+
+ def _get_icon(self, forecast):
+ """
+ Return an unicode icon based on the forecast code and text
+ See: http://developer.yahoo.com/weather/#codes
+ """
+ icons = ['☀', '☁', '☂', '☃', '?']
+ code = int(forecast['code'])
+ text = forecast['text'].lower()
+
+ # sun
+ if 'sun' in text or code in [31, 32, 33, 34, 36]:
+ code = 0
+
+ # cloud / early rain
+ elif 'cloud' in text or code in [
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 44
+ ]:
+ code = 1
+
+ # rain
+ elif 'rain' in text or code in [
+ 0, 1, 2, 3, 4, 5, 6, 9,
+ 11, 12,
+ 37, 38, 39,
+ 40, 45, 47
+ ]:
+ code = 2
+
+ # snow
+ elif 'snow' in text or code in [
+ 7, 8,
+ 10, 13, 14, 15, 16, 17, 18,
+ 35,
+ 41, 42, 43, 46
+ ]:
+ code = 3
+
+ # dunno
+ else:
+ code = -1
+
+ return icons[code]
+
+ def weather_yahoo(self, json, i3status_config):
+ """
+ This method gets executed by py3status
+ """
+ response = {
+ 'cached_until': time() + self.cache_timeout,
+ 'full_text': '',
+ 'name': 'weather_yahoo'
+ }
+
+ forecasts = self._get_forecast()
+ for forecast in forecasts:
+ icon = self._get_icon(forecast)
+ response['full_text'] += '{} '.format(icon)
+ response['full_text'] = response['full_text'].strip()
+
+ return (0, response)
diff --git a/.i3/py3status/backup/whoami.py b/.i3/py3status/backup/whoami.py
new file mode 100644
index 0000000..f930991
--- /dev/null
+++ b/.i3/py3status/backup/whoami.py
@@ -0,0 +1,26 @@
+from getpass import getuser
+from time import time
+
+
+class Py3status:
+ """
+ Simply output the currently logged in user in i3bar.
+
+ Inspired by i3 FAQ:
+ https://faq.i3wm.org/question/1618/add-user-name-to-status-bar/
+ """
+ def whoami(self, i3status_output_json, i3status_config):
+ """
+ We use the getpass module to get the current user.
+ """
+ # the current user doesnt change so much, cache it good
+ CACHE_TIMEOUT = 600
+
+ # here you can change the format of the output
+ # default is just to show the username
+ username = '{}'.format(getuser())
+
+ # set, cache and return the output
+ response = {'full_text': username, 'name': 'whoami'}
+ response['cached_until'] = time() + CACHE_TIMEOUT
+ return (0, response)
diff --git a/.i3/scripts/i3exit.sh b/.i3/scripts/i3exit.sh
new file mode 100755
index 0000000..3616139
--- /dev/null
+++ b/.i3/scripts/i3exit.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# exit script used in i3 wm
+#
+
+PNG_IMAGE="~/.i3/images/wallpaper.png"
+
+lock() {
+ if [ -f ${PNG_IMAGE} ]; then
+ i3lock -d -ti "${PNG_IMAGE}"
+ else
+ i3lock -d -c 000000
+ fi
+}
+
+case "$1" in
+ lock)
+ lock
+ ;;
+ logout)
+ i3-msg exit
+ ;;
+ suspend)
+ lock
+ dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Suspend
+ ;;
+ hibernate)
+ lock
+ dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate
+ ;;
+ reboot)
+ dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Restart
+ ;;
+ shutdown)
+ dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop
+ ;;
+ *)
+ echo "Usage: $0 {lock|logout|suspend|hibernate|reboot|shutdown}"
+ exit 2
+esac
+
+exit 0
+