diff options
Diffstat (limited to '.i3')
-rw-r--r-- | .i3/config | 362 | ||||
-rw-r--r-- | .i3/images/wallpaper.png | bin | 0 -> 87684 bytes | |||
-rw-r--r-- | .i3/py3status.conf | 78 | ||||
-rw-r--r-- | .i3/py3status/10-mpd.py | 117 | ||||
-rw-r--r-- | .i3/py3status/20-volume.py | 112 | ||||
-rw-r--r-- | .i3/py3status/25-microphone.py | 105 | ||||
-rw-r--r-- | .i3/py3status/30-touchpad.py | 86 | ||||
-rw-r--r-- | .i3/py3status/40-power.py | 73 | ||||
-rw-r--r-- | .i3/py3status/50-battery.py | 106 | ||||
-rw-r--r-- | .i3/py3status/80-datetime.py | 76 | ||||
-rw-r--r-- | .i3/py3status/backup/dpms.py | 44 | ||||
-rw-r--r-- | .i3/py3status/backup/empty_class.py | 41 | ||||
-rw-r--r-- | .i3/py3status/backup/glpi.py | 52 | ||||
-rw-r--r-- | .i3/py3status/backup/i3bar_click_events.py | 127 | ||||
-rw-r--r-- | .i3/py3status/backup/netdata.py | 132 | ||||
-rw-r--r-- | .i3/py3status/backup/ns_checker.py | 57 | ||||
-rw-r--r-- | .i3/py3status/backup/pingdom.py | 59 | ||||
-rw-r--r-- | .i3/py3status/backup/pomodoro.py | 123 | ||||
-rw-r--r-- | .i3/py3status/backup/sysdata.py | 137 | ||||
-rw-r--r-- | .i3/py3status/backup/weather_yahoo.py | 106 | ||||
-rw-r--r-- | .i3/py3status/backup/whoami.py | 26 | ||||
-rwxr-xr-x | .i3/scripts/i3exit.sh | 43 |
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 Binary files differnew file mode 100644 index 0000000..468b1a9 --- /dev/null +++ b/.i3/images/wallpaper.png 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 + |