First payload
5
.Rprofile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# The .First function is called after everything else in .Rprofile is executed
|
||||||
|
#.First <- function() {
|
||||||
|
#message("Welcome back ", Sys.getenv("USER"),"!\n","working directory is:", getwd())
|
||||||
|
#}
|
||||||
|
options(repos=structure(c(CRAN="http://cran.revolutionanalytics.com/")))
|
||||||
57
.Xdefaults
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
*foreground: #00cc00
|
||||||
|
*foreground_bold: #a8a19f
|
||||||
|
*cursor: #a8a19f
|
||||||
|
!!background = #1b1918
|
||||||
|
!!*background: rgba(0, 0, 0, .7)
|
||||||
|
|
||||||
|
!! black
|
||||||
|
*color0: #1b1918
|
||||||
|
*color8: #766e6b
|
||||||
|
!! red
|
||||||
|
*color1: #f22c40
|
||||||
|
*color9: #f22c40
|
||||||
|
!! green
|
||||||
|
*color2: #5ab738
|
||||||
|
*color10: #5ab738
|
||||||
|
!! yellow
|
||||||
|
*color3: #d5911a
|
||||||
|
*color11: #d5911a
|
||||||
|
!! blue
|
||||||
|
*color4: #407ee7
|
||||||
|
*color12: #407ee7
|
||||||
|
!! magenta
|
||||||
|
*color5: #6666ea
|
||||||
|
*color13: #6666ea
|
||||||
|
!! cyan
|
||||||
|
*color6: #00ad9c
|
||||||
|
*color14: #00ad9c
|
||||||
|
!! white
|
||||||
|
*color7: #a8a19f
|
||||||
|
*color15: #f1efee
|
||||||
|
|
||||||
|
URxvt.intensityStyles: false
|
||||||
|
URxvt.background: [70]#000000
|
||||||
|
URxvt.depth: 32
|
||||||
|
URxvt.font: xft:monospace:size=11
|
||||||
|
URxvt.scrollBar: false
|
||||||
|
URxvt.cursorColor: white
|
||||||
|
URxvt.perl-ext-common: default,matcher,resize-font
|
||||||
|
URxvt.perl-lib: $HOME/.config/Scripts
|
||||||
|
URxvt.url-launcher: /usr/bin/xdg-open
|
||||||
|
URxvt.matcher.button: 1
|
||||||
|
URxvt.resize-font.smaller: C-Down
|
||||||
|
URxvt.resize-font.bigger: C-Up
|
||||||
|
|
||||||
|
URxvt.colorUL: #4682B4
|
||||||
|
rofi.color-enabled: true
|
||||||
|
rofi.color-window: #000, #000, #000
|
||||||
|
rofi.color-normal: #111, #819396, #222, #008ed4, #ffffff
|
||||||
|
rofi.color-active: #002b37, #008ed4, #003643, #008ed4, #66c6ff
|
||||||
|
rofi.color-urgent: #002b37, #da4281, #003643, #008ed4, #890661
|
||||||
|
|
||||||
|
rofi.fake-transparency: true
|
||||||
|
rofi.lines: 3
|
||||||
|
rofi.bw: 0
|
||||||
|
rofi.opacity: "10"
|
||||||
|
rofi.hide-scrollbar: true
|
||||||
|
rofi.width: 30
|
||||||
13
.asoudrc
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pcm.softvol {
|
||||||
|
type softvol
|
||||||
|
slave.pcm "cards.pcm.default"
|
||||||
|
control {
|
||||||
|
name "Software"
|
||||||
|
card 0
|
||||||
|
}
|
||||||
|
max_db 20.0
|
||||||
|
}
|
||||||
|
pcm.!default {
|
||||||
|
type plug
|
||||||
|
slave.pcm "softvol"
|
||||||
|
}
|
||||||
14
.bash_profile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#
|
||||||
|
# ~/.bash_profile
|
||||||
|
#
|
||||||
|
|
||||||
|
[[ -f ~/.bashrc ]] && . ~/.bashrc
|
||||||
|
|
||||||
|
#if [ -z "$DISPLAY" ] && [ "$(fgconsole)" -eq 1 ]; then
|
||||||
|
#startx
|
||||||
|
#fi
|
||||||
|
|
||||||
|
#[ -z "$DISPLAY" -a "$(fgconsole)" -eq 1 ] && exec startx
|
||||||
|
|
||||||
|
|
||||||
|
export BROWSER=firefox
|
||||||
26
.config/Scripts/audio.sh
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#This is the ffmpeg command that the audio shortcut in i3 will run.
|
||||||
|
|
||||||
|
#Picks a file name for the output file based on availability:
|
||||||
|
|
||||||
|
if [[ -f ~/output.flac ]]
|
||||||
|
then
|
||||||
|
n=1
|
||||||
|
while [[ -f ~/output_$n.flac ]]
|
||||||
|
do
|
||||||
|
n=$((n+1))
|
||||||
|
done
|
||||||
|
filename="output_$n.flac"
|
||||||
|
else
|
||||||
|
filename="output.flac"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#The actual ffmpeg command:
|
||||||
|
|
||||||
|
ffmpeg \
|
||||||
|
-thread_queue_size 1024 \
|
||||||
|
-f alsa -ar 44100 -i hw:1 \
|
||||||
|
-af "volume=12" \
|
||||||
|
-c:v libx264 -r 30 -c:a flac $filename
|
||||||
|
#-c:v ffvhuff -r 30 -c:a flac $filename
|
||||||
5
.config/Scripts/aurinstall.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
wget https://aur.archlinux.org/cgit/aur.git/snapshot/$1.tar.gz
|
||||||
|
tar -xvzf $1.tar.gz
|
||||||
|
cd $1 && makepkg --no-confirm -si
|
||||||
|
cd .. && rm -rf $1 $1.tar.gz
|
||||||
139
.config/Scripts/bashrc
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
stty -ixon
|
||||||
|
|
||||||
|
export PS1="\[$(tput bold)\]\[$(tput setaf 1)\][\[$(tput setaf 3)\]\u\[$(tput setaf 2)\]@\[$(tput setaf 4)\]\h \[$(tput setaf 5)\]\W\[$(tput setaf 1)\]]\[$(tput setaf 7)\]\\$ \[$(tput sgr0)\]"
|
||||||
|
|
||||||
|
if [[ -f /usr/bin/iceweasel ]]; then
|
||||||
|
export BROWSER="iceweasel"
|
||||||
|
else
|
||||||
|
export BROWSER="firefox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
shopt -s autocd
|
||||||
|
|
||||||
|
#if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then
|
||||||
|
#exec startx
|
||||||
|
#fi
|
||||||
|
|
||||||
|
|
||||||
|
#Basic Aliases
|
||||||
|
alias v="vim"
|
||||||
|
#alias sv="sudo vim"
|
||||||
|
alias r="ranger"
|
||||||
|
alias ls='ls -hN --color=auto --group-directories-first'
|
||||||
|
alias lsa='ls -A'
|
||||||
|
g() { cd $1 && ls -a ;}
|
||||||
|
alias b="cd .. && ls -a"
|
||||||
|
alias ?="man"
|
||||||
|
alias q="exit"
|
||||||
|
alias e="exit"
|
||||||
|
|
||||||
|
alias mutt="mutt -F ~/.config/mutt/muttrc"
|
||||||
|
alias mocp="mocp --config ~/.config/moc/config"
|
||||||
|
alias calcurse="calcurse -D ~/.config/calcurse"
|
||||||
|
alias weechat="weechat -d ~/.config/weechat"
|
||||||
|
alias syncthing="syncthing -home='$HOME/.syncthing'"
|
||||||
|
alias tmux="tmux -f ~/.config/Scripts/tmux.conf"
|
||||||
|
#NEWSBEUTER and W3M
|
||||||
|
|
||||||
|
alias Xi="sudo xbps-install"
|
||||||
|
alias Xu="sudo xbps-remove -R"
|
||||||
|
alias Xup="sudo xbps-install -Suv"
|
||||||
|
alias Xc="xbps-remove -Oo"
|
||||||
|
alias Xq="xbps-query -Rs"
|
||||||
|
alias XI="xbps-query -s"
|
||||||
|
|
||||||
|
#Term only
|
||||||
|
alias mute="pamixer -m"
|
||||||
|
alias vd="pamixer -d 10"
|
||||||
|
alias vu="pamixer -i 10"
|
||||||
|
alias p="mocp -G &> /dev/null"
|
||||||
|
alias next="mocp -f &> /dev/null"
|
||||||
|
alias prev="mocp -r &> /dev/null"
|
||||||
|
alias mnt="sudo bash ~/.config/Scripts/mount.sh"
|
||||||
|
alias umnt="sudo bash ~/.config/Scripts/unmount.sh"
|
||||||
|
alias sdn="sudo shutdown now"
|
||||||
|
|
||||||
|
alias screenfetch="screenfetch -t"
|
||||||
|
alias yt="youtube-dl -ic"
|
||||||
|
alias yta="youtube-dl -xic"
|
||||||
|
|
||||||
|
alias webedit="ssh -l lukesmith -p 2222 lukesmith.xyz"
|
||||||
|
alias web="ssh -l lukesmith -p 2222 lukesmith.xyz"
|
||||||
|
alias desk="ssh -l luke -p 22 10.193.0.46"
|
||||||
|
serversend() { rsync -avr --rsh='ssh -p2222' $1 lukesmith@lukesmith.xyz:/home1/lukesmith/public_html ;}
|
||||||
|
alias ein="ssh -l einchan -p 22 104.238.215.7"
|
||||||
|
alias starwars="telnet towel.blinkenlights.nl"
|
||||||
|
|
||||||
|
alias rcsync="rsync -avr --rsh='ssh -p2222' .bashrc .vimrc .Xdefaults .tmux.conf .muttrc .bash_profile .vim .w3m .moc lukesmith@lukesmith.xyz:/home1/lukesmith/config"
|
||||||
|
|
||||||
|
alias newnet="sudo systemctl restart NetworkManager"
|
||||||
|
alias atltime="sudo timedatectl set-timezone America/New_York && i3 restart"
|
||||||
|
alias tuctime="sudo timedatectl set-timezone America/Phoenix && i3 restart"
|
||||||
|
|
||||||
|
bl() { convert $@ -resize 1440x1080\> bl_$@ ;}
|
||||||
|
|
||||||
|
alias pingme="ping lukesmith.xyz"
|
||||||
|
|
||||||
|
alias youtube="youtube-viewer"
|
||||||
|
alias YT="youtube-viewer"
|
||||||
|
alias syt="youtube-viewer"
|
||||||
|
|
||||||
|
alias etym="sdcv -u \"English Etymology\""
|
||||||
|
|
||||||
|
alias Txa="cp ~/Documents/LaTeX/article.tex"
|
||||||
|
alias Txs="cp ~/Documents/LaTeX/beamer.tex"
|
||||||
|
alias Txh="cp ~/Documents/LaTeX/handout.tex"
|
||||||
|
alias TC='find . -maxdepth 1 -regextype gnu-awk -regex "^.*\.(pyc|pyo|bak|swp|aux|log|nav|out|snm|toc|bcf|run\.xml|synctex\.gz|blg|bbl)" -delete'
|
||||||
|
|
||||||
|
getgit() { git clone http://github.com/$1.git ;}
|
||||||
|
|
||||||
|
folder() { echo -e "$1\t$2" >> ~/.config/Scripts/folders && i3 restart ;}
|
||||||
|
weath() { curl wttr.in/$1 ;}
|
||||||
|
alias work="mkdir ~/Work && cd ~/Work"
|
||||||
|
|
||||||
|
|
||||||
|
longterm() { rsync -avr --rsh='ssh -p2222' $1 lukesmith@lukesmith.xyz:/home1/lukesmith/public_html/longterm ;}
|
||||||
|
sendmine() { rsync -avr --rsh='ssh -p2222' $1 lukesmith@lukesmith.xyz:/home1/lukesmith/public_html/mine ;}
|
||||||
|
|
||||||
|
alias test='~/.config/bumblebee-status/bumblebee-status -m pasink pasource battery nic pacman disk datetime -p disk.path=/home datetime.format="%a, %b %d, %Y at %I:%M %p" -t kulade'
|
||||||
|
|
||||||
|
getlt() { wget http://lukesmith.xyz/longterm/$1 ;}
|
||||||
|
getmine() { wget http://lukesmith.xyz/mine/$1 --user=lukesmith --ask-password ;}
|
||||||
|
|
||||||
|
memefind() { find ~/Pictures/Memes/ -iname "*$1*" ;}
|
||||||
|
CF() { cd ~/.config/$1 && ls ;}
|
||||||
|
|
||||||
|
alias now="vim ~/Documents/Phonology/squib1.tex"
|
||||||
|
|
||||||
|
alias ethspeed="speedometer -r enp0s25"
|
||||||
|
|
||||||
|
note() { echo "$@" >> ~/notes ;}
|
||||||
|
|
||||||
|
alias extract="~/.config/Script/ext.sh"
|
||||||
|
|
||||||
|
alias refresh="python ~/.config/Scripts/shortcuts.py"
|
||||||
|
|
||||||
|
backup() { cp $1 $1.bu ;}
|
||||||
|
|
||||||
|
#alias man="w3mman"
|
||||||
|
|
||||||
|
alias mailsync="bash ~/.config/Scripts/mailsyncloop.sh"
|
||||||
|
|
||||||
|
alias wifispeed="speedometer -r wlp2s0"
|
||||||
|
|
||||||
|
alias trigger="bash ~/Creations/Scripts/trigger.sh"
|
||||||
|
|
||||||
|
alias bbs="python ~/.config/i3/bar/bumblebee-status"
|
||||||
|
|
||||||
|
alias tr="transmission-remote"
|
||||||
|
|
||||||
|
alias servs="ls /etc/sv"
|
||||||
|
|
||||||
|
alias debase="sudo umount /home/Shared/Videos"
|
||||||
|
|
||||||
|
alias makemine="sudo chown -R luke:luke /home/luke/Downloads/*"
|
||||||
|
|
||||||
|
serven() { sudo ln -s /etc/sv/$1 /var/service/ ;}
|
||||||
|
servdis() { sudo rm /var/service/$1 ;}
|
||||||
|
|
||||||
|
aurinstall() { curl -O https://aur.archlinux.org/cgit/aur.git/snapshot/$1.tar.gz && tar -xvzf $1.tar.gz && cd $1 && makepkg --noconfirm -si && cd .. && rm -rf $1 $1.tar.gz ;}
|
||||||
1
.config/Scripts/clear.sh
Executable file
@ -0,0 +1 @@
|
|||||||
|
find . -maxdepth 1 -regextype gnu-awk -regex "^.*\.(pyc|p yo|bak|swp|aux|log|lof|nav|out|snm|toc|bcf|run\.xml|synctex\.gz|blg|bbl)" -delete
|
||||||
24
.config/Scripts/configs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
cfb ~/.config/Scripts/bashrc
|
||||||
|
cfs ~/.config/Scripts/status.sh
|
||||||
|
cfz ~/.zshrc
|
||||||
|
cfv ~/.config/Scripts/vimrc
|
||||||
|
cfr ~/.config/ranger/rc.conf.base
|
||||||
|
cfi ~/.config/i3/config
|
||||||
|
cfq ~/.config/qutebrowser/keys.conf.base
|
||||||
|
cfQ ~/.config/qutebrowser/qutebrowser.conf
|
||||||
|
cfm ~/.config/mutt/muttrc
|
||||||
|
cfM ~/.config/moc/keymap
|
||||||
|
cff ~/.config/Scripts/folders
|
||||||
|
cfc ~/.config/Scripts/configs
|
||||||
|
cft ~/.config/termite/config
|
||||||
|
cfT ~/.config/Scripts/tmux.conf
|
||||||
|
eb ~/Documents/LaTeX/uni.bib
|
||||||
|
cv ~/Documents/LaTeX/cv.tex
|
||||||
|
cfl ~/.config/mutt/lukexyz.info
|
||||||
|
cfx ~/.config/mutt/luxmyth.info
|
||||||
|
cfk ~/.config/mutt/kulade.cock
|
||||||
|
cfo ~/.config/mutt/kulade.info
|
||||||
|
cfa ~/.config/mutt/aliases
|
||||||
|
cfp ~/.config/polybar/config
|
||||||
|
cfd ~/.Xdefaults
|
||||||
|
TO ~/Creations/Videos/todo.md
|
||||||
7
.config/Scripts/drives
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
wd2 1A3FE4E62BC1A399
|
||||||
|
sd 9C33-6BBD
|
||||||
|
king 66faa60c-b24f-46a6-92cd-b064e9dbdc6c
|
||||||
|
sony4 6C67-A7B4
|
||||||
|
black 0ff55b51-5294-4bc2-bbf0-819a804b0503
|
||||||
|
archive 0EC4117AC41164ED
|
||||||
|
blue 8f0d3707-f2a1-4a8f-910a-49d97ba80931
|
||||||
24
.config/Scripts/extract.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
if [ -f $1 ] ; then
|
||||||
|
# NAME=${1%.*}
|
||||||
|
# mkdir $NAME && cd $NAME
|
||||||
|
case $1 in
|
||||||
|
*.tar.bz2) tar xvjf ../$1 ;;
|
||||||
|
*.tar.gz) tar xvzf ../$1 ;;
|
||||||
|
*.tar.xz) tar xvJf ../$1 ;;
|
||||||
|
*.lzma) unlzma ../$1 ;;
|
||||||
|
*.bz2) bunzip2 ../$1 ;;
|
||||||
|
*.rar) unrar x -ad ../$1 ;;
|
||||||
|
*.gz) gunzip ../$1 ;;
|
||||||
|
*.tar) tar xvf ../$1 ;;
|
||||||
|
*.tbz2) tar xvjf ../$1 ;;
|
||||||
|
*.tgz) tar xvzf ../$1 ;;
|
||||||
|
*.zip) unzip ../$1 ;;
|
||||||
|
*.Z) uncompress ../$1 ;;
|
||||||
|
*.7z) 7z x ../$1 ;;
|
||||||
|
*.xz) unxz ../$1 ;;
|
||||||
|
*.exe) cabextract ../$1 ;;
|
||||||
|
*) echo "extract: '$1' - unknown archive method" ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "$1 - file does not exist"
|
||||||
|
fi
|
||||||
13
.config/Scripts/flash_win.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#Flashes the active window.
|
||||||
|
|
||||||
|
#Requires transset-df and a composite manager, like xcompmgr.
|
||||||
|
|
||||||
|
transset -a -m 0
|
||||||
|
sleep .1
|
||||||
|
transset -a -x 1
|
||||||
|
sleep .1
|
||||||
|
transset -a -m 0
|
||||||
|
sleep .1
|
||||||
|
transset -a -x 1
|
||||||
10
.config/Scripts/folders
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
h ~
|
||||||
|
d ~/Documents
|
||||||
|
D ~/Downloads
|
||||||
|
p ~/Pictures
|
||||||
|
v ~/Videos
|
||||||
|
m ~/Music
|
||||||
|
b ~/Books
|
||||||
|
s ~/.config/Scripts
|
||||||
|
/ /
|
||||||
|
r /
|
||||||
8
.config/Scripts/imapsync.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -f $(pgrep offlineimap) ]; then
|
||||||
|
offlineimap -o
|
||||||
|
echo "Sync begun."
|
||||||
|
else
|
||||||
|
echo "Sync in progress."
|
||||||
|
fi
|
||||||
154
.config/Scripts/luke_guide.md
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# A friendly guide to Luke's i3 rice
|
||||||
|
|
||||||
|
|
||||||
|
Use vim keys (h/j/k/l) to navigate this document. Pressing W will fit it to window width. + and - zoom in and out. q to quit. (These are general mupdf shortcuts.)
|
||||||
|
|
||||||
|
+ Mod+u will show this document at any time.
|
||||||
|
|
||||||
|
General questions? Leave a comment on YouTube or email me at luke@lukesmith.xyz.
|
||||||
|
|
||||||
|
## Basic goals and principles of my rice:
|
||||||
|
|
||||||
|
+ Naturalness - I want the number of keypresses I have to make to get what I want as little as possible.
|
||||||
|
+ Keyboard/vim-centrality - All my terminal apps (and other programs) use vim keys when possible. My hands never need leave the home row or thereabout.
|
||||||
|
+ Lots of color -- Many rices stick to one general color palatte. I like my system to be very vibrant.
|
||||||
|
|
||||||
|
## General changes
|
||||||
|
|
||||||
|
+ Capslock is now an alternative escape. Makes vim-craft much more efficient.
|
||||||
|
+ The menu button (usually between the right Alt and Ctrl) is an alternative Super/Mod button. This is to make one-handing on my laptops easier.
|
||||||
|
|
||||||
|
# Shortcut keys
|
||||||
|
|
||||||
|
## Window basics
|
||||||
|
|
||||||
|
Notice the case sensitivity of the shortcuts.
|
||||||
|
|
||||||
|
Be sure you play around with these. Be flexible with the basic commands and the rice will grow on you quick.
|
||||||
|
|
||||||
|
+ Mod+Enter -- Spawn terminal
|
||||||
|
+ Mod+q or Q -- Close window
|
||||||
|
+ Mod+d -- rofi (For running commands or programs without shortcuts)
|
||||||
|
+ Mod+t -- Toggle between spawning vertically and horizontally
|
||||||
|
+ Mod+f or F11 -- Fullscreen
|
||||||
|
+ Mod+h/j/k/l -- Move to different windows
|
||||||
|
+ Mod+H/J/K/L -- Move a window around
|
||||||
|
+ Mod+Y/U/I/O -- Resize windows
|
||||||
|
+ Mod+/ -- Spawn vertical terminal
|
||||||
|
+ Mod+' -- Spawn horizonal terminal
|
||||||
|
+ Mod+s/S -- Increase/decrease inner gaps
|
||||||
|
+ Mod+z/Z -- Increase/decrease outer gaps
|
||||||
|
+ Mod+D -- Reduce gaps to 0
|
||||||
|
+ Mod+T -- Restore gaps to default (15)
|
||||||
|
+ Mod+Shift+Space -- Make a window float (you can still resize and move floating windows with the same keys above)
|
||||||
|
+ Mod+Space -- Switch from a floating window to a non-floating one (or vice versa)
|
||||||
|
|
||||||
|
## Basic Programs
|
||||||
|
|
||||||
|
+ Mod+r -- ranger (file browser/manager)
|
||||||
|
+ Mod+e -- mutt (email)
|
||||||
|
+ Mod+m -- Music on Console Player
|
||||||
|
+ Mod+a -- qalc (calculator)
|
||||||
|
+ Mod+i -- htop (system info)
|
||||||
|
+ Mod+N -- newsbeuter (RSS feed reader)
|
||||||
|
+ Mod+y -- calcurse (calendar and schedule)
|
||||||
|
+ Mod+Shift+Enter -- tmux
|
||||||
|
+ Mod+w -- qutebrowser (web browser)
|
||||||
|
|
||||||
|
## Larger programs
|
||||||
|
|
||||||
|
+ Mod+W -- Firefox
|
||||||
|
+ Mod+E -- Thunderbird (Not installed by default)
|
||||||
|
+ Mod+B -- Blender
|
||||||
|
+ Mod+G -- GIMP
|
||||||
|
+ Mod+P -- Pinta
|
||||||
|
+ Mod+A -- Audacity
|
||||||
|
|
||||||
|
## System
|
||||||
|
|
||||||
|
+ Mod+R -- Restart/refresh i3 (renews configs, does not close any programs)
|
||||||
|
+ Mod+x -- i3lock (Enter password to return)
|
||||||
|
+ Mod+X -- shutdown now (Be careful with this one!)
|
||||||
|
+ Mod+Shift+Backspace -- reboot (And this one!)
|
||||||
|
+ Mod+Shift+Escape -- exit i3 (And this one as well!)
|
||||||
|
+ Mod+F3 -- arandr (For adding screens/HDMI/VGA connections)
|
||||||
|
+ Mod+F4 -- Hibernate
|
||||||
|
+ Mod+F5 -- Reset Network Manager
|
||||||
|
+ Mod+F7 -- Increase window transparency
|
||||||
|
+ Mod+F8 -- Decrease window transparency
|
||||||
|
|
||||||
|
## Audio
|
||||||
|
|
||||||
|
I use moc/mocp as a music player. If you prefer cmus, I have commented out shortcuts you can activate for it instead in the i3 config.
|
||||||
|
|
||||||
|
+ Mod+m -- Music on Console Player
|
||||||
|
+ Mod+n -- Next track
|
||||||
|
+ Mod+b -- Previous track
|
||||||
|
+ Mod+o -- Restart track
|
||||||
|
+ Mod+p -- Pause
|
||||||
|
+ Mod+M -- Mute all audio
|
||||||
|
+ Mod+v -- cli-visualizer
|
||||||
|
+ Mod+V -- projectM visualizer
|
||||||
|
+ Mod+- -- Decrease volume (holding shift increases amount)
|
||||||
|
+ Mod++ -- Increase volume (holding shift increases amount)
|
||||||
|
+ Mod+[ -- Back 10 seconds (holding shift increases amount)
|
||||||
|
+ Mod+] -- Forward 10 seconds (holding shift increases amount)
|
||||||
|
|
||||||
|
## Workspaces
|
||||||
|
|
||||||
|
There are ten workspaces. They work just like those in vanilla i3 with some additions.
|
||||||
|
|
||||||
|
+ Mod+(Number) -- Go to that number workspace
|
||||||
|
+ Mod+Shift+(Number) -- Send window to that workspace
|
||||||
|
+ Mod+Tab -- Go to previous workspace
|
||||||
|
+ Mod+g or escape -- Go to left workspace
|
||||||
|
+ Mod+; -- Go to right workspace
|
||||||
|
|
||||||
|
## Recording
|
||||||
|
|
||||||
|
+ Pause -- Begin screencast. Output goes into ~. Will overwrite any previous output.
|
||||||
|
+ ScrollLock -- Begin audio recording. Same traits as above
|
||||||
|
+ Mod+either of the above keys -- kills ffmpeg, thus ending recordings
|
||||||
|
+ ThinkVantage button (on Thinkpads) -- kills ffmpeg, thus ending recordings
|
||||||
|
+ Print Screen -- Take a scrot screenshot
|
||||||
|
+ Shift+Print Screen -- Take a scrot screenshot of only selected window
|
||||||
|
|
||||||
|
## Other buttons
|
||||||
|
|
||||||
|
I've mapped those extra buttons that some keyboards have (play and pause buttons, email, webbrowsing buttons, etc.) to what you would expect.
|
||||||
|
|
||||||
|
# Special traits of my rice
|
||||||
|
|
||||||
|
## Easy config access
|
||||||
|
|
||||||
|
Open a terminal and type "cfc." This will open a file where you will see customizable pairs of key shortcuts and config files. Enter any of these shortcuts in bash or ranger to immediately open the file in vim.
|
||||||
|
|
||||||
|
You may add new entries here and they will be refreshed when you refresh i3 (Mod+R).
|
||||||
|
|
||||||
|
## Folder and config shortcuts
|
||||||
|
|
||||||
|
Open a terminal and type "cff." This opens a file when you can keep and create folder shortcuts. There are only a few here now, because I don't know what your folder structure is going to look like, but on my machine, I have 81 and growing.
|
||||||
|
|
||||||
|
Each line has a shortcut key/keys and its target. These can be used in serveral applications. In bash, simply press "d," the shortcut for ~/Documents and you will cd there (and automatically ls -a).
|
||||||
|
|
||||||
|
ranger works similarly. When in ranger, just press "g" then the shortcut of the folder you want to go to. You may also press "t" plus the shortcut to open a new tab there. "m" plus the shortcut moves the selected files to the folder and "Y" copies them there. **Get good at this. It will make management of even the most complex file system easy.**
|
||||||
|
|
||||||
|
Lastly qutebrowser implements these shortcuts as well. When you see a file or image you want to download, press ";" followed by the folder shortcut and qutebrowser will let you select the file with its hint system. The file will then download to the directory you chose.
|
||||||
|
|
||||||
|
## Dynamically constructed configs
|
||||||
|
|
||||||
|
To keep these different shortcuts in sync, my rice will dynamically reconstruct the configs to bash, qutebrowser and ranger each time you refresh i3 (Mod+R).
|
||||||
|
|
||||||
|
Each time i3 starts or restarts, it will run ~/.config/Scripts/shortcuts.py, which reads the entries in the folder shortcut and config shortcut files and then translate them into the approriate syntax of all three programs.
|
||||||
|
|
||||||
|
It then takes that output and appends it to base configs of each program (~/.config/Scripts/bashrc, ~/config/qutebrowser/keys.conf.base, ~/.config/rc.conf.base) and puts the output in the proper places for each program.
|
||||||
|
|
||||||
|
## So what do I need to know?
|
||||||
|
|
||||||
|
Use the files in "cff" and "cfc" to add/change shortcuts. These shortcuts will be synced between bash, ranger and qutebrowser. Press Mod+R to refresh them. If you want to make permanent changes to your bash/ranger/qutebrowser configs, make them to the base files which you can access with "cfb," "cfr," and "cfq," respectively, then press Mod+R.
|
||||||
|
|
||||||
|
# Explore and customize
|
||||||
|
|
||||||
|
Don't like something about the rice? Change it. If you have a problem, try figuring it out yourself, but if you can't, ask on my YouTube or elsewhere.
|
||||||
|
|
||||||
|
Considering how formidable my rice might seem to greener Linux users, I hope between my vids and my documentation, you can tweak exactly what you want from it.
|
||||||
BIN
.config/Scripts/luke_guide.pdf
Normal file
12
.config/Scripts/mailsyncloop.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
offlineimap -o
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
if [ -f $(pgrep offlineimap) ]; then
|
||||||
|
offlineimap -o
|
||||||
|
echo "OfflineIMAP sync complete."
|
||||||
|
else
|
||||||
|
echo "OfflineIMAP already running."
|
||||||
|
fi
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
16
.config/Scripts/mount.sh
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for d in /dev/sd*
|
||||||
|
do
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r col1 col2
|
||||||
|
do
|
||||||
|
if [[ $(blkid -o value -s UUID $d) == ${col2} ]]
|
||||||
|
then
|
||||||
|
sudo mkdir /mnt/${col1}
|
||||||
|
sudo mount $d /mnt/${col1}
|
||||||
|
fi
|
||||||
|
done < /home/kulade/.config/Scripts/drives
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
1
.config/Scripts/remaps
Normal file
@ -0,0 +1 @@
|
|||||||
|
keycode 135 = Super_R
|
||||||
169
.config/Scripts/resize-font
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
# vim:ft=perl:fenc=utf-8
|
||||||
|
# Copyright (c) 2009-, Simon Lundström <simmel@soy.se>
|
||||||
|
# Copyright (c) 2014 Maarten de Vries <maarten@de-vri.es>
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
|
# copyright notice and this permission notice appear in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# Set your font in ~/.Xresources:
|
||||||
|
# urxvt.font: xft:Inconsolata:pixelsize=12
|
||||||
|
# to set it with pixels or
|
||||||
|
# urxvt.font: xft:Inconsolata:size=12
|
||||||
|
# to set it with points.
|
||||||
|
|
||||||
|
# And re-bind some keymappings (if you want, below are the defaults):
|
||||||
|
# URxvt.keysym.C-minus: resize-font:smaller
|
||||||
|
# URxvt.keysym.C-plus: resize-font:bigger
|
||||||
|
# URxvt.keysym.C-equal: resize-font:reset
|
||||||
|
# URxvt.keysym.C-question: resize-font:show
|
||||||
|
#
|
||||||
|
|
||||||
|
my @fonts = (
|
||||||
|
{'name' => 'font', 'code' => 710},
|
||||||
|
{'name' => 'boldFont', 'code' => 711},
|
||||||
|
{'name' => 'italicFont', 'code' => 712},
|
||||||
|
{'name' => 'boldItalicFont', 'code' => 713},
|
||||||
|
);
|
||||||
|
|
||||||
|
my @fixed = qw(4x6 5x7 5x8 6x9 6x10 6x12 6x13 7x13 7x14 8x13 8x16 9x15 9x18 10x20 12x24);
|
||||||
|
|
||||||
|
sub on_start {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
foreach (@fonts) {
|
||||||
|
$_->{'default'} = $self->resource($_->{'name'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub on_init {
|
||||||
|
my ($self) = @_;
|
||||||
|
my $commands = {
|
||||||
|
"smaller" => "C-minus",
|
||||||
|
"bigger" => "C-plus",
|
||||||
|
"reset" => "C-equal",
|
||||||
|
"show" => "C-question",
|
||||||
|
};
|
||||||
|
bind_hotkeys($self, $commands);
|
||||||
|
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
sub bind_hotkeys {
|
||||||
|
my ($self, $commands) = @_;
|
||||||
|
|
||||||
|
for (keys %$commands) {
|
||||||
|
my $hotkey = $$commands{$_};
|
||||||
|
my $hotkey_bound = $self->{'term'}->x_resource("keysym.$hotkey");
|
||||||
|
if (!defined($hotkey_bound) ) {
|
||||||
|
# Support old-style key bindings
|
||||||
|
if ($self->x_resource("%.$_")) {
|
||||||
|
$hotkey = $self->x_resource("%.$_");
|
||||||
|
}
|
||||||
|
|
||||||
|
# FIXME If we're bound to a keysym, don't bind the default.
|
||||||
|
$self->bind_action($hotkey, "%:$_") or
|
||||||
|
warn "unable to register '$hotkey' as hotkey for $_";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($hotkey_bound !~ /^resize-font:/) {
|
||||||
|
warn "Hotkey $$commands{$_} already bound to $hotkey_bound, not binding to resize-font:$_ by default.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub on_action {
|
||||||
|
my ($self, $string) = @_;
|
||||||
|
my $regex = qr"(?!pixelsize=)(\d+)";
|
||||||
|
|
||||||
|
if ($string eq "bigger") {
|
||||||
|
foreach (@fonts) {
|
||||||
|
next if not defined($_->{'default'});
|
||||||
|
update_font_size($self, $_, +2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($string eq "smaller") {
|
||||||
|
foreach (@fonts) {
|
||||||
|
next if not defined($_->{'default'});
|
||||||
|
update_font_size($self, $_, -2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($string eq "reset") {
|
||||||
|
foreach (@fonts) {
|
||||||
|
next if not defined($_->{'default'});
|
||||||
|
set_font($self, $_, $_->{'default'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($string eq "show") {
|
||||||
|
|
||||||
|
my $term = $self->{'term'};
|
||||||
|
$term->{'resize-font'}{'overlay'} = {
|
||||||
|
ov => $term->overlay_simple(0, -1, format_font_info($self)),
|
||||||
|
to => urxvt::timer
|
||||||
|
->new
|
||||||
|
->start(urxvt::NOW + 1)
|
||||||
|
->cb(sub {
|
||||||
|
delete $term->{'resize-font'}{'overlay'};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_font {
|
||||||
|
my ($self, $name) = @_;
|
||||||
|
return $self->resource($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_font {
|
||||||
|
my ($self, $font, $new) = @_;
|
||||||
|
$self->cmd_parse(sprintf("\33]%d;%s\007", $font->{'code'}, $new));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub update_font_size {
|
||||||
|
my ($self, $font, $delta) = @_;
|
||||||
|
my $regex = qr"(?<=size=)(\d+)";
|
||||||
|
my $current = get_font($self, $font->{'name'});
|
||||||
|
|
||||||
|
my ($index) = grep { $fixed[$_] eq $current } 0..$#fixed;
|
||||||
|
if ($index or $index eq 0) {
|
||||||
|
my $inc = $delta / abs($delta);
|
||||||
|
$index += $inc;
|
||||||
|
if ($index < 0) { $index = 0; }
|
||||||
|
if ($index > $#fixed) { $index = $#fixed; }
|
||||||
|
$current = $fixed[$index];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$current =~ s/$regex/$1+$delta/ge;
|
||||||
|
}
|
||||||
|
set_font($self, $font, $current);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub format_font_info {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $width = 0;
|
||||||
|
foreach (@fonts) {
|
||||||
|
my $length = length($_->{'name'});
|
||||||
|
$width = $length > $width ? $length : $width;
|
||||||
|
}
|
||||||
|
++$width;
|
||||||
|
|
||||||
|
my $info = '';
|
||||||
|
foreach (@fonts) {
|
||||||
|
$info .= sprintf("%-${width}s %s\n", $_->{'name'} . ':', get_font($self, $_->{'name'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
29
.config/Scripts/screencast.sh
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#This is the ffmpeg command that the screencast shortcut in i3 will run.
|
||||||
|
|
||||||
|
#Picks a file name for the output file based on availability:
|
||||||
|
|
||||||
|
if [[ -f ~/output.mkv ]]
|
||||||
|
then
|
||||||
|
n=1
|
||||||
|
while [[ -f $HOME/output_$n.mkv ]]
|
||||||
|
do
|
||||||
|
n=$((n+1))
|
||||||
|
done
|
||||||
|
filename="$HOME/output_$n.mkv"
|
||||||
|
else
|
||||||
|
filename="$HOME/output.mkv"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#The actual ffmpeg command:
|
||||||
|
|
||||||
|
ffmpeg -y \
|
||||||
|
-f x11grab \
|
||||||
|
-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \
|
||||||
|
-i :0.0 \
|
||||||
|
-thread_queue_size 1024 \
|
||||||
|
-f alsa -ar 44100 -i hw:1 \
|
||||||
|
-af "volume=12" \
|
||||||
|
-c:v libx264 -r 30 -c:a flac $filename
|
||||||
|
#-c:v ffvhuff -r 30 -c:a flac $filename
|
||||||
41
.config/Scripts/shortcuts.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import csv
|
||||||
|
|
||||||
|
qute = ""
|
||||||
|
rang = ""
|
||||||
|
bash = ""
|
||||||
|
|
||||||
|
with open(".config/qutebrowser/keys.conf.base") as qb:
|
||||||
|
qute+=qb.read()
|
||||||
|
with open(".config/ranger/rc.conf.base") as rg:
|
||||||
|
rang+=rg.read()
|
||||||
|
with open(".config/Scripts/bashrc") as bsh:
|
||||||
|
bash+=bsh.read()
|
||||||
|
|
||||||
|
#First we open the list of folder shortcuts and go down each line adding each in the required syntax to each of the three configs:
|
||||||
|
|
||||||
|
with open(".config/Scripts/folders") as fold:
|
||||||
|
for line in csv.reader(fold, dialect="excel-tab"):
|
||||||
|
#Adds the qutebrowser downloads commands:
|
||||||
|
qute+="set storage download-directory "+line[1]+" ;; hint links download\n\t;"+line[0]+"\n"
|
||||||
|
#Adds the ranger go, tab, move and yank commands:
|
||||||
|
rang+=("map g"+line[0]+" cd "+line[1]+"\n")
|
||||||
|
rang+=("map t"+line[0]+" tab_new "+line[1]+"\n")
|
||||||
|
rang+=("map m"+line[0]+" shell mv %s "+line[1]+"\n")
|
||||||
|
rang+=("map Y"+line[0]+" shell cp -r %s "+line[1]+"\n")
|
||||||
|
#Adds the bash shortcuts:
|
||||||
|
bash+=("alias "+line[0]+"=\"cd "+line[1]+" && ls -a\"\n")
|
||||||
|
|
||||||
|
#Goes thru the config file file and adds the shortcuts to both bash and ranger.
|
||||||
|
|
||||||
|
with open(".config/Scripts/configs") as conf:
|
||||||
|
for line in csv.reader(conf, dialect="excel-tab"):
|
||||||
|
bash+=("alias "+line[0]+"=\"vim "+line[1]+"\"\n")
|
||||||
|
rang+=("map "+line[0]+" shell vim "+line[1]+"\n")
|
||||||
|
|
||||||
|
|
||||||
|
with open(".config/ranger/rc.conf", "w") as outrang:
|
||||||
|
outrang.write(rang)
|
||||||
|
with open(".config/qutebrowser/keys.conf","w") as outqb:
|
||||||
|
outqb.write(qute)
|
||||||
|
with open(".bashrc","w") as outbash:
|
||||||
|
outbash.write(bash)
|
||||||
13
.config/Scripts/shrinkvid.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
sex=$(ffprobe -i $1 -show_entries format=duration -v quiet -of csv="p=0")
|
||||||
|
rate=$(qalc -t 1000000000 / $sex)
|
||||||
|
#rate=$(( 1000000000 / $sex ))
|
||||||
|
|
||||||
|
base=$(basename $1)
|
||||||
|
ext="${base##*.}"
|
||||||
|
base="${base%.*}"
|
||||||
|
|
||||||
|
ffmpeg -i $1 -b $rate $base'_min.'$ext
|
||||||
|
echo "sex is $sex"
|
||||||
|
echo "rate is $rate"
|
||||||
7
.config/Scripts/speedvid.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
base=$(basename $1)
|
||||||
|
ext="${base##*.}"
|
||||||
|
base="${base%.*}"
|
||||||
|
|
||||||
|
ffmpeg -i $1 -vf "setpts=$2*PTS" -an $base'_sped.'$ext
|
||||||
11
.config/Scripts/status.sh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
tmux -f ~/.config/Scripts/tmux.conf new-session -s "status" -d
|
||||||
|
tmux split-window -v "htop"
|
||||||
|
tmux split-window -h "speedometer -r wlp2s0"
|
||||||
|
tmux split-window -v "speedometer -r enp0s25"
|
||||||
|
tmux select-pane -t 0
|
||||||
|
tmux split-window -h "bash ~/.config/Scripts/mailsyncloop.sh"
|
||||||
|
tmux select-pane -t 0
|
||||||
|
tmux resize-pane -R 30
|
||||||
|
tmux -2 attach-session -d
|
||||||
11
.config/Scripts/test.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ffmpeg \
|
||||||
|
-f pulse -ac 2 -ar 48000 -i alsa_output.pci-0000_00_1b.0.analog-stereo.monitor \
|
||||||
|
-f pulse -ac 1 -ar 44100 -i alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo \
|
||||||
|
-filter_complex amix=inputs=2 \
|
||||||
|
-f x11grab -r 30 -s 1280x800 -i :0.0+0,0 \
|
||||||
|
-vcodec libx264 -preset fast -crf 18 \
|
||||||
|
-acodec libmp3lame -ar 44100 -q:a 1 \
|
||||||
|
-pix_fmt yuv420p \
|
||||||
|
this_output.mkv
|
||||||
177
.config/Scripts/tmux.conf
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
##############################
|
||||||
|
# _
|
||||||
|
# | |_ _ __ ___ _ ___ __
|
||||||
|
# | __| '_ ` _ \| | | \ \/ /
|
||||||
|
# | |_| | | | | | |_| |> <
|
||||||
|
# \__|_| |_| |_|\__,_/_/\_\
|
||||||
|
#
|
||||||
|
#############################
|
||||||
|
#
|
||||||
|
# COPY AND PASTE
|
||||||
|
# http://robots.thoughtbot.com/tmux-copy-paste-on-os-x-a-better-future
|
||||||
|
#
|
||||||
|
# Use vim keybindings in copy mode
|
||||||
|
setw -g mode-keys vi
|
||||||
|
|
||||||
|
# Setup 'v' to begin selection as in Vim
|
||||||
|
#bind-key -t vi-copy v begin-selection
|
||||||
|
#bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
|
||||||
|
|
||||||
|
# Update default binding of `Enter` to also use copy-pipe
|
||||||
|
# unbind -t vi-copy Enter
|
||||||
|
# bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
############################################################################
|
||||||
|
# Reset Prefix
|
||||||
|
############################################################################
|
||||||
|
set -g prefix C-a
|
||||||
|
bind-key a send-prefix # for nested tmux sessions
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Global options
|
||||||
|
############################################################################
|
||||||
|
# large history
|
||||||
|
set-option -g history-limit 10000
|
||||||
|
|
||||||
|
# colors
|
||||||
|
setw -g mode-bg black
|
||||||
|
set-option -g default-terminal "screen-256color" #"xterm-256color" # "screen-256color"
|
||||||
|
set-option -g pane-active-border-fg green
|
||||||
|
|
||||||
|
# utf8 support
|
||||||
|
#set-window-option -g utf8 on
|
||||||
|
|
||||||
|
|
||||||
|
# basic settings
|
||||||
|
set-window-option -g xterm-keys on # for vim
|
||||||
|
set-window-option -g mode-keys vi # vi key
|
||||||
|
set-window-option -g monitor-activity on
|
||||||
|
set-window-option -g window-status-current-fg white
|
||||||
|
setw -g window-status-current-attr reverse
|
||||||
|
|
||||||
|
# Automatically set window title
|
||||||
|
setw -g automatic-rename
|
||||||
|
|
||||||
|
# use mouse # More on mouse support http://floriancrouzat.net/2010/07/run-tmux-with-mouse-support-in-mac-os-x-terminal-app/
|
||||||
|
#setw -g mode-mouse on
|
||||||
|
#setw -g mouse-resize-pane on
|
||||||
|
#set -g mouse-select-window on
|
||||||
|
#set -g mouse-select-pane on
|
||||||
|
set -g mouse on
|
||||||
|
set -g history-limit 30000
|
||||||
|
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
|
||||||
|
|
||||||
|
# vi movement keys
|
||||||
|
# set-option -g status-keys vi
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Status Bar
|
||||||
|
############################################################################
|
||||||
|
#set-option -g status-utf8 on
|
||||||
|
set-option -g status-justify right
|
||||||
|
set-option -g status-bg black # colour213 # pink
|
||||||
|
set-option -g status-fg cyan
|
||||||
|
set-option -g status-interval 5
|
||||||
|
set-option -g status-left-length 30
|
||||||
|
set-option -g status-left '#[fg=magenta]» #[fg=blue,bold]#T#[default]'
|
||||||
|
set-option -g status-right '#[fg=red,bold][[ #(git branch) branch ]] #[fg=cyan]»» #[fg=blue,bold]###S #[fg=magenta]%R %m-%d#(acpi | cut -d ',' -f 2)#[default]'
|
||||||
|
set-option -g visual-activity on
|
||||||
|
|
||||||
|
# Titles (window number, program name, active (or not)
|
||||||
|
set-option -g set-titles on
|
||||||
|
set-option -g set-titles-string '#H:#S.#I.#P #W #T'
|
||||||
|
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Unbindings
|
||||||
|
############################################################################
|
||||||
|
#unbind [ # copy mode bound to escape key
|
||||||
|
unbind j
|
||||||
|
unbind C-b # unbind default leader key
|
||||||
|
unbind '"' # unbind horizontal split
|
||||||
|
unbind % # unbind vertical split
|
||||||
|
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Bindings
|
||||||
|
############################################################################
|
||||||
|
# reload tmux conf
|
||||||
|
bind-key r source-file ~/.tmux.conf
|
||||||
|
|
||||||
|
#bind Escape copy-mode
|
||||||
|
|
||||||
|
# new split in current pane (horizontal / vertical)
|
||||||
|
bind-key c split-window -v # split pane horizontally
|
||||||
|
bind-key v split-window -h # split pane vertically
|
||||||
|
|
||||||
|
# list panes
|
||||||
|
bind-key Space list-panes
|
||||||
|
|
||||||
|
# break-pane
|
||||||
|
bind-key Enter break-pane
|
||||||
|
|
||||||
|
# join-pane [-dhv] [-l size | -p percentage] [-s src-pane]
|
||||||
|
# [-t:dst-window.dst-pane] (destination window (dot) destination pane
|
||||||
|
# (alias: joinp)
|
||||||
|
#
|
||||||
|
#bind C-j command-prompt "joinp"
|
||||||
|
#bind C-j command-prompt "join-pane"
|
||||||
|
#bind-key j command-prompt "join-pane -s '%%'"
|
||||||
|
#bind-key j command-prompt "joinp -t:0"
|
||||||
|
bind-key Space command-prompt "joinp -t:%%" # %% = prompt for window.pane [-V|H] # vert|hor split
|
||||||
|
|
||||||
|
#previous pane
|
||||||
|
bind-key -n C-up prev
|
||||||
|
bind-key -n C-left prev
|
||||||
|
|
||||||
|
#next pane
|
||||||
|
bind-key -n C-right next
|
||||||
|
bind-key -n C-down next
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# windows
|
||||||
|
############################################################################
|
||||||
|
set-window-option -g window-status-current-bg red
|
||||||
|
bind C-j previous-window
|
||||||
|
bind C-k next-window
|
||||||
|
bind-key C-a last-window # C-a C-a for last active window
|
||||||
|
bind A command-prompt "rename-window %%"
|
||||||
|
# By default, all windows in a session are constrained to the size of the
|
||||||
|
# smallest client connected to that session,
|
||||||
|
# even if both clients are looking at different windows.
|
||||||
|
# It seems that in this particular case, Screen has the better default
|
||||||
|
# where a window is only constrained in size if a smaller client
|
||||||
|
# is actively looking at it.
|
||||||
|
setw -g aggressive-resize on
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# panes
|
||||||
|
############################################################################
|
||||||
|
# Navigation ---------------------------------------------------------------
|
||||||
|
# use the vim motion keys to move between panes
|
||||||
|
bind-key h select-pane -L
|
||||||
|
bind-key j select-pane -D
|
||||||
|
bind-key k select-pane -U
|
||||||
|
bind-key l select-pane -R
|
||||||
|
|
||||||
|
# Resizing ---------------------------------------------------------------
|
||||||
|
bind-key C-h resize-pane -L
|
||||||
|
bind-key C-j resize-pane -D
|
||||||
|
bind-key C-k resize-pane -U
|
||||||
|
bind-key C-l resize-pane -R
|
||||||
|
|
||||||
|
# use vim motion keys while in copy mode
|
||||||
|
setw -g mode-keys vi
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# layouts
|
||||||
|
############################################################################
|
||||||
|
bind o select-layout "active-only"
|
||||||
|
bind M-- select-layout "even-vertical"
|
||||||
|
bind M-| select-layout "even-horizontal"
|
||||||
|
bind M-r rotate-window
|
||||||
|
|
||||||
|
|
||||||
|
# focus on first window
|
||||||
|
# select-window -t 0
|
||||||
7
.config/Scripts/transmission.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ -f $(pgrep transmission) ];
|
||||||
|
then
|
||||||
|
urxvt -e transmission-remote-cli
|
||||||
|
else
|
||||||
|
transmission-daemon && urxvt -e transmission-remote-cli
|
||||||
|
fi
|
||||||
4
.config/Scripts/unmount.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
sync
|
||||||
|
umount /mnt/* 2> /dev/null
|
||||||
|
rm -d /mnt/* 2> /dev/null
|
||||||
26
.config/Scripts/video.sh
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#This is the ffmpeg command that the screencast shortcut in i3 will run.
|
||||||
|
|
||||||
|
#Picks a file name for the output file based on availability:
|
||||||
|
|
||||||
|
if [[ -f ~/output.mkv ]]
|
||||||
|
then
|
||||||
|
n=1
|
||||||
|
while [[ -f ~/output_$n.mkv ]]
|
||||||
|
do
|
||||||
|
n=$((n+1))
|
||||||
|
done
|
||||||
|
filename="output_$n.mkv"
|
||||||
|
else
|
||||||
|
filename="output.mkv"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#The actual ffmpeg command:
|
||||||
|
|
||||||
|
ffmpeg -y \
|
||||||
|
-f x11grab \
|
||||||
|
-s $(xdpyinfo | grep dimensions | awk '{print $2;}') \
|
||||||
|
-i :0.0 \
|
||||||
|
-c:v libx264 -qp 0 -r 30 $filename
|
||||||
|
#-c:v ffvhuff -r 30 -c:a flac $filename
|
||||||
166
.config/Scripts/vimrc
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
execute pathogen#infect()
|
||||||
|
set number
|
||||||
|
set relativenumber
|
||||||
|
set so=10
|
||||||
|
|
||||||
|
|
||||||
|
"""BASIC TOOLS
|
||||||
|
"Navigating with guides
|
||||||
|
inoremap <Space><Space> <Esc>/<++><Enter>"_c4l
|
||||||
|
vnoremap <Space><Space> <Esc>/<++><Enter>"_c4l
|
||||||
|
map <Space><Space> <Esc>/<++><Enter>"_c4l
|
||||||
|
inoremap ;gui <++>
|
||||||
|
"For normal mode when in terminals (in X I have caps mapped to esc, this replaces it when I don't have X)
|
||||||
|
inoremap jw <Esc>
|
||||||
|
inoremap wj <Esc>
|
||||||
|
inoremap <C-l> <Space><Space>
|
||||||
|
"For split navigation
|
||||||
|
map <C-h> <C-w>h
|
||||||
|
map <C-j> <C-w>j
|
||||||
|
map <C-k> <C-w>k
|
||||||
|
map <C-l> <C-w>l
|
||||||
|
|
||||||
|
set nocompatible
|
||||||
|
filetype plugin on
|
||||||
|
|
||||||
|
"""LATEX
|
||||||
|
autocmd FileType tex inoremap ;fr \begin{frame}<Enter>\frametitle{}<Enter><Enter><++><Enter><Enter>\end{frame}<Enter><Enter><++><Esc>6kf}i
|
||||||
|
autocmd FileType tex inoremap ;fi \begin{fitch}<Enter><Enter>\end{fitch}<Enter><Enter><++><Esc>3kA
|
||||||
|
autocmd FileType tex inoremap ;exe \begin{exe}<Enter>\ex<Space><Enter>\end{exe}<Enter><Enter><++><Esc>3kA
|
||||||
|
autocmd FileType tex inoremap ;em \emph{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;bf \textbf{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;it \textit{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;ct \textcite{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;cp \parencite{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;glos {\gll<Space><++><Space>\\<Enter><++><Space>\\<Enter>\trans{``<++>''}}<Esc>2k2bcw
|
||||||
|
autocmd FileType tex inoremap ;x \begin{xlist}<Enter>\ex<Space><Enter>\end{xlist}<Esc>kA<Space>
|
||||||
|
autocmd FileType tex inoremap ;ol \begin{enumerate}<Enter><Enter>\end{enumerate}<Enter><Enter><++><Esc>3kA\item<Space>
|
||||||
|
autocmd FileType tex inoremap ;ul \begin{itemize}<Enter><Enter>\end{itemize}<Enter><Enter><++><Esc>3kA\item<Space>
|
||||||
|
autocmd FileType tex inoremap ;li <Enter>\item<Space>
|
||||||
|
autocmd FileType tex inoremap ;ref \ref{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;tab \begin{tabular}<Enter><++><Enter>\end{tabular}<Enter><Enter><++><Esc>4kA{}<Esc>i
|
||||||
|
autocmd FileType tex inoremap ;ot \begin{tableau}<Enter>\inp{<++>}<Tab>\const{<++>}<Tab><++><Enter><++><Enter>\end{tableau}<Enter><Enter><++><Esc>5kA{}<Esc>i
|
||||||
|
autocmd FileType tex inoremap ;can \cand{}<Tab><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;con \const{}<Tab><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;v \vio{}<Tab><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;a \href{}{<++>}<Space><++><Esc>2T{i
|
||||||
|
autocmd FileType tex inoremap ;sc \textsc{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;sec \section{}<Enter><Enter><++><Esc>2kf}i
|
||||||
|
autocmd FileType tex inoremap ;ssec \subsection{}<Enter><Enter><++><Esc>2kf}i
|
||||||
|
autocmd FileType tex inoremap ;sssec \subsubsection{}<Enter><Enter><++><Esc>2kf}i
|
||||||
|
autocmd FileType tex inoremap ;st <Esc>F{i*<Esc>f}i
|
||||||
|
autocmd FileType tex inoremap ;beg \begin{%DELRN%}<Enter><++><Enter>\end{%DELRN%}<Enter><Enter><++><Esc>4kfR:MultipleCursorsFind<Space>%DELRN%<Enter>c
|
||||||
|
"autocmd FileType tex inoremap ;up \usepackage{}<Esc>i
|
||||||
|
autocmd FileType tex inoremap ;up <Esc>/usepackage<Enter>o\usepackage{}<Esc>i
|
||||||
|
autocmd FileType tex nnoremap ;up /usepackage<Enter>o\usepackage{}<Esc>i
|
||||||
|
autocmd FileType tex inoremap ;tt \texttt{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;bt {\blindtext}
|
||||||
|
autocmd FileType tex inoremap ;nu $\varnothing$
|
||||||
|
autocmd FileType tex inoremap ;col \begin{columns}[T]<Enter>\begin{column}{.5\textwidth}<Enter><Enter>\end{column}<Enter>\begin{column}{.5\textwidth}<Enter><++><Enter>\end{column}<Enter>\end{columns}<Esc>5kA
|
||||||
|
autocmd FileType tex inoremap ;rn (\ref{})<++><Esc>F}i
|
||||||
|
"""END
|
||||||
|
|
||||||
|
"""Logical Symbols
|
||||||
|
autocmd FileType tex inoremap ;m $$<Space><++><Esc>2T$i
|
||||||
|
autocmd FileType tex inoremap ;M $$$$<Enter><Enter><++><Esc>2k$hi
|
||||||
|
autocmd FileType tex inoremap ;neg {\neg}
|
||||||
|
autocmd FileType tex inoremap ;V {\vee}
|
||||||
|
autocmd FileType tex inoremap ;or {\vee}
|
||||||
|
autocmd FileType tex inoremap ;L {\wedge}
|
||||||
|
autocmd FileType tex inoremap ;and {\wedge}
|
||||||
|
autocmd FileType tex inoremap ;ra {\rightarrow}
|
||||||
|
autocmd FileType tex inoremap ;la {\leftarrow}
|
||||||
|
autocmd FileType tex inoremap ;lra {\leftrightarrow}
|
||||||
|
autocmd FileType tex inoremap ;fa {\forall}
|
||||||
|
autocmd FileType tex inoremap ;ex {\exists}
|
||||||
|
autocmd FileType tex inoremap ;dia {\Diamond}
|
||||||
|
autocmd FileType tex inoremap ;box {\Box}
|
||||||
|
"""END
|
||||||
|
|
||||||
|
autocmd Filetype tex inoremap ;nom {\textsc{nom}}
|
||||||
|
autocmd FileType tex inoremap ;acc {\textsc{acc}}
|
||||||
|
autocmd FileType tex inoremap ;dat {\textsc{dat}}
|
||||||
|
autocmd FileType tex inoremap ;gen {\textsc{gen}}
|
||||||
|
autocmd FileType tex inoremap ;abl {\textsc{abl}}
|
||||||
|
autocmd FileType tex inoremap ;voc {\textsc{voc}}
|
||||||
|
autocmd FileType tex inoremap ;loc {\textsc{loc}}
|
||||||
|
autocmd Filetype tex inoremap ;inst {\textsc{inst}}
|
||||||
|
"autocmd FileType tex inoremap ;
|
||||||
|
|
||||||
|
"""IPA
|
||||||
|
autocmd FileType tex inoremap ;tipa \textipa{}<Space><++><Esc>T{i
|
||||||
|
autocmd FileType tex inoremap ;ae {\ae}
|
||||||
|
autocmd FileType tex inoremap ;A {\textscripta}
|
||||||
|
autocmd FileType tex inoremap ;dh {\dh}
|
||||||
|
autocmd FileType tex inoremap ;yogh {\textyogh}
|
||||||
|
autocmd FileType tex inoremap ;j {\textdyoghlig}
|
||||||
|
autocmd FileType tex inoremap ;uh {\textschwa}
|
||||||
|
autocmd FileType tex inoremap ;eps {\textepsilon}
|
||||||
|
autocmd FileType tex inoremap ;gam {\textgamma}
|
||||||
|
autocmd FileType tex inoremap ;I {\textsci}
|
||||||
|
autocmd FileType tex inoremap ;sh {\textesh}
|
||||||
|
autocmd FileType tex inoremap ;th {\texttheta}
|
||||||
|
autocmd FileType tex inoremap ;Th {\textthorn}
|
||||||
|
autocmd FileType tex inoremap ;TH {\textthorn}
|
||||||
|
autocmd FileType tex inoremap ;ups {\textupsilon}
|
||||||
|
autocmd FileType tex inoremap ;ph {\textphi}
|
||||||
|
autocmd FileType tex inoremap ;om {\textomega}
|
||||||
|
autocmd FileType tex inoremap ;sig {\textsigma}
|
||||||
|
autocmd FileType tex inoremap ;oe {\oe}
|
||||||
|
autocmd FileType tex inoremap ;ng {\ng}
|
||||||
|
autocmd FileType tex inoremap ;au {\textopeno}
|
||||||
|
autocmd FileType tex inoremap ;O {\textopeno}
|
||||||
|
autocmd FileType tex inoremap ;glot {\textglotstop}
|
||||||
|
autocmd FileType tex inoremap ;ch {\textteshlig}
|
||||||
|
"""END
|
||||||
|
|
||||||
|
"""HTML
|
||||||
|
autocmd FileType html inoremap ;b <b></b><Space><++><Esc>FbT>i
|
||||||
|
autocmd FileType html inoremap ;i <em></em><Space><++><Esc>FeT>i
|
||||||
|
autocmd FileType html inoremap ;1 <h1></h1><Enter><Enter><++><Esc>2kf<i
|
||||||
|
autocmd FileType html inoremap ;2 <h2></h2><Enter><Enter><++><Esc>2kf<i
|
||||||
|
autocmd FileType html inoremap ;3 <h3></h3><Enter><Enter><++><Esc>2kf<i
|
||||||
|
autocmd FileType html inoremap ;p <p></p><Enter><Enter><++><Esc>02kf>a
|
||||||
|
autocmd FileType html inoremap ;a <a<Space>href=""><++></a><Space><++><Esc>F"i
|
||||||
|
autocmd FileType html inoremap ;ul <ul><Enter><li></li><Enter></ul><Enter><Enter><++><Esc>03kf<i
|
||||||
|
autocmd FileType html inoremap ;li <Esc>o<li></li><Esc>F>a
|
||||||
|
autocmd FileType html inoremap ;ol <ol><Enter><li></li><Enter></ol><Enter><Enter><++><Esc>03kf<i
|
||||||
|
|
||||||
|
"""END
|
||||||
|
|
||||||
|
""".bib
|
||||||
|
autocmd FileType bib inoremap ;a @article{<Enter><Tab>author<Space>=<Space>"<++>",<Enter><Tab>year<Space>=<Space>"<++>",<Enter><Tab>title<Space>=<Space>"<++>",<Enter><Tab>journal<Space>=<Space>"<++>",<Enter><Tab>volume<Space>=<Space>"<++>",<Enter><Tab>pages<Space>=<Space>"<++>",<Enter><Tab>}<Enter><++><Esc>8kA,<Esc>i
|
||||||
|
autocmd FileType bib inoremap ;b @book{<Enter><Tab>author<Space>=<Space>"<++>",<Enter><Tab>year<Space>=<Space>"<++>",<Enter><Tab>title<Space>=<Space>"<++>",<Enter><Tab>publisher<Space>=<Space>"<++>",<Enter><Tab>}<Enter><++><Esc>6kA,<Esc>i
|
||||||
|
autocmd FileType bib inoremap ;c @incollection{<Enter><Tab>author<Space>=<Space>"<++>",<Enter><Tab>title<Space>=<Space>"<++>",<Enter><Tab>booktitle<Space>=<Space>"<++>",<Enter><Tab>editor<Space>=<Space>"<++>",<Enter><Tab>year<Space>=<Space>"<++>",<Enter><Tab>publisher<Space>=<Space>"<++>",<Enter><Tab>}<Enter><++><Esc>8kA,<Esc>i
|
||||||
|
"""END
|
||||||
|
|
||||||
|
let g:instant_markdown_autostart = 0
|
||||||
|
|
||||||
|
autocmd Filetype markdown inoremap ;n ---<Enter><Enter>
|
||||||
|
autocmd Filetype markdown inoremap ;b ****<Space><++><Esc>F*hi
|
||||||
|
autocmd Filetype markdown inoremap ;s ~~~~<Space><++><Esc>F~hi
|
||||||
|
autocmd Filetype markdown inoremap ;e **<Space><++><Esc>F*i
|
||||||
|
autocmd Filetype markdown inoremap ;h ====<Space><++><Esc>F=hi
|
||||||
|
autocmd Filetype markdown inoremap ;i <Space><++><Esc>F[a
|
||||||
|
autocmd Filetype markdown inoremap ;a [](<++>)<Space><++><Esc>F[a
|
||||||
|
autocmd Filetype markdown inoremap ;1 #<Space><Enter><++><Esc>kA
|
||||||
|
autocmd Filetype markdown inoremap ;2 ##<Space><Enter><++><Esc>kA
|
||||||
|
autocmd Filetype markdown inoremap ;3 ###<Space><Enter><++><Esc>kA
|
||||||
|
autocmd Filetype markdown inoremap ;l --------<Enter>
|
||||||
|
autocmd Filetype markdown nnoremap <C-p> :!pandoc<Space>-t<Space>beamer<Space>-s<Space><C-r>%<space>-o<Space><C-r>%<Backspace><Backspace>pdf<Space>-V<Space>theme:Copenhagen<Space>--latex-engine=xelatex<Enter>
|
||||||
|
|
||||||
|
|
||||||
|
syntax on
|
||||||
|
|
||||||
|
"au BufWinLeave * mkview
|
||||||
|
"au BufWinEnter * silent loadview
|
||||||
|
|
||||||
|
colorscheme slate
|
||||||
|
|
||||||
|
let g:vimwiki_ext2syntax = {'.md': 'markdown', '.markdown': 'markdown', '.mdown': 'markdown'}
|
||||||
|
"Spell-check set to F6
|
||||||
|
map <F6> :setlocal spell! spelllang=en_us<CR>
|
||||||
|
map <F10> :Goyo<CR>
|
||||||
|
|
||||||
|
set wildmode=longest,list,full
|
||||||
|
set wildmenu
|
||||||
16
.config/Scripts/wall_looper.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#Feed this script two arguments, $1 for a folder directory and $2 for a time interval in seconds.
|
||||||
|
|
||||||
|
#Will loop thru the files in the directory, using feh to change the background every $2 seconds.
|
||||||
|
|
||||||
|
while [ 1==1 ]
|
||||||
|
|
||||||
|
do
|
||||||
|
for file in $1*;
|
||||||
|
do
|
||||||
|
sleep $2
|
||||||
|
feh --bg-scale "$file"
|
||||||
|
cp "$file" ~/.config/wall.png
|
||||||
|
done
|
||||||
|
done
|
||||||
25
.config/calcurse/conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
appearance.calendarview=monthly
|
||||||
|
appearance.compactpanels=no
|
||||||
|
appearance.defaultpanel=calendar
|
||||||
|
appearance.layout=1
|
||||||
|
appearance.notifybar=yes
|
||||||
|
appearance.sidebarwidth=1
|
||||||
|
appearance.theme=red on default
|
||||||
|
appearance.todoview=show-completed
|
||||||
|
daemon.enable=no
|
||||||
|
daemon.log=no
|
||||||
|
format.inputdate=1
|
||||||
|
format.notifydate=%a %F
|
||||||
|
format.notifytime=%T
|
||||||
|
format.outputdate=%D
|
||||||
|
general.autogc=no
|
||||||
|
general.autosave=yes
|
||||||
|
general.confirmdelete=yes
|
||||||
|
general.confirmquit=no
|
||||||
|
general.firstdayofweek=sunday
|
||||||
|
general.periodicsave=0
|
||||||
|
general.progressbar=yes
|
||||||
|
general.systemdialogs=no
|
||||||
|
notification.command=printf '\a'
|
||||||
|
notification.notifyall=flagged-only
|
||||||
|
notification.warning=300
|
||||||
70
.config/calcurse/keys
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
# Calcurse keys configuration file
|
||||||
|
#
|
||||||
|
# This file sets the keybindings used by Calcurse.
|
||||||
|
# Lines beginning with "#" are comments, and ignored by Calcurse.
|
||||||
|
# To assign a keybinding to an action, this file must contain a line
|
||||||
|
# with the following syntax:
|
||||||
|
#
|
||||||
|
# ACTION KEY1 KEY2 ... KEYn
|
||||||
|
#
|
||||||
|
# Where ACTION is what will be performed when KEY1, KEY2, ..., or KEYn
|
||||||
|
# will be pressed.
|
||||||
|
#
|
||||||
|
# To define bindings which use the CONTROL key, prefix the key with 'C-'.
|
||||||
|
# The escape, space bar and horizontal Tab key can be specified using
|
||||||
|
# the 'ESC', 'SPC' and 'TAB' keyword, respectively.
|
||||||
|
# Arrow keys can also be specified with the UP, DWN, LFT, RGT keywords.
|
||||||
|
# Last, Home and End keys can be assigned using 'KEY_HOME' and 'KEY_END'
|
||||||
|
# keywords.
|
||||||
|
#
|
||||||
|
# A description of what each ACTION keyword is used for is available
|
||||||
|
# from calcurse online configuration menu.
|
||||||
|
|
||||||
|
generic-cancel ESC
|
||||||
|
generic-select SPC
|
||||||
|
generic-credits @
|
||||||
|
generic-help ?
|
||||||
|
generic-quit q Q
|
||||||
|
generic-save s S ^S
|
||||||
|
generic-reload R
|
||||||
|
generic-copy c
|
||||||
|
generic-paste p ^V
|
||||||
|
generic-change-view TAB
|
||||||
|
generic-import i I
|
||||||
|
generic-export x X
|
||||||
|
generic-goto g G
|
||||||
|
generic-other-cmd o O
|
||||||
|
generic-config-menu C
|
||||||
|
generic-redraw ^R
|
||||||
|
generic-add-appt ^A
|
||||||
|
generic-add-todo ^T
|
||||||
|
generic-prev-day T ^H
|
||||||
|
generic-next-day t ^L
|
||||||
|
generic-prev-week W ^K
|
||||||
|
generic-next-week w ^J
|
||||||
|
generic-prev-month M
|
||||||
|
generic-next-month m
|
||||||
|
generic-prev-year Y
|
||||||
|
generic-next-year y
|
||||||
|
generic-scroll-down ^N
|
||||||
|
generic-scroll-up ^P
|
||||||
|
generic-goto-today ^G
|
||||||
|
generic-command :
|
||||||
|
move-right l L RGT
|
||||||
|
move-left h H LFT
|
||||||
|
move-down j J DWN
|
||||||
|
move-up k K UP
|
||||||
|
start-of-week 0
|
||||||
|
end-of-week $
|
||||||
|
add-item a A
|
||||||
|
del-item d D
|
||||||
|
edit-item e E
|
||||||
|
view-item v V
|
||||||
|
pipe-item |
|
||||||
|
flag-item !
|
||||||
|
repeat r
|
||||||
|
edit-note n N
|
||||||
|
view-note >
|
||||||
|
raise-priority +
|
||||||
|
lower-priority -
|
||||||
56
.config/compton.conf
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# vim: filetype=conf
|
||||||
|
backend = "glx";
|
||||||
|
paint-on-overlay = true;
|
||||||
|
glx-no-stencil = true;
|
||||||
|
glx-no-rebind-pixmap = true;
|
||||||
|
vsync = "opengl-swc";
|
||||||
|
|
||||||
|
# These are important. The first one enables the opengl backend. The last one is the vsync method. Depending on the driver you might need to use a different method.
|
||||||
|
# The other options are smaller performance tweaks that work well in most cases.
|
||||||
|
# You can find the rest of the options here: https://github.com/chjj/compton/wiki/perf-guide, and here: https://github.com/chjj/compton/wiki/vsync-guide
|
||||||
|
|
||||||
|
|
||||||
|
# Shadow
|
||||||
|
shadow = true; # Enabled client-side shadows on windows.
|
||||||
|
no-dock-shadow = true; # Avoid drawing shadows on dock/panel windows.
|
||||||
|
no-dnd-shadow = true; # Don't draw shadows on DND windows.
|
||||||
|
clear-shadow = true; # Zero the part of the shadow's mask behind the window (experimental).
|
||||||
|
shadow-radius = 7; # The blur radius for shadows. (default 12)
|
||||||
|
shadow-offset-x = -7; # The left offset for shadows. (default -15)
|
||||||
|
shadow-offset-y = -7; # The top offset for shadows. (default -15)
|
||||||
|
shadow-exclude = [
|
||||||
|
"! name~=''",
|
||||||
|
"n:e:Notification",
|
||||||
|
"n:e:Plank",
|
||||||
|
"n:e:Docky",
|
||||||
|
"g:e:Synapse",
|
||||||
|
"g:e:Kupfer",
|
||||||
|
"g:e:WC_Cronograph",
|
||||||
|
"g:e:Conky",
|
||||||
|
"n:w:*Firefox*",
|
||||||
|
"n:w:*Chrome*",
|
||||||
|
"n:w:*Chromium*",
|
||||||
|
"class_g ?= 'Notify-osd'",
|
||||||
|
"class_g ?= 'Cairo-dock'",
|
||||||
|
"class_g ?= 'Xfce4-notifyd'",
|
||||||
|
"class_g ?= 'Xfce4-power-manager'"
|
||||||
|
];
|
||||||
|
|
||||||
|
# The shadow exclude options are helpful if you have shadows enabled. Due to the way compton draws its shadows, certain applications will have visual glitches
|
||||||
|
# (most applications are fine, only apps that do weird things with xshapes or argb are affected).
|
||||||
|
# This list includes all the affected apps I found in my testing. The "! name~=''" part excludes shadows on any "Unknown" windows, this prevents a visual glitch with the XFWM alt tab switcher.
|
||||||
|
|
||||||
|
# Fading
|
||||||
|
fading = false; # Fade windows during opacity changes.
|
||||||
|
fade-delta = 4; # The time between steps in a fade in milliseconds. (default 10).
|
||||||
|
fade-in-step = 0.03; # Opacity change between steps while fading in. (default 0.028).
|
||||||
|
fade-out-step = 0.03; # Opacity change between steps while fading out. (default 0.03).
|
||||||
|
#no-fading-openclose = true; # Fade windows in/out when opening/closing
|
||||||
|
|
||||||
|
detect-client-opacity = true; # This prevents opacity being ignored for some apps. For example without this enabled my xfce4-notifyd is 100% opacity no matter what.
|
||||||
|
|
||||||
|
# Window type settings
|
||||||
|
wintypes:
|
||||||
|
{
|
||||||
|
tooltip = { fade = true; shadow = false; };
|
||||||
|
};
|
||||||
12
.config/feh/keys
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
zoom_in K XF86Forward
|
||||||
|
zoom_out J XF86Back
|
||||||
|
next_img L space
|
||||||
|
prev_img BackSpace H
|
||||||
|
|
||||||
|
scroll_up k Up
|
||||||
|
scroll_down j Down
|
||||||
|
scroll_right l Right
|
||||||
|
scroll_left h Left
|
||||||
|
|
||||||
|
toggle_fullscreen f
|
||||||
|
save_filelist F
|
||||||
24
.config/fontconfig/fonts.conf
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
|
||||||
|
<fontconfig>
|
||||||
|
|
||||||
|
<alias>
|
||||||
|
<family>serif</family>
|
||||||
|
<prefer><family>Tinos</family></prefer>
|
||||||
|
</alias>
|
||||||
|
<alias>
|
||||||
|
<family>sans-serif</family>
|
||||||
|
<prefer><family>Arimo</family></prefer>
|
||||||
|
</alias>
|
||||||
|
<alias>
|
||||||
|
<family>sans</family>
|
||||||
|
<prefer><family>Arimo</family></prefer>
|
||||||
|
</alias>
|
||||||
|
<alias>
|
||||||
|
<family>monospace</family>
|
||||||
|
<prefer><family>Tamsyn</family></prefer>
|
||||||
|
</alias>
|
||||||
|
|
||||||
|
</fontconfig>
|
||||||
|
|
||||||
|
|
||||||
15
.config/i3/bar/.codeclimate.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
engines:
|
||||||
|
duplication:
|
||||||
|
enabled: true
|
||||||
|
config:
|
||||||
|
languages:
|
||||||
|
- python
|
||||||
|
fixme:
|
||||||
|
enabled: true
|
||||||
|
radon:
|
||||||
|
enabled: true
|
||||||
|
ratings:
|
||||||
|
paths:
|
||||||
|
- "**.py"
|
||||||
|
exclude_paths:
|
||||||
|
- tests/
|
||||||
10
.config/i3/bar/.coveragerc
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[run]
|
||||||
|
omit =
|
||||||
|
tests/*
|
||||||
|
*mock*
|
||||||
|
*funcsigs*
|
||||||
|
*pbr*
|
||||||
|
*six*
|
||||||
|
/usr/lib*
|
||||||
|
|
||||||
|
[report]
|
||||||
91
.config/i3/bar/.gitignore
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
*swp
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
18
.config/i3/bar/.travis.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
- "3.3"
|
||||||
|
- "3.4"
|
||||||
|
- "3.5"
|
||||||
|
- "3.6"
|
||||||
|
install:
|
||||||
|
- pip install psutil
|
||||||
|
- pip install netifaces
|
||||||
|
- pip install -U coverage==4.3
|
||||||
|
- pip install codeclimate-test-reporter
|
||||||
|
script:
|
||||||
|
- nosetests -v --with-coverage --cover-erase tests/
|
||||||
|
- CODECLIMATE_REPO_TOKEN=40cb00907f7a10e04868e856570bb997ab9c42fd3b63d980f2b2269433195fdf codeclimate-test-reporter
|
||||||
|
addons:
|
||||||
|
code_climate:
|
||||||
|
repo_token: 40cb00907f7a10e04868e856570bb997ab9c42fd3b63d980f2b2269433195fdf
|
||||||
21
.config/i3/bar/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 tobi-wan-kenobi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
134
.config/i3/bar/README.md
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# bumblebee-status
|
||||||
|
|
||||||
|
[](https://travis-ci.org/tobi-wan-kenobi/bumblebee-status)
|
||||||
|
[](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
||||||
|
[](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/coverage)
|
||||||
|
[](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
||||||
|
|
||||||
|
bumblebee-status is a modular, theme-able status line generator for the [i3 window manager](https://i3wm.org/).
|
||||||
|
|
||||||
|
Focus is on:
|
||||||
|
* Ease of use (no configuration files!)
|
||||||
|
* Theme support
|
||||||
|
* Extensibility (of course...)
|
||||||
|
|
||||||
|
I hope you like it and appreciate any kind of feedback: Bug reports, Feature requests, etc. :)
|
||||||
|
|
||||||
|
Thanks a lot!
|
||||||
|
|
||||||
|
Supported Python versions: 2.7, 3.3, 3.4, 3.5, 3.6
|
||||||
|
|
||||||
|
Explicitly unsupported Python versions: 3.2 (missing unicode literals)
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
See [the wiki](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki) for documentation.
|
||||||
|
|
||||||
|
Other resources:
|
||||||
|
|
||||||
|
* A list of [available modules](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/Available-Modules)
|
||||||
|
* [How to write a theme](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-theme)
|
||||||
|
* [How to write a module](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-module)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
```
|
||||||
|
$ git clone git://github.com/tobi-wan-kenobi/bumblebee-status
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
## Normal usage
|
||||||
|
Next, open your i3wm configuration and modify the *status_command* for your i3bar like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
bar {
|
||||||
|
status_command = <path to bumblebee-status/bumblebee-status> -m <list of modules> -p <list of module parameters> -t <theme>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can retrieve a list of modules and themes by entering:
|
||||||
|
```
|
||||||
|
$ cd bumblebee-status
|
||||||
|
$ ./bumblebee-status -l themes
|
||||||
|
$ ./bumblebee-status -l modules
|
||||||
|
```
|
||||||
|
|
||||||
|
To change the update interval, use:
|
||||||
|
```
|
||||||
|
$ ./bumblebee-status -m <list of modules> -p interval=<interval in seconds>
|
||||||
|
```
|
||||||
|
|
||||||
|
As a simple example, this is what my i3 configuration looks like:
|
||||||
|
|
||||||
|
```
|
||||||
|
bar {
|
||||||
|
font pango:Inconsolata 10
|
||||||
|
position top
|
||||||
|
tray_output none
|
||||||
|
status_command ~/.i3/bumblebee-status/bumblebee-status -m nic disk:root cpu memory battery date time pasink pasource dnf -p root.path=/ time.format="%H:%M CW %V" date.format="%a, %b %d %Y" -t solarized-powerline
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart i3wm and - that's it!
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
If errors occur, you should see them in the i3bar itself. If that does not work, or you need more information for troubleshooting, you can activate a debug log using the `-d` or `--debug` switch:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bumblebee-status -d -m <list of modules>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a file called `debug.log` in the same directory as the executable `bumblebee-status`.
|
||||||
|
|
||||||
|
# Required Modules
|
||||||
|
|
||||||
|
Modules and commandline utilities are only required for modules, the core itself has no external dependencies at all.
|
||||||
|
|
||||||
|
* psutil (for the modules 'cpu', 'memory', 'traffic')
|
||||||
|
* netifaces (for the module 'nic', 'traffic')
|
||||||
|
* requests (for the module 'weather')
|
||||||
|
|
||||||
|
# Required commandline utilities
|
||||||
|
|
||||||
|
* xbacklight (for the module 'brightness')
|
||||||
|
* xset (for the module 'caffeine')
|
||||||
|
* notify-send (for the module 'caffeine')
|
||||||
|
* cmus-remote (for the module 'cmus')
|
||||||
|
* dnf (for the module 'dnf')
|
||||||
|
* gpmdp-remote (for the module 'gpmdp')
|
||||||
|
* setxkbmap (for the module 'layout')
|
||||||
|
* fakeroot (for the module 'pacman')
|
||||||
|
* pacman (for the module 'pacman')
|
||||||
|
* pactl (for the module 'pulseaudio')
|
||||||
|
* ping (for the module 'ping')
|
||||||
|
* redshift (for the module 'redshift')
|
||||||
|
* xrandr (for the module 'xrandr')
|
||||||
|
* sensors (for the module 'sensors')
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
Here are some screenshots for all themes that currently exist:
|
||||||
|
|
||||||
|
:exclamation: Some themes (all 'Powerline' themes) require [Font Awesome](http://fontawesome.io/) and a powerline-compatible font ([powerline-fonts](https://github.com/powerline/fonts), for example) to display all icons correctly.
|
||||||
|
|
||||||
|
Gruvbox Powerline (`-t gruvbox-powerline`) (contributed by [@paxy97](https://github.com/paxy97)):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Solarized Powerline (`-t solarized-powerline`):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Gruvbox (`-t gruvbox`):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Solarized (`-t solarized`):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Powerline (`-t powerline`):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Default (nothing or `-t default`):
|
||||||
|
|
||||||
|

|
||||||
26
.config/i3/bar/bin/load-i3-bars.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ ! -f ~/.i3/config.template ]; then
|
||||||
|
cp ~/.i3/config ~/.i3/config.template
|
||||||
|
else
|
||||||
|
cp ~/.i3/config.template ~/.i3/config
|
||||||
|
fi
|
||||||
|
|
||||||
|
screens=$(xrandr -q|grep ' connected'| grep -P '\d+x\d+' |cut -d' ' -f1)
|
||||||
|
|
||||||
|
echo "screens: $screens"
|
||||||
|
|
||||||
|
while read -r line; do
|
||||||
|
screen=$(echo $line | cut -d' ' -f1)
|
||||||
|
others=$(echo $screens|tr ' ' '\n'|grep -v $screen|tr '\n' '-'|sed 's/.$//')
|
||||||
|
|
||||||
|
if [ -f ~/.i3/config.$screen-$others ]; then
|
||||||
|
cat ~/.i3/config.$screen-$others >> ~/.i3/config
|
||||||
|
else
|
||||||
|
if [ -f ~/.i3/config.$screen ]; then
|
||||||
|
cat ~/.i3/config.$screen >> ~/.i3/config
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done <<< "$screens"
|
||||||
|
|
||||||
|
i3-msg restart
|
||||||
22
.config/i3/bar/bin/pacman-updates
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
if ! type -P fakeroot >/dev/null; then
|
||||||
|
error 'Cannot find the fakeroot binary.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $CHECKUPDATES_DB ]]; then
|
||||||
|
CHECKUPDATES_DB="${TMPDIR:-/tmp}/checkup-db-${USER}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f $CHECKUPDATES_DB/db.lck' INT TERM EXIT
|
||||||
|
|
||||||
|
DBPath="${DBPath:-/var/lib/pacman/}"
|
||||||
|
eval $(awk -F' *= *' '$1 ~ /DBPath/ { print $1 "=" $2 }' /etc/pacman.conf)
|
||||||
|
|
||||||
|
mkdir -p "$CHECKUPDATES_DB"
|
||||||
|
ln -s "${DBPath}/local" "$CHECKUPDATES_DB" &> /dev/null
|
||||||
|
fakeroot -- pacman -Sy --dbpath "$CHECKUPDATES_DB" --logfile /dev/null &> /dev/null
|
||||||
|
fakeroot pacman -Su -p --dbpath "$CHECKUPDATES_DB"
|
||||||
|
|
||||||
|
exit 0
|
||||||
12
.config/i3/bar/bin/toggle-display.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo $(dirname $(readlink -f "$0"))
|
||||||
|
|
||||||
|
i3bar_update=$(dirname $(readlink -f "$0"))/load-i3-bars.sh
|
||||||
|
|
||||||
|
xrandr "$@"
|
||||||
|
|
||||||
|
if [ -f $i3bar_update ]; then
|
||||||
|
sleep 1
|
||||||
|
$i3bar_update
|
||||||
|
fi
|
||||||
66
.config/i3/bar/bumblebee-status
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import bumblebee.theme
|
||||||
|
import bumblebee.engine
|
||||||
|
import bumblebee.config
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.modules.error
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config = bumblebee.config.Config(sys.argv[1:])
|
||||||
|
|
||||||
|
if config.debug():
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="[%(asctime)s] %(levelname)-8s %(message)s",
|
||||||
|
filename=os.path.expanduser(config.logfile())
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="[%(asctime)s] %(levelname)-8s %(message)s",
|
||||||
|
stream=sys.stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
theme = bumblebee.theme.Theme(config.theme())
|
||||||
|
output = bumblebee.output.I3BarOutput(theme=theme)
|
||||||
|
inp = bumblebee.input.I3BarInput()
|
||||||
|
engine = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
engine = bumblebee.engine.Engine(
|
||||||
|
config=config,
|
||||||
|
output=output,
|
||||||
|
inp=inp,
|
||||||
|
)
|
||||||
|
engine.run()
|
||||||
|
except KeyboardInterrupt as error:
|
||||||
|
inp.stop()
|
||||||
|
sys.exit(0)
|
||||||
|
except BaseException as e:
|
||||||
|
logging.exception(e)
|
||||||
|
if output.started():
|
||||||
|
output.flush()
|
||||||
|
output.end()
|
||||||
|
else:
|
||||||
|
output.start()
|
||||||
|
import time
|
||||||
|
while True:
|
||||||
|
output.begin()
|
||||||
|
error = bumblebee.modules.error.Module(engine, config)
|
||||||
|
error.set("exception occurred: {}".format(e))
|
||||||
|
widget = error.widgets()[0]
|
||||||
|
widget.link_module(error)
|
||||||
|
output.draw(widget, error)
|
||||||
|
output.flush()
|
||||||
|
output.end()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
0
.config/i3/bar/bumblebee/__init__.py
Normal file
99
.config/i3/bar/bumblebee/config.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
"""Configuration handling
|
||||||
|
|
||||||
|
This module provides configuration information (loaded modules,
|
||||||
|
module parameters, etc.) to all other components
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import argparse
|
||||||
|
import textwrap
|
||||||
|
import importlib
|
||||||
|
import bumblebee.store
|
||||||
|
|
||||||
|
MODULE_HELP = "Specify a space-separated list of modules to load. The order of the list determines their order in the i3bar (from left to right). Use <module>:<alias> to provide an alias in case you want to load the same module multiple times, but specify different parameters."
|
||||||
|
THEME_HELP = "Specify the theme to use for drawing modules"
|
||||||
|
PARAMETER_HELP = "Provide configuration parameters in the form of <module>.<key>=<value>"
|
||||||
|
LIST_HELP = "Display a list of either available themes or available modules along with their parameters."
|
||||||
|
DEBUG_HELP = "Enable debug log ('debug.log' located in the same directory as the bumblebee-status executable)"
|
||||||
|
|
||||||
|
class print_usage(argparse.Action):
|
||||||
|
def __init__(self, option_strings, dest, nargs=None, **kwargs):
|
||||||
|
argparse.Action.__init__(self, option_strings, dest, nargs, **kwargs)
|
||||||
|
self._indent = " "*2
|
||||||
|
|
||||||
|
def __call__(self, parser, namespace, value, option_string=None):
|
||||||
|
if value == "modules":
|
||||||
|
self.print_modules()
|
||||||
|
elif value == "themes":
|
||||||
|
self.print_themes()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def print_themes(self):
|
||||||
|
print(textwrap.fill(", ".join(bumblebee.theme.themes()),
|
||||||
|
80, initial_indent = self._indent, subsequent_indent = self._indent
|
||||||
|
))
|
||||||
|
|
||||||
|
def print_modules(self):
|
||||||
|
for m in bumblebee.engine.all_modules():
|
||||||
|
mod = importlib.import_module("bumblebee.modules.{}".format(m["name"]))
|
||||||
|
print(textwrap.fill("{}:".format(m["name"]), 80,
|
||||||
|
initial_indent=self._indent*2, subsequent_indent=self._indent*2))
|
||||||
|
for line in mod.__doc__.split("\n"):
|
||||||
|
print(textwrap.fill(line, 80,
|
||||||
|
initial_indent=self._indent*3, subsequent_indent=self._indent*6))
|
||||||
|
|
||||||
|
def create_parser():
|
||||||
|
"""Create the argument parser"""
|
||||||
|
parser = argparse.ArgumentParser(description="display system data in the i3bar")
|
||||||
|
parser.add_argument("-m", "--modules", nargs="+", default=[],
|
||||||
|
help=MODULE_HELP)
|
||||||
|
parser.add_argument("-t", "--theme", default="default", help=THEME_HELP)
|
||||||
|
parser.add_argument("-p", "--parameters", nargs="+", default=[],
|
||||||
|
help=PARAMETER_HELP)
|
||||||
|
parser.add_argument("-l", "--list", choices=["modules", "themes"], action=print_usage,
|
||||||
|
help=LIST_HELP)
|
||||||
|
parser.add_argument("-d", "--debug", action="store_true",
|
||||||
|
help=DEBUG_HELP)
|
||||||
|
parser.add_argument("-f", "--logfile", default="~/bumblebee-status-debug.log",
|
||||||
|
help="Location of the debug log file")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
class Config(bumblebee.store.Store):
|
||||||
|
"""Top-level configuration class
|
||||||
|
|
||||||
|
Parses commandline arguments and provides non-module
|
||||||
|
specific configuration information.
|
||||||
|
"""
|
||||||
|
def __init__(self, args=None):
|
||||||
|
super(Config, self).__init__()
|
||||||
|
parser = create_parser()
|
||||||
|
self._args = parser.parse_args(args if args else [])
|
||||||
|
|
||||||
|
if not self._args.debug:
|
||||||
|
logger = logging.getLogger().disabled = True
|
||||||
|
|
||||||
|
for param in self._args.parameters:
|
||||||
|
key, value = param.split("=")
|
||||||
|
self.set(key, value)
|
||||||
|
|
||||||
|
def modules(self):
|
||||||
|
"""Return a list of all activated modules"""
|
||||||
|
return [{
|
||||||
|
"module": x.split(":")[0],
|
||||||
|
"name": x if not ":" in x else x.split(":")[1],
|
||||||
|
} for x in self._args.modules]
|
||||||
|
|
||||||
|
def theme(self):
|
||||||
|
"""Return the name of the selected theme"""
|
||||||
|
return self._args.theme
|
||||||
|
|
||||||
|
def debug(self):
|
||||||
|
return self._args.debug
|
||||||
|
|
||||||
|
def logfile(self):
|
||||||
|
return self._args.logfile
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
166
.config/i3/bar/bumblebee/engine.py
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
"""Core application engine"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import pkgutil
|
||||||
|
import importlib
|
||||||
|
import bumblebee.error
|
||||||
|
import bumblebee.modules
|
||||||
|
|
||||||
|
def all_modules():
|
||||||
|
"""Return a list of available modules"""
|
||||||
|
result = []
|
||||||
|
path = os.path.dirname(bumblebee.modules.__file__)
|
||||||
|
for mod in [name for _, name, _ in pkgutil.iter_modules([path])]:
|
||||||
|
result.append({
|
||||||
|
"name": mod
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
class Module(object):
|
||||||
|
"""Module instance base class
|
||||||
|
|
||||||
|
Objects of this type represent the modules that
|
||||||
|
the user configures. Concrete module implementations
|
||||||
|
(e.g. CPU utilization, disk usage, etc.) derive from
|
||||||
|
this base class.
|
||||||
|
"""
|
||||||
|
def __init__(self, engine, config={}, widgets=[]):
|
||||||
|
self.name = config.get("name", self.__module__.split(".")[-1])
|
||||||
|
self._config = config
|
||||||
|
self.id = self.name
|
||||||
|
self._widgets = []
|
||||||
|
if widgets:
|
||||||
|
self._widgets = widgets if isinstance(widgets, list) else [widgets]
|
||||||
|
|
||||||
|
def widgets(self):
|
||||||
|
"""Return the widgets to draw for this module"""
|
||||||
|
return self._widgets
|
||||||
|
|
||||||
|
def widget(self, name):
|
||||||
|
for widget in self._widgets:
|
||||||
|
if widget.name == name:
|
||||||
|
return widget
|
||||||
|
|
||||||
|
def widget_by_id(self, uid):
|
||||||
|
for widget in self._widgets:
|
||||||
|
if widget.id == uid:
|
||||||
|
return widget
|
||||||
|
return None
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
"""By default, update() is a NOP"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_all(self):
|
||||||
|
self.update(self._widgets)
|
||||||
|
|
||||||
|
def parameter(self, name, default=None):
|
||||||
|
"""Return the config parameter 'name' for this module"""
|
||||||
|
name = "{}.{}".format(self.name, name)
|
||||||
|
return self._config["config"].get(name, default)
|
||||||
|
|
||||||
|
def threshold_state(self, value, warn, crit):
|
||||||
|
if value > float(self.parameter("critical", crit)):
|
||||||
|
return "critical"
|
||||||
|
if value > float(self.parameter("warning", warn)):
|
||||||
|
return "warning"
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Engine(object):
|
||||||
|
"""Engine for driving the application
|
||||||
|
|
||||||
|
This class connects input/output, instantiates all
|
||||||
|
required modules and drives the "event loop"
|
||||||
|
"""
|
||||||
|
def __init__(self, config, output=None, inp=None):
|
||||||
|
self._output = output
|
||||||
|
self._config = config
|
||||||
|
self._running = True
|
||||||
|
self._modules = []
|
||||||
|
self.input = inp
|
||||||
|
self._aliases = self._read_aliases()
|
||||||
|
self.load_modules(config.modules())
|
||||||
|
|
||||||
|
self.input.register_callback(None, bumblebee.input.WHEEL_UP,
|
||||||
|
"i3-msg workspace prev_on_output")
|
||||||
|
self.input.register_callback(None, bumblebee.input.WHEEL_DOWN,
|
||||||
|
"i3-msg workspace next_on_output")
|
||||||
|
|
||||||
|
self.input.start()
|
||||||
|
|
||||||
|
def modules(self):
|
||||||
|
return self._modules
|
||||||
|
|
||||||
|
def load_modules(self, modules):
|
||||||
|
"""Load specified modules and return them as list"""
|
||||||
|
for module in modules:
|
||||||
|
mod = self._load_module(module["module"], module["name"])
|
||||||
|
self._modules.append(mod)
|
||||||
|
self._register_module_callbacks(mod)
|
||||||
|
return self._modules
|
||||||
|
|
||||||
|
def _register_module_callbacks(self, module):
|
||||||
|
buttons = [
|
||||||
|
{ "name": "left-click", "id": bumblebee.input.LEFT_MOUSE },
|
||||||
|
{ "name": "middle-click", "id": bumblebee.input.MIDDLE_MOUSE },
|
||||||
|
{ "name": "right-click", "id": bumblebee.input.RIGHT_MOUSE },
|
||||||
|
{ "name": "wheel-up", "id": bumblebee.input.WHEEL_UP },
|
||||||
|
{ "name": "wheel-down", "id": bumblebee.input.WHEEL_DOWN },
|
||||||
|
]
|
||||||
|
for button in buttons:
|
||||||
|
if module.parameter(button["name"], None):
|
||||||
|
self.input.register_callback(obj=module,
|
||||||
|
button=button["id"], cmd=module.parameter(button["name"]))
|
||||||
|
|
||||||
|
def _read_aliases(self):
|
||||||
|
result = {}
|
||||||
|
for module in all_modules():
|
||||||
|
mod = importlib.import_module("bumblebee.modules.{}".format(module["name"]))
|
||||||
|
for alias in getattr(mod, "ALIASES", []):
|
||||||
|
result[alias] = module["name"]
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _load_module(self, module_name, config_name=None):
|
||||||
|
"""Load specified module and return it as object"""
|
||||||
|
if module_name in self._aliases:
|
||||||
|
config_name is config_name if config_name else module_name
|
||||||
|
module_name = self._aliases[module_name]
|
||||||
|
if config_name is None:
|
||||||
|
config_name = module_name
|
||||||
|
try:
|
||||||
|
module = importlib.import_module("bumblebee.modules.{}".format(module_name))
|
||||||
|
except ImportError as error:
|
||||||
|
raise bumblebee.error.ModuleLoadError(error)
|
||||||
|
return getattr(module, "Module")(self, {
|
||||||
|
"name": config_name,
|
||||||
|
"config": self._config
|
||||||
|
})
|
||||||
|
|
||||||
|
def running(self):
|
||||||
|
"""Check whether the event loop is running"""
|
||||||
|
return self._running
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop the event loop"""
|
||||||
|
self._running = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Start the event loop"""
|
||||||
|
self._output.start()
|
||||||
|
while self.running():
|
||||||
|
self._output.begin()
|
||||||
|
for module in self._modules:
|
||||||
|
module.update(module.widgets())
|
||||||
|
for widget in module.widgets():
|
||||||
|
widget.link_module(module)
|
||||||
|
self._output.draw(widget=widget, module=module, engine=self)
|
||||||
|
self._output.flush()
|
||||||
|
self._output.end()
|
||||||
|
if self.running():
|
||||||
|
self.input.wait(float(self._config.get("interval", 1)))
|
||||||
|
|
||||||
|
self._output.stop()
|
||||||
|
self.input.stop()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
15
.config/i3/bar/bumblebee/error.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"""Collection of all exceptions raised by this tool"""
|
||||||
|
|
||||||
|
class BaseError(Exception):
|
||||||
|
"""Base class for all exceptions generated by this tool"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ModuleLoadError(BaseError):
|
||||||
|
"""Raised whenever loading a module fails"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ThemeLoadError(BaseError):
|
||||||
|
"""Raised whenever loading a theme fails"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
134
.config/i3/bar/bumblebee/input.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
"""Input classes"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
import time
|
||||||
|
import select
|
||||||
|
import threading
|
||||||
|
import bumblebee.util
|
||||||
|
|
||||||
|
LEFT_MOUSE = 1
|
||||||
|
MIDDLE_MOUSE = 2
|
||||||
|
RIGHT_MOUSE = 3
|
||||||
|
WHEEL_UP = 4
|
||||||
|
WHEEL_DOWN = 5
|
||||||
|
|
||||||
|
def is_terminated():
|
||||||
|
for thread in threading.enumerate():
|
||||||
|
if thread.name == "MainThread" and not thread.is_alive():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read_input(inp):
|
||||||
|
"""Read i3bar input and execute callbacks"""
|
||||||
|
epoll = select.epoll()
|
||||||
|
epoll.register(sys.stdin.fileno(), select.EPOLLIN)
|
||||||
|
while inp.running:
|
||||||
|
if is_terminated():
|
||||||
|
return
|
||||||
|
|
||||||
|
events = epoll.poll(1)
|
||||||
|
for fileno, event in events:
|
||||||
|
line = "["
|
||||||
|
while "[" in line:
|
||||||
|
line = sys.stdin.readline().strip(",").strip()
|
||||||
|
inp.has_event = True
|
||||||
|
try:
|
||||||
|
event = json.loads(line)
|
||||||
|
if "instance" in event:
|
||||||
|
inp.callback(event)
|
||||||
|
inp.redraw()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
epoll.unregister(sys.stdin.fileno())
|
||||||
|
epoll.close()
|
||||||
|
inp.has_event = True
|
||||||
|
inp.clean_exit = True
|
||||||
|
|
||||||
|
class I3BarInput(object):
|
||||||
|
"""Process incoming events from the i3bar"""
|
||||||
|
def __init__(self):
|
||||||
|
self.running = True
|
||||||
|
self._callbacks = {}
|
||||||
|
self.clean_exit = False
|
||||||
|
self.global_id = str(uuid.uuid4())
|
||||||
|
self.need_event = False
|
||||||
|
self.has_event = False
|
||||||
|
self._condition = threading.Condition()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Start asynchronous input processing"""
|
||||||
|
self.has_event = False
|
||||||
|
self.running = True
|
||||||
|
self._condition.acquire()
|
||||||
|
self._thread = threading.Thread(target=read_input, args=(self,))
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
def redraw(self):
|
||||||
|
self._condition.acquire()
|
||||||
|
self._condition.notify()
|
||||||
|
self._condition.release()
|
||||||
|
|
||||||
|
def alive(self):
|
||||||
|
"""Check whether the input processing is still active"""
|
||||||
|
return self._thread.is_alive()
|
||||||
|
|
||||||
|
def wait(self, timeout):
|
||||||
|
self._condition.wait(timeout)
|
||||||
|
|
||||||
|
def _wait(self):
|
||||||
|
while not self.has_event:
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.has_event = False
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop asynchronous input processing"""
|
||||||
|
self._condition.release()
|
||||||
|
if self.need_event:
|
||||||
|
self._wait()
|
||||||
|
self.running = False
|
||||||
|
self._thread.join()
|
||||||
|
return self.clean_exit
|
||||||
|
|
||||||
|
def _uuidstr(self, name, button):
|
||||||
|
return "{}::{}".format(name, button)
|
||||||
|
|
||||||
|
def _uid(self, obj, button):
|
||||||
|
uid = self.global_id
|
||||||
|
if obj:
|
||||||
|
uid = obj.id
|
||||||
|
return self._uuidstr(uid, button)
|
||||||
|
|
||||||
|
def deregister_callbacks(self, obj):
|
||||||
|
to_delete = []
|
||||||
|
uid = obj.id if obj else self.global_id
|
||||||
|
for key in self._callbacks:
|
||||||
|
if uid in key:
|
||||||
|
to_delete.append(key)
|
||||||
|
for key in to_delete:
|
||||||
|
del self._callbacks[key]
|
||||||
|
|
||||||
|
def register_callback(self, obj, button, cmd):
|
||||||
|
"""Register a callback function or system call"""
|
||||||
|
uid = self._uid(obj, button)
|
||||||
|
if uid not in self._callbacks:
|
||||||
|
self._callbacks[uid] = {}
|
||||||
|
self._callbacks[uid] = cmd
|
||||||
|
|
||||||
|
def callback(self, event):
|
||||||
|
"""Execute callback action for an incoming event"""
|
||||||
|
button = event["button"]
|
||||||
|
|
||||||
|
cmd = self._callbacks.get(self._uuidstr(self.global_id, button), None)
|
||||||
|
cmd = self._callbacks.get(self._uuidstr(event["name"], button), cmd)
|
||||||
|
cmd = self._callbacks.get(self._uuidstr(event["instance"], button), cmd)
|
||||||
|
|
||||||
|
if cmd is None:
|
||||||
|
return
|
||||||
|
if callable(cmd):
|
||||||
|
cmd(event)
|
||||||
|
else:
|
||||||
|
bumblebee.util.execute(cmd, False)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
0
.config/i3/bar/bumblebee/modules/__init__.py
Normal file
36
.config/i3/bar/bumblebee/modules/amixer.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""get volume level
|
||||||
|
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.volume)
|
||||||
|
)
|
||||||
|
self._level = "0"
|
||||||
|
self._muted = True
|
||||||
|
device = self.parameter("device", "Master,0")
|
||||||
|
self._cmdString = "amixer get {}".format(device)
|
||||||
|
|
||||||
|
def volume(self, widget):
|
||||||
|
m = re.search(r'([\d]+)\%', self._level)
|
||||||
|
self._muted = True
|
||||||
|
if m:
|
||||||
|
if m.group(1) != "0":
|
||||||
|
self._muted = False
|
||||||
|
return "{}%".format(m.group(1))
|
||||||
|
else:
|
||||||
|
return "0%"
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._level = bumblebee.util.execute(self._cmdString)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if self._muted:
|
||||||
|
return [ "warning", "muted" ]
|
||||||
|
return [ "unmuted" ]
|
||||||
82
.config/i3/bar/bumblebee/modules/battery.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays battery status, remaining percentage and charging information.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* battery.device : The device to read information from (defaults to BAT0)
|
||||||
|
* battery.warning : Warning threshold in % of remaining charge (defaults to 20)
|
||||||
|
* battery.critical: Critical threshold in % of remaining charge (defaults to 10)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.capacity)
|
||||||
|
)
|
||||||
|
battery = self.parameter("device", "BAT0")
|
||||||
|
self._path = "/sys/class/power_supply/{}".format(battery)
|
||||||
|
self._capacity = 100
|
||||||
|
self._ac = False
|
||||||
|
|
||||||
|
def capacity(self, widget):
|
||||||
|
if self._ac:
|
||||||
|
return "ac"
|
||||||
|
if self._capacity == -1:
|
||||||
|
return "n/a"
|
||||||
|
return "{:03d}%".format(self._capacity)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
widget = widgets[0]
|
||||||
|
self._ac = False
|
||||||
|
if not os.path.exists(self._path):
|
||||||
|
self._ac = True
|
||||||
|
self._capacity = 100
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(self._path + "/capacity") as f:
|
||||||
|
self._capacity = int(f.read())
|
||||||
|
except IOError:
|
||||||
|
self._capacity = -1
|
||||||
|
self._capacity = self._capacity if self._capacity < 100 else 100
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
state = []
|
||||||
|
|
||||||
|
if self._capacity < 0:
|
||||||
|
return ["critical", "unknown"]
|
||||||
|
|
||||||
|
if self._capacity < int(self.parameter("critical", 10)):
|
||||||
|
state.append("critical")
|
||||||
|
elif self._capacity > int(self.parameter("great", 90)):
|
||||||
|
state.append("great")
|
||||||
|
elif self._capacity > int(self.parameter("good", 80)):
|
||||||
|
state.append("good")
|
||||||
|
elif self._capacity < int(self.parameter("warning", 20)):
|
||||||
|
state.append("warning")
|
||||||
|
elif self._capacity < int(self.parameter("mid", 80)):
|
||||||
|
state.append("mid")
|
||||||
|
|
||||||
|
if self._ac:
|
||||||
|
state.append("AC")
|
||||||
|
else:
|
||||||
|
charge = ""
|
||||||
|
with open(self._path + "/status") as f:
|
||||||
|
charge = f.read().strip()
|
||||||
|
if charge == "Discharging":
|
||||||
|
state.append("discharging-{}".format(min([10, 25, 50, 80, 100] , key=lambda i:abs(i-self._capacity))))
|
||||||
|
else:
|
||||||
|
if self._capacity > 95:
|
||||||
|
state.append("charged")
|
||||||
|
else:
|
||||||
|
state.append("charging")
|
||||||
|
|
||||||
|
return state
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
75
.config/i3/bar/bumblebee/modules/battery.py_ori
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays battery status, remaining percentage and charging information.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* battery.device : The device to read information from (defaults to BAT0)
|
||||||
|
* battery.warning : Warning threshold in % of remaining charge (defaults to 20)
|
||||||
|
* battery.critical: Critical threshold in % of remaining charge (defaults to 10)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.capacity)
|
||||||
|
)
|
||||||
|
battery = self.parameter("device", "BAT0")
|
||||||
|
self._path = "/sys/class/power_supply/{}".format(battery)
|
||||||
|
self._capacity = 100
|
||||||
|
self._ac = False
|
||||||
|
|
||||||
|
def capacity(self, widget):
|
||||||
|
if self._ac:
|
||||||
|
return "ac"
|
||||||
|
if self._capacity == -1:
|
||||||
|
return "n/a"
|
||||||
|
return "{:03d}%".format(self._capacity)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._ac = False
|
||||||
|
if not os.path.exists(self._path):
|
||||||
|
self._ac = True
|
||||||
|
self._capacity = 100
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(self._path + "/capacity") as f:
|
||||||
|
self._capacity = int(f.read())
|
||||||
|
except IOError:
|
||||||
|
self._capacity = -1
|
||||||
|
self._capacity = self._capacity if self._capacity < 100 else 100
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
state = []
|
||||||
|
|
||||||
|
if self._capacity < 0:
|
||||||
|
return ["critical", "unknown"]
|
||||||
|
|
||||||
|
if self._capacity < int(self.parameter("critical", 10)):
|
||||||
|
state.append("critical")
|
||||||
|
elif self._capacity < int(self.parameter("warning", 20)):
|
||||||
|
state.append("warning")
|
||||||
|
|
||||||
|
if self._ac:
|
||||||
|
state.append("AC")
|
||||||
|
else:
|
||||||
|
charge = ""
|
||||||
|
with open(self._path + "/status") as f:
|
||||||
|
charge = f.read().strip()
|
||||||
|
if charge == "Discharging":
|
||||||
|
state.append("discharging-{}".format(min([10, 25, 50, 80, 100] , key=lambda i:abs(i-self._capacity))))
|
||||||
|
else:
|
||||||
|
if self._capacity > 95:
|
||||||
|
state.append("charged")
|
||||||
|
else:
|
||||||
|
state.append("charging")
|
||||||
|
|
||||||
|
return state
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
37
.config/i3/bar/bumblebee/modules/brightness.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the brightness of a display
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* xbacklight
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* brightness.step: The amount of increase/decrease on scroll in % (defaults to 2)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.brightness)
|
||||||
|
)
|
||||||
|
self._brightness = 0
|
||||||
|
|
||||||
|
step = self.parameter("step", 2)
|
||||||
|
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.WHEEL_UP,
|
||||||
|
cmd="xbacklight +{}%".format(step))
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.WHEEL_DOWN,
|
||||||
|
cmd="xbacklight -{}%".format(step))
|
||||||
|
|
||||||
|
def brightness(self, widget):
|
||||||
|
return "{:03.0f}%".format(self._brightness)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._brightness = float(bumblebee.util.execute("xbacklight -get"))
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
48
.config/i3/bar/bumblebee/modules/caffeine.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Enable/disable automatic screen locking.
|
||||||
|
|
||||||
|
Requires the following executables:
|
||||||
|
* xset
|
||||||
|
* notify-send
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.caffeine)
|
||||||
|
)
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd=self._toggle
|
||||||
|
)
|
||||||
|
|
||||||
|
def caffeine(self, widget):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if self._active():
|
||||||
|
return "activated"
|
||||||
|
return "deactivated"
|
||||||
|
|
||||||
|
def _active(self):
|
||||||
|
for line in bumblebee.util.execute("xset q").split("\n"):
|
||||||
|
if "timeout" in line:
|
||||||
|
timeout = int(line.split(" ")[4])
|
||||||
|
if timeout == 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _toggle(self, widget):
|
||||||
|
if self._active():
|
||||||
|
bumblebee.util.execute("xset s default")
|
||||||
|
bumblebee.util.execute("notify-send \"Out of coffee\"")
|
||||||
|
else:
|
||||||
|
bumblebee.util.execute("xset s off")
|
||||||
|
bumblebee.util.execute("notify-send \"Consuming caffeine\"")
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
92
.config/i3/bar/bumblebee/modules/cmus.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Displays information about the current song in cmus.
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* cmus-remote
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* cmus.format: Format string for the song information. Tag values can be put in curly brackets (i.e. {artist})
|
||||||
|
"""
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import string
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
from bumblebee.output import scrollable
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = [
|
||||||
|
bumblebee.output.Widget(name="cmus.prev"),
|
||||||
|
bumblebee.output.Widget(name="cmus.main", full_text=self.description),
|
||||||
|
bumblebee.output.Widget(name="cmus.next"),
|
||||||
|
bumblebee.output.Widget(name="cmus.shuffle"),
|
||||||
|
bumblebee.output.Widget(name="cmus.repeat"),
|
||||||
|
]
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
|
||||||
|
engine.input.register_callback(widgets[0], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="cmus-remote -r")
|
||||||
|
engine.input.register_callback(widgets[1], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="cmus-remote -u")
|
||||||
|
engine.input.register_callback(widgets[2], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="cmus-remote -n")
|
||||||
|
engine.input.register_callback(widgets[3], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="cmus-remote -S")
|
||||||
|
engine.input.register_callback(widgets[4], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="cmus-remote -R")
|
||||||
|
|
||||||
|
self._fmt = self.parameter("format", "{artist} - {title} {position}/{duration}")
|
||||||
|
self._status = None
|
||||||
|
self._shuffle = False
|
||||||
|
self._repeat = False
|
||||||
|
self._tags = defaultdict(lambda: '')
|
||||||
|
|
||||||
|
@scrollable
|
||||||
|
def description(self, widget):
|
||||||
|
return string.Formatter().vformat(self._fmt, (), self._tags)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._load_song()
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if widget.name == "cmus.shuffle":
|
||||||
|
return "shuffle-on" if self._shuffle else "shuffle-off"
|
||||||
|
if widget.name == "cmus.repeat":
|
||||||
|
return "repeat-on" if self._repeat else "repeat-off"
|
||||||
|
if widget.name == "cmus.prev":
|
||||||
|
return "prev"
|
||||||
|
if widget.name == "cmus.next":
|
||||||
|
return "next"
|
||||||
|
return self._status
|
||||||
|
|
||||||
|
def _load_song(self):
|
||||||
|
info = ""
|
||||||
|
try:
|
||||||
|
info = bumblebee.util.execute("cmus-remote -Q")
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
self._tags = defaultdict(lambda: '')
|
||||||
|
for line in info.split("\n"):
|
||||||
|
if line.startswith("status"):
|
||||||
|
self._status = line.split(" ", 2)[1]
|
||||||
|
if line.startswith("tag"):
|
||||||
|
key, value = line.split(" ", 2)[1:]
|
||||||
|
self._tags.update({ key: value })
|
||||||
|
for key in ["duration", "position"]:
|
||||||
|
if line.startswith(key):
|
||||||
|
dur = int(line.split(" ")[1])
|
||||||
|
self._tags.update({key:bumblebee.util.durationfmt(dur)})
|
||||||
|
if line.startswith("set repeat "):
|
||||||
|
self._repeat = False if "false" in line else True
|
||||||
|
if line.startswith("set shuffle "):
|
||||||
|
self._shuffle = False if "false" in line else True
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
37
.config/i3/bar/bumblebee/modules/cpu.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays CPU utilization across all CPUs.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* cpu.warning : Warning threshold in % of CPU usage (defaults to 70%)
|
||||||
|
* cpu.critical: Critical threshold in % of CPU usage (defaults to 80%)
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import psutil
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.utilization)
|
||||||
|
)
|
||||||
|
self._utilization = psutil.cpu_percent(percpu=False)
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="gnome-system-monitor")
|
||||||
|
|
||||||
|
def utilization(self, widget):
|
||||||
|
return "{:06.02f}%".format(self._utilization)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._utilization = psutil.cpu_percent(percpu=False)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return self.threshold_state(self._utilization, 70, 80)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
35
.config/i3/bar/bumblebee/modules/datetime.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the current date and time.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* datetime.format: strftime()-compatible formatting string
|
||||||
|
* date.format : alias for datetime.format
|
||||||
|
* time.format : alias for datetime.format
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
import datetime
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
ALIASES = [ "date", "time" ]
|
||||||
|
|
||||||
|
def default_format(module):
|
||||||
|
default = "%x %X"
|
||||||
|
if module == "date":
|
||||||
|
default = "%x"
|
||||||
|
if module == "time":
|
||||||
|
default = "%X"
|
||||||
|
return default
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.get_time)
|
||||||
|
)
|
||||||
|
self._fmt = self.parameter("format", default_format(self.name))
|
||||||
|
|
||||||
|
def get_time(self, widget):
|
||||||
|
return datetime.datetime.now().strftime(self._fmt)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
47
.config/i3/bar/bumblebee/modules/disk.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Shows free diskspace, total diskspace and the percentage of free disk space.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* disk.warning: Warning threshold in % of disk space (defaults to 80%)
|
||||||
|
* disk.critical: Critical threshold in % of disk space (defaults ot 90%)
|
||||||
|
* disk.path: Path to calculate disk usage from (defaults to /)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.diskspace)
|
||||||
|
)
|
||||||
|
self._path = self.parameter("path", "/")
|
||||||
|
self._perc = 0
|
||||||
|
self._used = 0
|
||||||
|
self._size = 0
|
||||||
|
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="termite -e ranger {}".format(self._path))
|
||||||
|
|
||||||
|
def diskspace(self, widget):
|
||||||
|
#return "{} {}/{} ({:05.02f}%)".format(self._path,
|
||||||
|
#bumblebee.util.bytefmt(self._used),
|
||||||
|
#bumblebee.util.bytefmt(self._size), self._perc
|
||||||
|
#)
|
||||||
|
#return "{} {:05.02f}%".format(self._path, self._perc)
|
||||||
|
return "{}".format(bumblebee.util.bytefmt(self._size - self._used))
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
st = os.statvfs(self._path)
|
||||||
|
self._size = st.f_frsize*st.f_blocks
|
||||||
|
self._used = self._size - st.f_frsize*st.f_bavail
|
||||||
|
self._perc = 100.0*self._used/self._size
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return self.threshold_state(self._perc, 90, 95)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
45
.config/i3/bar/bumblebee/modules/disk.py_ori
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Shows free diskspace, total diskspace and the percentage of free disk space.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* disk.warning: Warning threshold in % of disk space (defaults to 80%)
|
||||||
|
* disk.critical: Critical threshold in % of disk space (defaults ot 90%)
|
||||||
|
* disk.path: Path to calculate disk usage from (defaults to /)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.diskspace)
|
||||||
|
)
|
||||||
|
self._path = self.parameter("path", "/")
|
||||||
|
self._perc = 0
|
||||||
|
self._used = 0
|
||||||
|
self._size = 0
|
||||||
|
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="nautilus {}".format(self._path))
|
||||||
|
|
||||||
|
def diskspace(self, widget):
|
||||||
|
return "{} {}/{} ({:05.02f}%)".format(self._path,
|
||||||
|
bumblebee.util.bytefmt(self._used),
|
||||||
|
bumblebee.util.bytefmt(self._size), self._perc
|
||||||
|
)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
st = os.statvfs(self._path)
|
||||||
|
self._size = st.f_blocks * st.f_frsize
|
||||||
|
self._used = (st.f_blocks - st.f_bfree) * st.f_frsize
|
||||||
|
self._perc = 100.0*self._used/self._size
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return self.threshold_state(self._perc, 80, 90)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
80
.config/i3/bar/bumblebee/modules/dnf.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays DNF package update information (<security>/<bugfixes>/<enhancements>/<other>)
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* dnf
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* dnf.interval: Time in seconds between two consecutive update checks (defaulst to 1800)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
def get_dnf_info(widget):
|
||||||
|
try:
|
||||||
|
res = bumblebee.util.execute("dnf updateinfo")
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
security = 0
|
||||||
|
bugfixes = 0
|
||||||
|
enhancements = 0
|
||||||
|
other = 0
|
||||||
|
for line in res.split("\n"):
|
||||||
|
|
||||||
|
if not line.startswith(" "): continue
|
||||||
|
elif "ecurity" in line:
|
||||||
|
for s in line.split():
|
||||||
|
if s.isdigit(): security += int(s)
|
||||||
|
elif "ugfix" in line:
|
||||||
|
for s in line.split():
|
||||||
|
if s.isdigit(): bugfixes += int(s)
|
||||||
|
elif "hancement" in line:
|
||||||
|
for s in line.split():
|
||||||
|
if s.isdigit(): enhancements += int(s)
|
||||||
|
else:
|
||||||
|
for s in line.split():
|
||||||
|
if s.isdigit(): other += int(s)
|
||||||
|
|
||||||
|
widget.set("security", security)
|
||||||
|
widget.set("bugfixes", bugfixes)
|
||||||
|
widget.set("enhancements", enhancements)
|
||||||
|
widget.set("other", other)
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widget = bumblebee.output.Widget(full_text=self.updates)
|
||||||
|
super(Module, self).__init__(engine, config, widget)
|
||||||
|
self._next_check = 0
|
||||||
|
|
||||||
|
def updates(self, widget):
|
||||||
|
result = []
|
||||||
|
for t in ["security", "bugfixes", "enhancements", "other"]:
|
||||||
|
result.append(str(widget.get(t, 0)))
|
||||||
|
return "/".join(result)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
if int(time.time()) < self._next_check:
|
||||||
|
return
|
||||||
|
thread = threading.Thread(target=get_dnf_info, args=(widgets[0],))
|
||||||
|
thread.start()
|
||||||
|
self._next_check = int(time.time()) + self.parameter("interval", 30*60)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
cnt = 0
|
||||||
|
for t in ["security", "bugfixes", "enhancements", "other"]:
|
||||||
|
cnt += widget.get(t, 0)
|
||||||
|
if cnt == 0:
|
||||||
|
return "good"
|
||||||
|
if cnt > 50 or widget.get("security", 0) > 0:
|
||||||
|
return "critical"
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
26
.config/i3/bar/bumblebee/modules/error.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Draws an error widget.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.text)
|
||||||
|
)
|
||||||
|
self._text = ""
|
||||||
|
|
||||||
|
def set(self, text):
|
||||||
|
self._text = text
|
||||||
|
|
||||||
|
def text(self, widget):
|
||||||
|
return self._text
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return ["critical"]
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
58
.config/i3/bar/bumblebee/modules/gpmdp.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays information about the current song in Google Play music player.
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* gpmdp-remote
|
||||||
|
"""
|
||||||
|
|
||||||
|
import string
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = [
|
||||||
|
bumblebee.output.Widget(name="gpmdp.prev"),
|
||||||
|
bumblebee.output.Widget(name="gpmdp.main", full_text=self.description),
|
||||||
|
bumblebee.output.Widget(name="gpmdp.next"),
|
||||||
|
]
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
|
||||||
|
engine.input.register_callback(widgets[0], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="playerctl previous")
|
||||||
|
engine.input.register_callback(widgets[1], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="playerctl play-pause")
|
||||||
|
engine.input.register_callback(widgets[2], button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="playerctl next")
|
||||||
|
|
||||||
|
self._status = None
|
||||||
|
self._tags = None
|
||||||
|
|
||||||
|
def description(self, widget):
|
||||||
|
return self._tags if self._tags else "n/a"
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._load_song()
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if widget.name == "gpmdp.prev":
|
||||||
|
return "prev"
|
||||||
|
if widget.name == "gpmdp.next":
|
||||||
|
return "next"
|
||||||
|
return self._status
|
||||||
|
|
||||||
|
def _load_song(self):
|
||||||
|
info = ""
|
||||||
|
try:
|
||||||
|
info = bumblebee.util.execute("gpmdp-remote current")
|
||||||
|
status = bumblebee.util.execute("gpmdp-remote status")
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
self._status = status.split("\n")[0].lower()
|
||||||
|
self._tags = info.split("\n")[0]
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
21
.config/i3/bar/bumblebee/modules/kernel.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Shows Linux kernel version information"""
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.output)
|
||||||
|
)
|
||||||
|
self._release_name = platform.release()
|
||||||
|
|
||||||
|
def output(self, widget):
|
||||||
|
return self._release_name
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
74
.config/i3/bar/bumblebee/modules/layout.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays and changes the current keyboard layout
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* setxkbmap
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* layout.lang: pipe-separated list of languages to cycle through (e.g. us|rs|de). Default: en
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.layout)
|
||||||
|
)
|
||||||
|
self._languages = self.parameter("lang", "us").split("|")
|
||||||
|
self._idx = 0
|
||||||
|
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd=self._next_keymap)
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE,
|
||||||
|
cmd=self._prev_keymap)
|
||||||
|
|
||||||
|
def _next_keymap(self, event):
|
||||||
|
self._idx = (self._idx + 1) % len(self._languages)
|
||||||
|
self._set_keymap()
|
||||||
|
|
||||||
|
def _prev_keymap(self, event):
|
||||||
|
self._idx = self._idx - 1 if self._idx > 0 else len(self._languages) - 1
|
||||||
|
self._set_keymap()
|
||||||
|
|
||||||
|
def _set_keymap(self):
|
||||||
|
tmp = self._languages[self._idx].split(":")
|
||||||
|
layout = tmp[0]
|
||||||
|
variant = ""
|
||||||
|
if len(tmp) > 1:
|
||||||
|
variant = "-variant {}".format(tmp[1])
|
||||||
|
try:
|
||||||
|
bumblebee.util.execute("setxkbmap -layout {} {}".format(layout, variant))
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def layout(self, widget):
|
||||||
|
try:
|
||||||
|
res = bumblebee.util.execute("setxkbmap -query")
|
||||||
|
except RuntimeError:
|
||||||
|
return "n/a"
|
||||||
|
layout = ""
|
||||||
|
variant = None
|
||||||
|
for line in res.split("\n"):
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
if "layout" in line:
|
||||||
|
layout = line.split(":")[1].strip()
|
||||||
|
if "variant" in line:
|
||||||
|
variant = line.split(":")[1].strip()
|
||||||
|
if variant:
|
||||||
|
layout += ":" + variant
|
||||||
|
|
||||||
|
if layout in self._languages:
|
||||||
|
self._idx = self._languages.index(layout)
|
||||||
|
else:
|
||||||
|
self._languages.append(layout)
|
||||||
|
self._idx = len(self._languages) - 1
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
41
.config/i3/bar/bumblebee/modules/load.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays system load.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* load.warning : Warning threshold for the one-minute load average (defaults to 70% of the number of CPUs)
|
||||||
|
* load.critical: Critical threshold for the one-minute load average (defaults to 80% of the number of CPUs)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.load)
|
||||||
|
)
|
||||||
|
self._load = [0, 0, 0]
|
||||||
|
try:
|
||||||
|
self._cpus = multiprocessing.cpu_count()
|
||||||
|
except NotImplementedError as e:
|
||||||
|
self._cpus = 1
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="gnome-system-monitor")
|
||||||
|
|
||||||
|
def load(self, widget):
|
||||||
|
return "{:.02f}/{:.02f}/{:.02f}".format(
|
||||||
|
self._load[0], self._load[1], self._load[2]
|
||||||
|
)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._load = os.getloadavg()
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return self.threshold_state(self._load[0], self._cpus*0.7, self._cpus*0.8)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
47
.config/i3/bar/bumblebee/modules/memory.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays available RAM, total amount of RAM and percentage available.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* cpu.warning : Warning threshold in % of memory used (defaults to 80%)
|
||||||
|
* cpu.critical: Critical threshold in % of memory used (defaults to 90%)
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import psutil
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.memory_usage)
|
||||||
|
)
|
||||||
|
self._mem = psutil.virtual_memory()
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE,
|
||||||
|
cmd="gnome-system-monitor")
|
||||||
|
|
||||||
|
def memory_usage(self, widget):
|
||||||
|
used = self._mem.total - self._mem.available
|
||||||
|
return "{}/{} ({:05.02f}%)".format(
|
||||||
|
bumblebee.util.bytefmt(used),
|
||||||
|
bumblebee.util.bytefmt(self._mem.total),
|
||||||
|
self._mem.percent
|
||||||
|
)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._mem = psutil.virtual_memory()
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if self._mem.percent > float(self.parameter("critical", 90)):
|
||||||
|
return "critical"
|
||||||
|
if self._mem.percent > float(self.parameter("warning", 80)):
|
||||||
|
return "warning"
|
||||||
|
return None
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
83
.config/i3/bar/bumblebee/modules/nic.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the name, IP address(es) and status of each available network interface.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* nic.exclude: Comma-separated list of interface prefixes to exclude (defaults to "lo,virbr,docker,vboxnet,veth")
|
||||||
|
"""
|
||||||
|
|
||||||
|
import netifaces
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = []
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
self._exclude = tuple(filter(len, self.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(",")))
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
states = []
|
||||||
|
|
||||||
|
if widget.get("state") == "down":
|
||||||
|
states.append("critical")
|
||||||
|
elif widget.get("state") != "up":
|
||||||
|
states.append("warning")
|
||||||
|
else:
|
||||||
|
states.append("good")
|
||||||
|
|
||||||
|
intf = widget.get("intf")
|
||||||
|
iftype = "wireless" if self._iswlan(intf) else "wired"
|
||||||
|
iftype = "tunnel" if self._istunnel(intf) else iftype
|
||||||
|
|
||||||
|
states.append("{}-{}".format(iftype, widget.get("state")))
|
||||||
|
|
||||||
|
return states
|
||||||
|
|
||||||
|
def _iswlan(self, intf):
|
||||||
|
# wifi, wlan, wlp, seems to work for me
|
||||||
|
if intf.startswith("w"): return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _istunnel(self, intf):
|
||||||
|
return intf.startswith("tun")
|
||||||
|
|
||||||
|
def _update_widgets(self, widgets):
|
||||||
|
interfaces = [ i for i in netifaces.interfaces() if not i.startswith(self._exclude) ]
|
||||||
|
|
||||||
|
for widget in widgets:
|
||||||
|
widget.set("visited", False)
|
||||||
|
|
||||||
|
for intf in interfaces:
|
||||||
|
addr = []
|
||||||
|
state = "down"
|
||||||
|
try:
|
||||||
|
if netifaces.AF_INET in netifaces.ifaddresses(intf):
|
||||||
|
for ip in netifaces.ifaddresses(intf)[netifaces.AF_INET]:
|
||||||
|
if "addr" in ip and ip["addr"] != "":
|
||||||
|
addr.append(ip["addr"])
|
||||||
|
state = "up"
|
||||||
|
except Exception as e:
|
||||||
|
addr = []
|
||||||
|
widget = self.widget(intf)
|
||||||
|
if not widget:
|
||||||
|
widget = bumblebee.output.Widget(name=intf)
|
||||||
|
widgets.append(widget)
|
||||||
|
widget.full_text("{}".format(",".join(addr)))
|
||||||
|
#widget.full_text("{} {} {}".format(intf, state, ", ".join(addr)))
|
||||||
|
widget.set("intf", intf)
|
||||||
|
widget.set("state", state)
|
||||||
|
widget.set("visited", True)
|
||||||
|
|
||||||
|
for widget in widgets:
|
||||||
|
if widget.get("visited") == False:
|
||||||
|
widgets.remove(widget)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
88
.config/i3/bar/bumblebee/modules/nic.py_ori
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the name, IP address(es) and status of each available network interface.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* nic.exclude: Comma-separated list of interface prefixes to exclude (defaults to "lo,virbr,docker,vboxnet,veth")
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import netifaces
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = []
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
self._exclude = tuple(filter(len, self.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(",")))
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
states = []
|
||||||
|
|
||||||
|
if widget.get("state") == "down":
|
||||||
|
states.append("critical")
|
||||||
|
elif widget.get("state") != "up":
|
||||||
|
states.append("warning")
|
||||||
|
|
||||||
|
intf = widget.get("intf")
|
||||||
|
iftype = "wireless" if self._iswlan(intf) else "wired"
|
||||||
|
iftype = "tunnel" if self._istunnel(intf) else iftype
|
||||||
|
|
||||||
|
states.append("{}-{}".format(iftype, widget.get("state")))
|
||||||
|
|
||||||
|
return states
|
||||||
|
|
||||||
|
def _iswlan(self, intf):
|
||||||
|
# wifi, wlan, wlp, seems to work for me
|
||||||
|
if intf.startswith("w"): return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _istunnel(self, intf):
|
||||||
|
return intf.startswith("tun")
|
||||||
|
|
||||||
|
def get_addresses(self, intf):
|
||||||
|
retval = []
|
||||||
|
try:
|
||||||
|
for ip in netifaces.ifaddresses(intf).get(netifaces.AF_INET, []):
|
||||||
|
if ip.get("addr", "") != "":
|
||||||
|
retval.append(ip.get("addr"))
|
||||||
|
except Exception:
|
||||||
|
return []
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def _update_widgets(self, widgets):
|
||||||
|
interfaces = [ i for i in netifaces.interfaces() if not i.startswith(self._exclude) ]
|
||||||
|
|
||||||
|
for widget in widgets:
|
||||||
|
widget.set("visited", False)
|
||||||
|
|
||||||
|
for intf in interfaces:
|
||||||
|
addr = []
|
||||||
|
state = "down"
|
||||||
|
for ip in self.get_addresses(intf):
|
||||||
|
addr.append(ip)
|
||||||
|
state = "up"
|
||||||
|
widget = self.widget(intf)
|
||||||
|
if not widget:
|
||||||
|
widget = bumblebee.output.Widget(name=intf)
|
||||||
|
widgets.append(widget)
|
||||||
|
widget.full_text("{} {} {}".format(intf, state, ", ".join(addr)))
|
||||||
|
widget.set("intf", intf)
|
||||||
|
widget.set("state", state)
|
||||||
|
widget.set("visited", True)
|
||||||
|
|
||||||
|
for widget in widgets:
|
||||||
|
if widget.get("visited") == False:
|
||||||
|
widgets.remove(widget)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
70
.config/i3/bar/bumblebee/modules/pacman.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays update information per repository for pacman."
|
||||||
|
|
||||||
|
Requires the following executables:
|
||||||
|
* fakeroot
|
||||||
|
* pacman
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
#list of repositories.
|
||||||
|
#the last one sould always be other
|
||||||
|
repos = ["core", "extra", "community", "multilib", "testing", "other"]
|
||||||
|
|
||||||
|
def get_pacman_info(widget, path):
|
||||||
|
try:
|
||||||
|
result = bumblebee.util.execute("{}/../../bin/pacman-updates".format(path))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
count = len(repos)*[0]
|
||||||
|
|
||||||
|
for line in result.splitlines():
|
||||||
|
if line.startswith(("http", "rsync")):
|
||||||
|
for i in range(len(repos)-1):
|
||||||
|
if "/" + repos[i] + "/" in line:
|
||||||
|
count[i] += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result[-1] += 1
|
||||||
|
|
||||||
|
for i in range(len(repos)):
|
||||||
|
widget.set(repos[i], count[i])
|
||||||
|
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.updates)
|
||||||
|
)
|
||||||
|
self._count = 0
|
||||||
|
|
||||||
|
def updates(self, widget):
|
||||||
|
return '/'.join(map(lambda x: str(widget.get(x,0)), repos))
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
if self._count == 0:
|
||||||
|
thread = threading.Thread(target=get_pacman_info, args=(widgets[0],path))
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
# TODO: improve this waiting mechanism a bit
|
||||||
|
self._count += 1
|
||||||
|
self._count = 0 if self._count > 300 else self._count
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
weightedCount = sum(map(lambda x: (len(repos)-x[0]) * widget.get(x[1],0), enumerate(repos)))
|
||||||
|
|
||||||
|
if weightedCount < 10:
|
||||||
|
return "good"
|
||||||
|
|
||||||
|
return self.threshold_state(weightedCount, 100, 150)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
77
.config/i3/bar/bumblebee/modules/ping.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Periodically checks the RTT of a configurable host using ICMP echos
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* ping
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* ping.interval: Time in seconds between two RTT checks (defaults to 60)
|
||||||
|
* ping.address : IP address to check
|
||||||
|
* ping.timeout : Timeout for waiting for a reply (defaults to 5.0)
|
||||||
|
* ping.probes : Number of probes to send (defaults to 5)
|
||||||
|
* ping.warning : Threshold for warning state, in seconds (defaults to 1.0)
|
||||||
|
* ping.critical: Threshold for critical state, in seconds (defaults to 2.0)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
def get_rtt(module, widget):
|
||||||
|
try:
|
||||||
|
widget.set("rtt-unreachable", False)
|
||||||
|
res = bumblebee.util.execute("ping -n -q -c {} -W {} {}".format(
|
||||||
|
widget.get("rtt-probes"), widget.get("rtt-timeout"), widget.get("address")
|
||||||
|
))
|
||||||
|
|
||||||
|
for line in res.split("\n"):
|
||||||
|
if not line.startswith("rtt"): continue
|
||||||
|
m = re.search(r'([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+)\s+(\S+)', line)
|
||||||
|
|
||||||
|
widget.set("rtt-min", float(m.group(1)))
|
||||||
|
widget.set("rtt-avg", float(m.group(2)))
|
||||||
|
widget.set("rtt-max", float(m.group(3)))
|
||||||
|
widget.set("rtt-unit", m.group(5))
|
||||||
|
except Exception as e:
|
||||||
|
widget.set("rtt-unreachable", True)
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widget = bumblebee.output.Widget(full_text=self.rtt)
|
||||||
|
super(Module, self).__init__(engine, config, widget)
|
||||||
|
|
||||||
|
widget.set("address", self.parameter("address", "8.8.8.8"))
|
||||||
|
widget.set("interval", self.parameter("interval", 60))
|
||||||
|
widget.set("rtt-probes", self.parameter("probes", 5))
|
||||||
|
widget.set("rtt-timeout", self.parameter("timeout", 5.0))
|
||||||
|
widget.set("rtt-avg", 0.0)
|
||||||
|
widget.set("rtt-unit", "")
|
||||||
|
|
||||||
|
self._next_check = 0
|
||||||
|
|
||||||
|
def rtt(self, widget):
|
||||||
|
if widget.get("rtt-unreachable"):
|
||||||
|
return "{}: unreachable".format(widget.get("address"))
|
||||||
|
return "{}: {:.1f}{}".format(
|
||||||
|
widget.get("address"),
|
||||||
|
widget.get("rtt-avg"),
|
||||||
|
widget.get("rtt-unit")
|
||||||
|
)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if widget.get("rtt-unreachable"): return ["critical"]
|
||||||
|
return self.threshold_state(widget.get("rtt-avg"), 1000.0, 2000.0)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
if int(time.time()) < self._next_check:
|
||||||
|
return
|
||||||
|
thread = threading.Thread(target=get_rtt, args=(self,widgets[0],))
|
||||||
|
thread.start()
|
||||||
|
self._next_check = int(time.time()) + int(widgets[0].get("interval"))
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
107
.config/i3/bar/bumblebee/modules/pulseaudio.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays volume and mute status of PulseAudio devices.
|
||||||
|
|
||||||
|
Aliases: pasink, pasource
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* pactl
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
ALIASES = [ "pasink", "pasource" ]
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.volume)
|
||||||
|
)
|
||||||
|
|
||||||
|
self._left = 0
|
||||||
|
self._right = 0
|
||||||
|
self._mono = 0
|
||||||
|
self._mute = False
|
||||||
|
channel = "sink" if self.name == "pasink" else "source"
|
||||||
|
|
||||||
|
self._patterns = [
|
||||||
|
{ "expr": "Name:", "callback": (lambda line: False) },
|
||||||
|
{ "expr": "Mute:", "callback": (lambda line: self.mute(False if " no" in line.lower() else True)) },
|
||||||
|
{ "expr": "Volume:", "callback": self.getvolume },
|
||||||
|
]
|
||||||
|
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE, cmd="pavucontrol")
|
||||||
|
|
||||||
|
events = [
|
||||||
|
{ "type": "mute", "action": "toggle", "button": bumblebee.input.LEFT_MOUSE },
|
||||||
|
{ "type": "volume", "action": "+2%", "button": bumblebee.input.WHEEL_UP },
|
||||||
|
{ "type": "volume", "action": "-2%", "button": bumblebee.input.WHEEL_DOWN },
|
||||||
|
]
|
||||||
|
|
||||||
|
for event in events:
|
||||||
|
engine.input.register_callback(self, button=event["button"],
|
||||||
|
cmd="pactl set-{}-{} @DEFAULT_{}@ {}".format(channel, event["type"],
|
||||||
|
channel.upper(), event["action"]))
|
||||||
|
|
||||||
|
def mute(self, value):
|
||||||
|
self._mute = value
|
||||||
|
|
||||||
|
def getvolume(self, line):
|
||||||
|
if "mono" in line:
|
||||||
|
m = re.search(r'mono:.*\s*\/\s*(\d+)%', line)
|
||||||
|
if m:
|
||||||
|
self._mono = m.group(1)
|
||||||
|
else:
|
||||||
|
m = re.search(r'left:.*\s*\/\s*(\d+)%.*right:.*\s*\/\s*(\d+)%', line)
|
||||||
|
if m:
|
||||||
|
self._left = m.group(1)
|
||||||
|
self._right = m.group(2)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _default_device(self):
|
||||||
|
output = bumblebee.util.execute("pactl info")
|
||||||
|
pattern = "Default Sink: " if self.name == "pasink" else "Default Source: "
|
||||||
|
for line in output.split("\n"):
|
||||||
|
if line.startswith(pattern):
|
||||||
|
return line.replace(pattern, "")
|
||||||
|
return "n/a"
|
||||||
|
|
||||||
|
def volume(self, widget):
|
||||||
|
if int(self._mono) > 0:
|
||||||
|
return "{}%".format(self._mono)
|
||||||
|
elif self._left == self._right:
|
||||||
|
return "{}%".format(self._left)
|
||||||
|
else:
|
||||||
|
return "{}%/{}%".format(self._left, self._right)
|
||||||
|
return "n/a"
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
channel = "sinks" if self.name == "pasink" else "sources"
|
||||||
|
device = self._default_device()
|
||||||
|
|
||||||
|
result = bumblebee.util.execute("pactl list {}".format(channel))
|
||||||
|
found = False
|
||||||
|
|
||||||
|
for line in result.split("\n"):
|
||||||
|
if device in line:
|
||||||
|
found = True
|
||||||
|
continue
|
||||||
|
if found == False:
|
||||||
|
continue
|
||||||
|
for pattern in self._patterns:
|
||||||
|
if not pattern["expr"] in line:
|
||||||
|
continue
|
||||||
|
if pattern["callback"](line) == False and found == True:
|
||||||
|
return
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if self._mute:
|
||||||
|
return [ "warning", "muted" ]
|
||||||
|
return [ "unmuted" ]
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
46
.config/i3/bar/bumblebee/modules/redshift.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the current color temperature of redshift
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* redshift
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.text)
|
||||||
|
)
|
||||||
|
self._text = ""
|
||||||
|
self._state = "transition"
|
||||||
|
|
||||||
|
def text(self, widget):
|
||||||
|
return "{}".format(self._text)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
result = bumblebee.util.execute("redshift -p")
|
||||||
|
|
||||||
|
temp = ""
|
||||||
|
transition = ""
|
||||||
|
for line in result.split("\n"):
|
||||||
|
if "temperature" in line.lower():
|
||||||
|
temp = line.split(" ")[2]
|
||||||
|
if "period" in line.lower():
|
||||||
|
state = line.split(" ")[1].lower()
|
||||||
|
if "day" in state:
|
||||||
|
self._state = "day"
|
||||||
|
elif "night" in state:
|
||||||
|
self._state = "night"
|
||||||
|
else:
|
||||||
|
self._state = "transition"
|
||||||
|
transition = " ".join(line.split(" ")[2:])
|
||||||
|
self._text = "{} {}".format(temp, transition)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
45
.config/i3/bar/bumblebee/modules/sensors.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""Displays sensor temperature
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* sensors
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* sensors.match: What line in the output of `sensors -u` should be matched against (default: temp1_input)
|
||||||
|
* sensors.match_number: which of the matches you want (default -1: last match).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.temperature)
|
||||||
|
)
|
||||||
|
self._temperature = "unknown"
|
||||||
|
pattern = self.parameter("match", "temp1_input")
|
||||||
|
pattern_string = r"^\s*{}:\s*([\d.]+)$".format(pattern)
|
||||||
|
self._match_number = int(self.parameter("match_number", "-1"))
|
||||||
|
self._pattern = re.compile(pattern_string, re.MULTILINE)
|
||||||
|
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, cmd="xsensors")
|
||||||
|
|
||||||
|
def get_temp(self):
|
||||||
|
temperatures = bumblebee.util.execute("sensors -u")
|
||||||
|
matching_temp = self._pattern.findall(temperatures)
|
||||||
|
temperature = "unknown"
|
||||||
|
if matching_temp:
|
||||||
|
temperature = int(float(matching_temp[self._match_number]))
|
||||||
|
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
def temperature(self, widget):
|
||||||
|
return self._temperature
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._temperature = self.get_temp()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
23
.config/i3/bar/bumblebee/modules/spacer.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Draws a widget with configurable text content.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* spacer.text: Widget contents (defaults to empty string)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.text)
|
||||||
|
)
|
||||||
|
self._text = self.parameter("text", "")
|
||||||
|
|
||||||
|
def text(self, widget):
|
||||||
|
return self._text
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
62
.config/i3/bar/bumblebee/modules/stock.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Display a stock quote from yahoo finance.
|
||||||
|
|
||||||
|
Requires the following python packages:
|
||||||
|
* requests
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* stock.symbols : Comma-separated list of symbols to fetch
|
||||||
|
* stock.change : Should we fetch change in stock value (defaults to True)
|
||||||
|
* stock.currencies : List of symbols to go with the values (default $)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
import requests
|
||||||
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.value)
|
||||||
|
)
|
||||||
|
self._symbols = self.parameter("symbols", "")
|
||||||
|
self._change = self.parameter("change", True)
|
||||||
|
self._currencies = self.parameter('currencies', None)
|
||||||
|
self._baseurl = 'http://download.finance.yahoo.com/d/quotes.csv'
|
||||||
|
self._value = self.fetch()
|
||||||
|
|
||||||
|
if not self._currencies:
|
||||||
|
self._currencies = '$' * len(self._symbols)
|
||||||
|
|
||||||
|
# The currencies could be unicode, like the € symbol. Convert to a unicode object.
|
||||||
|
if hasattr(self._currencies, "decode"):
|
||||||
|
self._currencies = self._currencies.decode("utf-8", "ignore")
|
||||||
|
|
||||||
|
def value(self, widget):
|
||||||
|
results = []
|
||||||
|
for i, val in enumerate(self._value.split('\n')):
|
||||||
|
try:
|
||||||
|
currency_symbol = self._currencies[i]
|
||||||
|
except:
|
||||||
|
currency_symbol = '$'
|
||||||
|
results.append('%s%s' % (currency_symbol, val))
|
||||||
|
return u' '.join(results)
|
||||||
|
|
||||||
|
def fetch(self):
|
||||||
|
if self._symbols:
|
||||||
|
url = self._baseurl
|
||||||
|
url += '?s=%s&f=l1' % self._symbols
|
||||||
|
if self._change:
|
||||||
|
url += 'c1'
|
||||||
|
return requests.get(url).text.strip()
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._value = self.fetch()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
16
.config/i3/bar/bumblebee/modules/test.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Test module
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
ALIASES = [ "test-alias" ]
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text="test")
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
72
.config/i3/bar/bumblebee/modules/traffic.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays network IO for interfaces.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* traffic.exclude: Comma-separated list of interface prefixes to exclude (defaults to "lo,virbr,docker,vboxnet,veth")
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import psutil
|
||||||
|
import netifaces
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = []
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
self._exclude = tuple(filter(len, self.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(",")))
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
self._status = ""
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
if "traffic.rx" in widget.name:
|
||||||
|
return "rx"
|
||||||
|
if "traffic.tx" in widget.name:
|
||||||
|
return "tx"
|
||||||
|
return self._status
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self._update_widgets(widgets)
|
||||||
|
|
||||||
|
def create_widget(self, widgets, name, txt=None, attributes={}):
|
||||||
|
widget = self.widget(name)
|
||||||
|
if widget: return widget
|
||||||
|
|
||||||
|
widget = bumblebee.output.Widget(name=name)
|
||||||
|
widget.full_text(txt)
|
||||||
|
widgets.append(widget)
|
||||||
|
|
||||||
|
for key in attributes:
|
||||||
|
widget.set(key, attributes[key])
|
||||||
|
|
||||||
|
return widget
|
||||||
|
|
||||||
|
def _update_widgets(self, widgets):
|
||||||
|
interfaces = [ i for i in netifaces.interfaces() if not i.startswith(self._exclude) ]
|
||||||
|
|
||||||
|
counters = psutil.net_io_counters(pernic=True)
|
||||||
|
for interface in interfaces:
|
||||||
|
if not interface: interface = "lo"
|
||||||
|
data = {
|
||||||
|
"rx": counters[interface].bytes_recv,
|
||||||
|
"tx": counters[interface].bytes_sent,
|
||||||
|
}
|
||||||
|
|
||||||
|
name = "traffic-{}".format(interface)
|
||||||
|
|
||||||
|
self.create_widget(widgets, name, interface)
|
||||||
|
|
||||||
|
for direction in ["rx", "tx"]:
|
||||||
|
name = "traffic.{}-{}".format(direction, interface)
|
||||||
|
widget = self.create_widget(widgets, name, attributes={"theme.minwidth": "1000.00MB"})
|
||||||
|
prev = widget.get(direction, 0)
|
||||||
|
speed = bumblebee.util.bytefmt(int(data[direction]) - int(prev))
|
||||||
|
widget.full_text(speed)
|
||||||
|
widget.set(direction, data[direction])
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
74
.config/i3/bar/bumblebee/modules/weather.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Displays the temperature on the current location based on the ip
|
||||||
|
|
||||||
|
Requires the following python packages:
|
||||||
|
* requests
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
* weather.interval: Interval (in minutes) for updating weather information
|
||||||
|
* weather.location: Set location (ISO 3166 country code), defaults to 'auto' for getting location from http://ipinfo.io
|
||||||
|
* weather.unit: metric (default), kelvin, imperial
|
||||||
|
* weather.apikey: API key from http://api.openweathermap.org
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
from requests.exceptions import RequestException
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
super(Module, self).__init__(engine, config,
|
||||||
|
bumblebee.output.Widget(full_text=self.temperature)
|
||||||
|
)
|
||||||
|
self._temperature = 0
|
||||||
|
self._apikey = self.parameter("apikey", "af7bfe22287c652d032a3064ffa44088")
|
||||||
|
self._location = self.parameter("location", "auto")
|
||||||
|
self._interval = int(self.parameter("interval", "15"))
|
||||||
|
self._unit = self.parameter("unit", "metric")
|
||||||
|
self._nextcheck = 0
|
||||||
|
self._valid = False
|
||||||
|
|
||||||
|
def _unit_suffix(self):
|
||||||
|
if self._unit == "metric":
|
||||||
|
return "C"
|
||||||
|
if self._unit == "kelvin":
|
||||||
|
return "K"
|
||||||
|
if self._unit == "imperial":
|
||||||
|
return "F"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def temperature(self, widget):
|
||||||
|
if not self._valid:
|
||||||
|
return u"?"
|
||||||
|
return u"{}°{}".format(self._temperature, self._unit_suffix())
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
timestamp = int(time.time())
|
||||||
|
if self._nextcheck < int(time.time()):
|
||||||
|
try:
|
||||||
|
self._nextcheck = int(time.time()) + self._interval*60
|
||||||
|
weather_url = "http://api.openweathermap.org/data/2.5/weather?appid={}".format(self._apikey)
|
||||||
|
weather_url = "{}&units={}".format(weather_url, self._unit)
|
||||||
|
if self._location == "auto":
|
||||||
|
location_url = "http://ipinfo.io/json"
|
||||||
|
location = json.loads(requests.get(location_url).text)
|
||||||
|
coord = location["loc"].split(",")
|
||||||
|
weather_url = "{url}&lat={lat}&lon={lon}".format(url=weather_url, lat=coord[0], lon=coord[1])
|
||||||
|
else:
|
||||||
|
weather_url = "{url}&q={city}".format(url=weather_url, city=self._location)
|
||||||
|
weather = json.loads(requests.get(weather_url).text)
|
||||||
|
self._temperature = int(weather['main']['temp'])
|
||||||
|
self._valid = True
|
||||||
|
except RequestException:
|
||||||
|
self._valid = False
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
74
.config/i3/bar/bumblebee/modules/xrandr.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# pylint: disable=C0111,R0903
|
||||||
|
|
||||||
|
"""Shows a widget for each connected screen and allows the user to enable/disable screens.
|
||||||
|
|
||||||
|
Requires the following executable:
|
||||||
|
* xrandr
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import bumblebee.util
|
||||||
|
import bumblebee.input
|
||||||
|
import bumblebee.output
|
||||||
|
import bumblebee.engine
|
||||||
|
|
||||||
|
class Module(bumblebee.engine.Module):
|
||||||
|
def __init__(self, engine, config):
|
||||||
|
widgets = []
|
||||||
|
self._engine = engine
|
||||||
|
super(Module, self).__init__(engine, config, widgets)
|
||||||
|
self.update_widgets(widgets)
|
||||||
|
|
||||||
|
def update_widgets(self, widgets):
|
||||||
|
new_widgets = []
|
||||||
|
for line in bumblebee.util.execute("xrandr -q").split("\n"):
|
||||||
|
if not " connected" in line:
|
||||||
|
continue
|
||||||
|
display = line.split(" ", 2)[0]
|
||||||
|
m = re.search(r'\d+x\d+\+(\d+)\+\d+', line)
|
||||||
|
|
||||||
|
widget = self.widget(display)
|
||||||
|
if not widget:
|
||||||
|
widget = bumblebee.output.Widget(full_text=display, name=display)
|
||||||
|
self._engine.input.register_callback(widget, button=1, cmd=self._toggle)
|
||||||
|
self._engine.input.register_callback(widget, button=3, cmd=self._toggle)
|
||||||
|
new_widgets.append(widget)
|
||||||
|
widget.set("state", "on" if m else "off")
|
||||||
|
widget.set("pos", int(m.group(1)) if m else sys.maxsize)
|
||||||
|
|
||||||
|
while len(widgets) > 0:
|
||||||
|
del widgets[0]
|
||||||
|
for widget in new_widgets:
|
||||||
|
widgets.append(widget)
|
||||||
|
|
||||||
|
def update(self, widgets):
|
||||||
|
self.update_widgets(widgets)
|
||||||
|
|
||||||
|
def state(self, widget):
|
||||||
|
return widget.get("state", "off")
|
||||||
|
|
||||||
|
def _toggle(self, event):
|
||||||
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
toggle_cmd = "{}/../../bin/toggle-display.sh".format(path)
|
||||||
|
|
||||||
|
widget = self.widget_by_id(event["instance"])
|
||||||
|
|
||||||
|
if widget.get("state") == "on":
|
||||||
|
bumblebee.util.execute("{} --output {} --off".format(toggle_cmd, widget.name))
|
||||||
|
else:
|
||||||
|
first_neighbor = next((widget for widget in self.widgets() if widget.get("state") == "on"), None)
|
||||||
|
last_neighbor = next((widget for widget in reversed(self.widgets()) if widget.get("state") == "on"), None)
|
||||||
|
|
||||||
|
neighbor = first_neighbor if event["button"] == bumblebee.input.LEFT_MOUSE else last_neighbor
|
||||||
|
|
||||||
|
if neighbor == None:
|
||||||
|
bumblebee.util.execute("{} --output {} --auto".format(toggle_cmd, widget.name))
|
||||||
|
else:
|
||||||
|
bumblebee.util.execute("{} --output {} --auto --{}-of {}".format(toggle_cmd, widget.name,
|
||||||
|
"left" if event.get("button") == bumblebee.input.LEFT_MOUSE else "right",
|
||||||
|
neighbor.name))
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
140
.config/i3/bar/bumblebee/output.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# pylint: disable=R0201
|
||||||
|
|
||||||
|
"""Output classes"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import bumblebee.store
|
||||||
|
|
||||||
|
def scrollable(func):
|
||||||
|
def wrapper(module, widget):
|
||||||
|
text = func(module, widget)
|
||||||
|
width = widget.get("theme.width", module.parameter("width", 30))
|
||||||
|
widget.set("theme.minwidth", "A"*width)
|
||||||
|
if len(text) <= width:
|
||||||
|
return text
|
||||||
|
# we need to shorten
|
||||||
|
start = widget.get("scrolling.start", -1)
|
||||||
|
direction = widget.get("scrolling.direction", "right")
|
||||||
|
start += 1 if direction == "right" else -1
|
||||||
|
widget.set("scrolling.start", start)
|
||||||
|
if width + start >= len(text):
|
||||||
|
widget.set("scrolling.direction", "left")
|
||||||
|
if start <= 0:
|
||||||
|
widget.set("scrolling.direction", "right")
|
||||||
|
text = text[start:width+start]
|
||||||
|
|
||||||
|
return text
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
class Widget(bumblebee.store.Store):
|
||||||
|
"""Represents a single visible block in the status bar"""
|
||||||
|
def __init__(self, full_text="", name=""):
|
||||||
|
super(Widget, self).__init__()
|
||||||
|
self._full_text = full_text
|
||||||
|
self.module = None
|
||||||
|
self._module = None
|
||||||
|
self.name = name
|
||||||
|
self.id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
def link_module(self, module):
|
||||||
|
"""Set the module that spawned this widget
|
||||||
|
|
||||||
|
This is done outside the constructor to avoid having to
|
||||||
|
pass in the module name in every concrete module implementation"""
|
||||||
|
self.module = module.name
|
||||||
|
self._module = module
|
||||||
|
|
||||||
|
def cls(self):
|
||||||
|
if not self._module:
|
||||||
|
return None
|
||||||
|
return self._module.__module__.replace("bumblebee.modules.", "")
|
||||||
|
|
||||||
|
def state(self):
|
||||||
|
"""Return the widget's state"""
|
||||||
|
if self._module and hasattr(self._module, "state"):
|
||||||
|
states = self._module.state(self)
|
||||||
|
if not isinstance(states, list):
|
||||||
|
return [states]
|
||||||
|
return states
|
||||||
|
return []
|
||||||
|
|
||||||
|
def full_text(self, value=None):
|
||||||
|
"""Set or retrieve the full text to display in the widget"""
|
||||||
|
if value:
|
||||||
|
self._full_text = value
|
||||||
|
else:
|
||||||
|
if callable(self._full_text):
|
||||||
|
return self._full_text(self)
|
||||||
|
else:
|
||||||
|
return self._full_text
|
||||||
|
|
||||||
|
class I3BarOutput(object):
|
||||||
|
"""Manage output according to the i3bar protocol"""
|
||||||
|
def __init__(self, theme):
|
||||||
|
self._theme = theme
|
||||||
|
self._widgets = []
|
||||||
|
self._started = False
|
||||||
|
|
||||||
|
def started(self):
|
||||||
|
return self._started
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Print start preamble for i3bar protocol"""
|
||||||
|
self._started = True
|
||||||
|
sys.stdout.write(json.dumps({"version": 1, "click_events": True}) + "\n[\n")
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Finish i3bar protocol"""
|
||||||
|
sys.stdout.write("]\n")
|
||||||
|
|
||||||
|
def draw(self, widget, module=None, engine=None):
|
||||||
|
"""Draw a single widget"""
|
||||||
|
full_text = widget.full_text()
|
||||||
|
padding = self._theme.padding(widget)
|
||||||
|
prefix = self._theme.prefix(widget, padding)
|
||||||
|
suffix = self._theme.suffix(widget, padding)
|
||||||
|
minwidth = self._theme.minwidth(widget)
|
||||||
|
if prefix:
|
||||||
|
full_text = u"{}{}".format(prefix, full_text)
|
||||||
|
if suffix:
|
||||||
|
full_text = u"{}{}".format(full_text, suffix)
|
||||||
|
separator = self._theme.separator(widget)
|
||||||
|
if separator:
|
||||||
|
self._widgets.append({
|
||||||
|
u"full_text": separator,
|
||||||
|
"separator": False,
|
||||||
|
"color": self._theme.separator_fg(widget),
|
||||||
|
"background": self._theme.separator_bg(widget),
|
||||||
|
"separator_block_width": self._theme.separator_block_width(widget),
|
||||||
|
})
|
||||||
|
width = self._theme.minwidth(widget)
|
||||||
|
self._widgets.append({
|
||||||
|
u"full_text": full_text,
|
||||||
|
"color": self._theme.fg(widget),
|
||||||
|
"background": self._theme.bg(widget),
|
||||||
|
"separator_block_width": self._theme.separator_block_width(widget),
|
||||||
|
"separator": True if separator is None else False,
|
||||||
|
"min_width": width + "A"*(len(prefix) + len(suffix)) if width else None,
|
||||||
|
"align": self._theme.align(widget),
|
||||||
|
"instance": widget.id,
|
||||||
|
"name": module.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
def begin(self):
|
||||||
|
"""Start one output iteration"""
|
||||||
|
self._widgets = []
|
||||||
|
self._theme.reset()
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
"""Flushes output"""
|
||||||
|
sys.stdout.write(json.dumps(self._widgets))
|
||||||
|
|
||||||
|
def end(self):
|
||||||
|
"""Finalizes output"""
|
||||||
|
sys.stdout.write(",\n")
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
21
.config/i3/bar/bumblebee/store.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"""Store interface
|
||||||
|
|
||||||
|
Allows arbitrary classes to offer a simple get/set
|
||||||
|
store interface by deriving from the Store class in
|
||||||
|
this module
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Store(object):
|
||||||
|
"""Interface for storing and retrieving simple values"""
|
||||||
|
def __init__(self):
|
||||||
|
self._data = {}
|
||||||
|
|
||||||
|
def set(self, key, value):
|
||||||
|
"""Set 'key' to 'value', overwriting 'key' if it exists already"""
|
||||||
|
self._data[key] = value
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
"""Return the current value of 'key', or 'default' if 'key' is not set"""
|
||||||
|
return self._data.get(key, default)
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
180
.config/i3/bar/bumblebee/theme.py
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# pylint: disable=C0103
|
||||||
|
|
||||||
|
"""Theme support"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import copy
|
||||||
|
import json
|
||||||
|
import io
|
||||||
|
|
||||||
|
import bumblebee.error
|
||||||
|
|
||||||
|
def theme_path():
|
||||||
|
"""Return the path of the theme directory"""
|
||||||
|
return os.path.dirname("{}/../themes/".format(os.path.dirname(os.path.realpath(__file__))))
|
||||||
|
|
||||||
|
def themes():
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for filename in glob.iglob("{}/*.json".format(theme_path())):
|
||||||
|
if "test" not in filename:
|
||||||
|
result.append(os.path.basename(filename).replace(".json", ""))
|
||||||
|
return result
|
||||||
|
|
||||||
|
class Theme(object):
|
||||||
|
"""Represents a collection of icons and colors"""
|
||||||
|
def __init__(self, name):
|
||||||
|
self._init(self.load(name))
|
||||||
|
self._widget = None
|
||||||
|
self._cycle_idx = 0
|
||||||
|
self._cycle = {}
|
||||||
|
self._prevbg = None
|
||||||
|
|
||||||
|
def _init(self, data):
|
||||||
|
"""Initialize theme from data structure"""
|
||||||
|
for iconset in data.get("icons", []):
|
||||||
|
self._merge(data, self._load_icons(iconset))
|
||||||
|
self._theme = data
|
||||||
|
self._defaults = data.get("defaults", {})
|
||||||
|
self._cycles = self._theme.get("cycle", [])
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def data(self):
|
||||||
|
"""Return the raw theme data"""
|
||||||
|
return self._theme
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Reset theme to initial state"""
|
||||||
|
self._cycle = self._cycles[0] if len(self._cycles) > 0 else {}
|
||||||
|
self._cycle_idx = 0
|
||||||
|
self._widget = None
|
||||||
|
self._prevbg = None
|
||||||
|
|
||||||
|
def padding(self, widget):
|
||||||
|
"""Return padding for widget"""
|
||||||
|
return self._get(widget, "padding", "")
|
||||||
|
|
||||||
|
def prefix(self, widget, default=None):
|
||||||
|
"""Return the theme prefix for a widget's full text"""
|
||||||
|
padding = self.padding(widget)
|
||||||
|
pre = self._get(widget, "prefix", None)
|
||||||
|
return u"{}{}{}".format(padding, pre, padding) if pre else default
|
||||||
|
|
||||||
|
def suffix(self, widget, default=None):
|
||||||
|
"""Return the theme suffix for a widget's full text"""
|
||||||
|
padding = self._get(widget, "padding", "")
|
||||||
|
suf = self._get(widget, "suffix", None)
|
||||||
|
return u"{}{}{}".format(padding, suf, padding) if suf else default
|
||||||
|
|
||||||
|
def fg(self, widget):
|
||||||
|
"""Return the foreground color for this widget"""
|
||||||
|
return self._get(widget, "fg", None)
|
||||||
|
|
||||||
|
def bg(self, widget):
|
||||||
|
"""Return the background color for this widget"""
|
||||||
|
return self._get(widget, "bg", None)
|
||||||
|
|
||||||
|
def align(self, widget):
|
||||||
|
"""Return the widget alignment"""
|
||||||
|
return self._get(widget, "align", None)
|
||||||
|
|
||||||
|
def minwidth(self, widget):
|
||||||
|
"""Return the minimum width string for this widget"""
|
||||||
|
return self._get(widget, "minwidth", "")
|
||||||
|
|
||||||
|
def separator(self, widget):
|
||||||
|
"""Return the separator between widgets"""
|
||||||
|
return self._get(widget, "separator", None)
|
||||||
|
|
||||||
|
def separator_fg(self, widget):
|
||||||
|
"""Return the separator's foreground/text color"""
|
||||||
|
return self.bg(widget)
|
||||||
|
|
||||||
|
def separator_bg(self, widget):
|
||||||
|
"""Return the separator's background color"""
|
||||||
|
return self._prevbg
|
||||||
|
|
||||||
|
def separator_block_width(self, widget):
|
||||||
|
"""Return the SBW"""
|
||||||
|
return self._get(widget, "separator-block-width", None)
|
||||||
|
|
||||||
|
def _load_icons(self, name):
|
||||||
|
"""Load icons for a theme"""
|
||||||
|
path = "{}/icons/".format(theme_path())
|
||||||
|
return self.load(name, path=path)
|
||||||
|
|
||||||
|
def load(self, name, path=theme_path()):
|
||||||
|
"""Load and parse a theme file"""
|
||||||
|
themefile = "{}/{}.json".format(path, name)
|
||||||
|
|
||||||
|
if os.path.isfile(themefile):
|
||||||
|
try:
|
||||||
|
with io.open(themefile,encoding="utf-8") as data:
|
||||||
|
return json.load(data)
|
||||||
|
except ValueError as exception:
|
||||||
|
raise bumblebee.error.ThemeLoadError("JSON error: {}".format(exception))
|
||||||
|
else:
|
||||||
|
raise bumblebee.error.ThemeLoadError("no such theme: {}".format(name))
|
||||||
|
|
||||||
|
def _get(self, widget, name, default=None):
|
||||||
|
"""Return the config value 'name' for 'widget'"""
|
||||||
|
|
||||||
|
if not self._widget:
|
||||||
|
self._widget = widget
|
||||||
|
|
||||||
|
if self._widget != widget:
|
||||||
|
self._prevbg = self.bg(self._widget)
|
||||||
|
self._widget = widget
|
||||||
|
if len(self._cycles) > 0:
|
||||||
|
self._cycle_idx = (self._cycle_idx + 1) % len(self._cycles)
|
||||||
|
self._cycle = self._cycles[self._cycle_idx]
|
||||||
|
|
||||||
|
module_theme = self._theme.get(widget.module, {})
|
||||||
|
class_theme = self._theme.get(widget.cls(), {})
|
||||||
|
|
||||||
|
state_themes = []
|
||||||
|
# avoid infinite recursion
|
||||||
|
states = widget.state()
|
||||||
|
if name not in states:
|
||||||
|
for state in states:
|
||||||
|
state_themes.append(self._get(widget, state, {}))
|
||||||
|
|
||||||
|
value = self._defaults.get(name, default)
|
||||||
|
value = widget.get("theme.{}".format(name), value)
|
||||||
|
value = self._cycle.get(name, value)
|
||||||
|
value = class_theme.get(name, value)
|
||||||
|
value = module_theme.get(name, value)
|
||||||
|
|
||||||
|
for theme in state_themes:
|
||||||
|
value = theme.get(name, value)
|
||||||
|
|
||||||
|
if isinstance(value, list):
|
||||||
|
key = "{}-idx".format(name)
|
||||||
|
idx = widget.get(key, 0)
|
||||||
|
widget.set(key, (idx + 1) % len(value))
|
||||||
|
value = value[idx]
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
# algorithm copied from
|
||||||
|
# http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts
|
||||||
|
# nicely done :)
|
||||||
|
def _merge(self, target, *args):
|
||||||
|
"""Merge two arbitrarily nested data structures"""
|
||||||
|
if len(args) > 1:
|
||||||
|
for item in args:
|
||||||
|
self._merge(item)
|
||||||
|
return target
|
||||||
|
|
||||||
|
item = args[0]
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
return item
|
||||||
|
for key, value in item.items():
|
||||||
|
if key in target and isinstance(target[key], dict):
|
||||||
|
self._merge(target[key], value)
|
||||||
|
else:
|
||||||
|
target[key] = copy.deepcopy(value)
|
||||||
|
return target
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
47
.config/i3/bar/bumblebee/util.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import shlex
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
try:
|
||||||
|
from exceptions import RuntimeError
|
||||||
|
except ImportError:
|
||||||
|
# Python3 doesn't require this anymore
|
||||||
|
pass
|
||||||
|
|
||||||
|
def execute(cmd, wait=True):
|
||||||
|
logging.info("executing command '{}'".format(cmd))
|
||||||
|
args = shlex.split(cmd)
|
||||||
|
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
rv = None
|
||||||
|
|
||||||
|
if wait:
|
||||||
|
out, _ = proc.communicate()
|
||||||
|
if proc.returncode != 0:
|
||||||
|
raise RuntimeError("{} exited with {}".format(cmd, proc.returncode))
|
||||||
|
|
||||||
|
if hasattr(out, "decode"):
|
||||||
|
rv = out.decode("utf-8")
|
||||||
|
else:
|
||||||
|
rv = out
|
||||||
|
|
||||||
|
logging.info(u"command returned '{}'".format("" if not rv else rv))
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def bytefmt(num):
|
||||||
|
for unit in [ "", "Ki", "Mi", "Gi" ]:
|
||||||
|
if num < 1024.0:
|
||||||
|
return "{:.2f}{}B".format(num, unit)
|
||||||
|
num /= 1024.0
|
||||||
|
return "{:.2f}GiB".format(num*1024.0)
|
||||||
|
|
||||||
|
def durationfmt(duration):
|
||||||
|
minutes, seconds = divmod(duration, 60)
|
||||||
|
hours, minutes = divmod(minutes, 60)
|
||||||
|
res = "{:02d}:{:02d}".format(minutes, seconds)
|
||||||
|
if hours > 0: res = "{:02d}:{}".format(hours, res)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
3
.config/i3/bar/runlint.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
find . -name "*.py"|xargs pylint --disable=R0903,R0201,C0330
|
||||||
11
.config/i3/bar/runtests.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "testing with $(python2 -V 2>&1)"
|
||||||
|
python2 $(which nosetests) --rednose -v --with-coverage --cover-erase tests/
|
||||||
|
|
||||||
|
if [ $? == 0 ]; then
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "testing with $(python3 -V 2>&1)"
|
||||||
|
python3 $(which nosetests-3) --rednose -v --with-coverage --cover-erase tests/
|
||||||
|
fi
|
||||||
BIN
.config/i3/bar/screenshots/amixer.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
.config/i3/bar/screenshots/battery.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
.config/i3/bar/screenshots/brightness.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
.config/i3/bar/screenshots/caffeine.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
.config/i3/bar/screenshots/cmus.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
.config/i3/bar/screenshots/cpu.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
.config/i3/bar/screenshots/date.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
.config/i3/bar/screenshots/datetime.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
.config/i3/bar/screenshots/disk.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
.config/i3/bar/screenshots/dnf.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
.config/i3/bar/screenshots/kernel.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |