From ef6928d257192d54d867db9155bcbe127a5eddd6 Mon Sep 17 00:00:00 2001 From: Aleksander Cynarski Date: Sat, 12 Jan 2019 18:22:02 +0100 Subject: [PATCH] initial --- .exports.example | 24 + .gitconfig | 24 + .gitignore | 15 + .signature | 6 + .taskrc | 34 + .thymerc | 42 + .tmux.conf | 96 ++ .zshrc | 156 ++ README.md | 18 + bin/bash2048.sh | 365 +++++ bin/changelog | 18 + bin/christtree.sh | 66 + bin/crpass | 3 + bin/gogs | 366 +++++ bin/jsawk | 1326 +++++++++++++++++ bin/make_archive | 14 + bin/pipes.sh | 121 ++ nvim/init.vim | 344 +++++ tmux/powerline/AUTHORS | 34 + tmux/powerline/LICENSE | 14 + tmux/powerline/README.md | 209 +++ tmux/powerline/color_palette.sh | 14 + tmux/powerline/config/defaults.sh | 5 + tmux/powerline/config/helpers.sh | 9 + tmux/powerline/config/paths.sh | 14 + tmux/powerline/config/shell.sh | 20 + tmux/powerline/generate_rc.sh | 12 + tmux/powerline/img/full.png | Bin 0 -> 12243 bytes tmux/powerline/img/left-status.png | Bin 0 -> 2210 bytes tmux/powerline/img/right-status.png | Bin 0 -> 2335 bytes tmux/powerline/img/right-status_no_mail.png | Bin 0 -> 1933 bytes tmux/powerline/img/right-status_no_mpd.png | Bin 0 -> 1561 bytes .../img/right-status_weather_battery.png | Bin 0 -> 1625 bytes tmux/powerline/lib/arg_processing.sh | 9 + tmux/powerline/lib/formatting.sh | 5 + tmux/powerline/lib/muting.sh | 20 + tmux/powerline/lib/powerline.sh | 142 ++ tmux/powerline/lib/rcfile.sh | 68 + tmux/powerline/lib/text_roll.sh | 63 + tmux/powerline/lib/tmux_adapter.sh | 12 + tmux/powerline/mute_powerline.sh | 10 + tmux/powerline/powerline.sh | 22 + tmux/powerline/segments/Makefile | 18 + tmux/powerline/segments/battery.sh | 150 ++ tmux/powerline/segments/cpu.sh | 22 + tmux/powerline/segments/date.sh | 23 + tmux/powerline/segments/date_day.sh | 6 + tmux/powerline/segments/earthquake.sh | 173 +++ tmux/powerline/segments/hostname.sh | 31 + tmux/powerline/segments/ifstat.sh | 39 + tmux/powerline/segments/ifstat_sys.sh | 42 + tmux/powerline/segments/lan_ip.sh | 32 + tmux/powerline/segments/load.sh | 6 + tmux/powerline/segments/mailcount.sh | 204 +++ .../segments/mailcount_apple_mail.script | 14 + tmux/powerline/segments/now_playing.sh | 297 ++++ tmux/powerline/segments/np_itunes.script | 24 + tmux/powerline/segments/np_mpd.c | 179 +++ tmux/powerline/segments/np_pithos.py | 9 + tmux/powerline/segments/np_rdio_mac.script | 20 + tmux/powerline/segments/np_spotify_mac.script | 27 + tmux/powerline/segments/pwd.sh | 39 + tmux/powerline/segments/rainbarf.sh | 16 + tmux/powerline/segments/thyme.sh | 9 + tmux/powerline/segments/time.sh | 23 + tmux/powerline/segments/tmux_mem_cpu_load.sh | 14 + tmux/powerline/segments/tmux_session_info.sh | 7 + tmux/powerline/segments/uptime.sh | 30 + tmux/powerline/segments/utc_time.sh | 6 + tmux/powerline/segments/vcs_branch.sh | 90 ++ tmux/powerline/segments/vcs_compare.sh | 71 + tmux/powerline/segments/vcs_modified.sh | 70 + tmux/powerline/segments/vcs_others.sh | 51 + tmux/powerline/segments/vcs_revision.sh | 43 + tmux/powerline/segments/vcs_staged.sh | 57 + tmux/powerline/segments/wan_ip.sh | 43 + tmux/powerline/segments/weather.sh | 191 +++ tmux/powerline/segments/xkb_layout.c | 64 + tmux/powerline/segments/xkb_layout.sh | 32 + tmux/powerline/themes/default.sh | 58 + tmux/powerline/themes/paramah.sh | 59 + 81 files changed, 6009 insertions(+) create mode 100644 .exports.example create mode 100644 .gitconfig create mode 100644 .gitignore create mode 100644 .signature create mode 100644 .taskrc create mode 100644 .thymerc create mode 100644 .tmux.conf create mode 100644 .zshrc create mode 100644 README.md create mode 100755 bin/bash2048.sh create mode 100755 bin/changelog create mode 100755 bin/christtree.sh create mode 100755 bin/crpass create mode 100755 bin/gogs create mode 100755 bin/jsawk create mode 100755 bin/make_archive create mode 100755 bin/pipes.sh create mode 100644 nvim/init.vim create mode 100644 tmux/powerline/AUTHORS create mode 100644 tmux/powerline/LICENSE create mode 100644 tmux/powerline/README.md create mode 100755 tmux/powerline/color_palette.sh create mode 100644 tmux/powerline/config/defaults.sh create mode 100644 tmux/powerline/config/helpers.sh create mode 100644 tmux/powerline/config/paths.sh create mode 100644 tmux/powerline/config/shell.sh create mode 100755 tmux/powerline/generate_rc.sh create mode 100644 tmux/powerline/img/full.png create mode 100644 tmux/powerline/img/left-status.png create mode 100644 tmux/powerline/img/right-status.png create mode 100644 tmux/powerline/img/right-status_no_mail.png create mode 100644 tmux/powerline/img/right-status_no_mpd.png create mode 100644 tmux/powerline/img/right-status_weather_battery.png create mode 100644 tmux/powerline/lib/arg_processing.sh create mode 100644 tmux/powerline/lib/formatting.sh create mode 100644 tmux/powerline/lib/muting.sh create mode 100644 tmux/powerline/lib/powerline.sh create mode 100644 tmux/powerline/lib/rcfile.sh create mode 100644 tmux/powerline/lib/text_roll.sh create mode 100644 tmux/powerline/lib/tmux_adapter.sh create mode 100755 tmux/powerline/mute_powerline.sh create mode 100755 tmux/powerline/powerline.sh create mode 100644 tmux/powerline/segments/Makefile create mode 100755 tmux/powerline/segments/battery.sh create mode 100755 tmux/powerline/segments/cpu.sh create mode 100755 tmux/powerline/segments/date.sh create mode 100755 tmux/powerline/segments/date_day.sh create mode 100755 tmux/powerline/segments/earthquake.sh create mode 100755 tmux/powerline/segments/hostname.sh create mode 100755 tmux/powerline/segments/ifstat.sh create mode 100755 tmux/powerline/segments/ifstat_sys.sh create mode 100755 tmux/powerline/segments/lan_ip.sh create mode 100755 tmux/powerline/segments/load.sh create mode 100755 tmux/powerline/segments/mailcount.sh create mode 100755 tmux/powerline/segments/mailcount_apple_mail.script create mode 100755 tmux/powerline/segments/now_playing.sh create mode 100755 tmux/powerline/segments/np_itunes.script create mode 100644 tmux/powerline/segments/np_mpd.c create mode 100755 tmux/powerline/segments/np_pithos.py create mode 100755 tmux/powerline/segments/np_rdio_mac.script create mode 100755 tmux/powerline/segments/np_spotify_mac.script create mode 100755 tmux/powerline/segments/pwd.sh create mode 100755 tmux/powerline/segments/rainbarf.sh create mode 100755 tmux/powerline/segments/thyme.sh create mode 100755 tmux/powerline/segments/time.sh create mode 100755 tmux/powerline/segments/tmux_mem_cpu_load.sh create mode 100755 tmux/powerline/segments/tmux_session_info.sh create mode 100755 tmux/powerline/segments/uptime.sh create mode 100755 tmux/powerline/segments/utc_time.sh create mode 100755 tmux/powerline/segments/vcs_branch.sh create mode 100755 tmux/powerline/segments/vcs_compare.sh create mode 100755 tmux/powerline/segments/vcs_modified.sh create mode 100755 tmux/powerline/segments/vcs_others.sh create mode 100755 tmux/powerline/segments/vcs_revision.sh create mode 100755 tmux/powerline/segments/vcs_staged.sh create mode 100755 tmux/powerline/segments/wan_ip.sh create mode 100755 tmux/powerline/segments/weather.sh create mode 100644 tmux/powerline/segments/xkb_layout.c create mode 100755 tmux/powerline/segments/xkb_layout.sh create mode 100644 tmux/powerline/themes/default.sh create mode 100644 tmux/powerline/themes/paramah.sh diff --git a/.exports.example b/.exports.example new file mode 100644 index 0000000..2843c1a --- /dev/null +++ b/.exports.example @@ -0,0 +1,24 @@ +export SINGLE_LINE_ZLE=true +export PHPLS_ALLOW_XDEBUG=1 +export DISABLE_AUTO_TITLE=true +export WORKON_HOME=$HOME/.virtualenvs +export PAGER=most +export GOSS_PATH=/usr/local/bin/dgoss + +export TMUX_TMPDIR=$HOME + +export WORKON_HOME=~/.virtualenvs + +export LANG=en_US.UTF-8 + +export ARCHFLAGS="-arch x86_64" + +export SSH_KEY_PATH="~/.ssh/rsa_id" + + +export JIRA_API_TOKEN= + +export GOGS_ROOT_URL= +export GOGS_TOKEN= + + diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..5cdaa28 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,24 @@ +[user] + email = aleksander@cynarski.pl + name = Aleksander Cynarski + signingkey = C4340BA42B9C173A +[push] + default = matching +[merge] + conflictstyle = diff3 + tool = meld +[alias] + lg1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all + lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all + lg = !"git lg1" + tree = "forest --pretty=format:\"%C(red)%h %C(magenta)(%ar) %C(blue)%an %C(reset)%s\" --style=15 --reverse" + d = difftool + open = !vim `git-open.sh` +[diff] + tool = vimdiff +[difftool] + prompt = false +[core] + excludesfile = ~/.gitignore + quotepath = false + editor = vim diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dcb56d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +compile +.phpcomplete_extended/ +.php_cs.cache +zeus/ +_todos.md +.tmuxp.yaml +vendor/ +./docker/docker-compose-elena.yml +.jira-url +.jira-prefix +.jira-name +tags +tags.* +.vscode +.exports diff --git a/.signature b/.signature new file mode 100644 index 0000000..aea5e65 --- /dev/null +++ b/.signature @@ -0,0 +1,6 @@ +-- +Aleksander "paramah" Cynarski +------------------------------- +PGP/GPG: http://gpg.cynarski.pl +About: http://cynarski.pl + diff --git a/.taskrc b/.taskrc new file mode 100644 index 0000000..c70c6a7 --- /dev/null +++ b/.taskrc @@ -0,0 +1,34 @@ +# [Created by task 2.5.1 10/18/2018 20:29:25] +# Taskwarrior program configuration file. +# For more documentation, see http://taskwarrior.org or try 'man task', 'man task-color', +# 'man task-sync' or 'man taskrc' + +# Here is an example of entries that use the default, override and blank values +# variable=foo -- By specifying a value, this overrides the default +# variable= -- By specifying no value, this means no default +# #variable=foo -- By commenting out the line, or deleting it, this uses the default + +# Use the command 'task show' to see all defaults and overrides + +# Files +data.location=~/.task + +# Color theme (uncomment one to use) +#include /usr/share/doc/task/rc/light-16.theme +#include /usr/share/doc/task/rc/light-256.theme +#include /usr/share/doc/task/rc/dark-16.theme +include /usr/share/doc/task/rc/dark-256.theme +#include /usr/share/doc/task/rc/dark-red-256.theme +#include /usr/share/doc/task/rc/dark-green-256.theme +#include /usr/share/doc/task/rc/dark-blue-256.theme +#include /usr/share/doc/task/rc/dark-violets-256.theme +#include /usr/share/doc/task/rc/dark-yellow-green.theme +#include /usr/share/doc/task/rc/dark-gray-256.theme +#include /usr/share/doc/task/rc/dark-gray-blue-256.theme +#include /usr/share/doc/task/rc/solarized-dark-256.theme +#include /usr/share/doc/task/rc/solarized-light-256.theme +#include /usr/share/doc/task/rc/no-color.theme + +uda.totalactivetime.type=duration +uda.totalactivetime.label=Total active time +uda.totalactivetime.values= diff --git a/.thymerc b/.thymerc new file mode 100644 index 0000000..045817a --- /dev/null +++ b/.thymerc @@ -0,0 +1,42 @@ +set :timer, 25*60 # 25 minute pomodoros +set :timer_break, 5*60 # 5 minute breaks +set :warning, 5*60 # show warning color in tmux at <5 minutes, 0 to disable +set :warning_color, 'red,bold' # warning color for tmux is red/bold +set :break_color, 'magenta' # break color is blue +set :interval, 1 # refresh timer every 1 second +set :tmux, true # turn on tmux integration +set :tmux_theme, "#[fg=mycolor,bg=mycolor]#[fg=%s]%s#[fg=mycolor,bg=mycolor]" + +# adds `-t --today` option, which opens a text file in vim +option :t, :today, 'open today sheet' do + `vim -O ~/.thyme-today.md ~/.thyme-records.md < \`tty\` > \`tty\`` +end + +# adds `-s --seconds num` option, which allows on the fly timer +option :s, 'seconds num', 'run with custom seconds' do |num| + set :timer, num.to_i + run +end + +# execute hook before thyme program starts +before(:all) do + `notify-send 'Uruchomiłem serwer pomidora.'` + `tmux set-option -g status-bg black` +end + +# execute hook before each pomodoro +before do + `notify-send 'Pomidor rozpoczęty'` +end + +# execute hook after each pomodoro +after do |seconds_left| + `notify-send 'Pomidor skończony' 'Zrób sobie chwilę przerwy, pooddychaj, zapal, napij sie kawy, kogoś wkurz - nie wiem, zajmij się sobią :)'` if seconds_left == 0 + `tmux new-window -n _screensaver_ "~/bin/pipes.sh -r 0 -p 50 -t 3 -s 10; tmux set -g status on"` if seconds_left == 0 +end + +# execute hook after thyme program quits +after(:all) do + `notify-send 'Zrobiłeś pomidory' 'Jesteś z siebie dumny? \nTo dobrze, a teraz walcz dalej.'` + +end diff --git a/.tmux.conf b/.tmux.conf new file mode 100644 index 0000000..2aa70ef --- /dev/null +++ b/.tmux.conf @@ -0,0 +1,96 @@ +#tmux conf by Paramah + +set -g default-terminal "screen-256color" + +unbind C-b +set -g prefix C-a + +unbind l +bind C-a last-window +bind C-p previous-window +bind C-n next-window +bind -n f7 previous-window +bind -n f8 next-window + +# Resize bindings (vim like) +bind C-k resize-pane -U +bind C-j resize-pane -D +bind C-h resize-pane -L +bind C-l resize-pane -R + +# Change window move behavior +bind . command-prompt "swap-window -t '%%'" +bind > command-prompt "move-window -t '%%'" + +bind f command-prompt "resize-pane -Z" +bind n command-prompt "resize-pane" + +unbind % +bind | split-window -h +unbind '"' +bind - split-window -v + +# History +set -g history-limit 10000 + +# Terminal emulator window title +set -g set-titles on +set -g set-titles-string '#S:#I.#P #W' + + +# clock +set-window-option -g clock-mode-colour colour18 #green + +bind b set-window-option synchronize-panes + +set -g mouse on + +set -g default-terminal "screen-256color" +# Define my custom menu bar +# status bar colors +set -g status-bg colour0 +set -g status-fg white + +# alignment settings +set-option -g status-justify centre + +# status left options +set -g status-interval 1 + +# window list options +# setw -g automatic-rename on +set-window-option -g window-status-format "#[fg=colour0,bg=colour234,nobold,noitalics,nounderscore] #[fg=colour208,bg=colour234,nobold,noitalics,nounderscore]#I#F  #[fg=colour233,bg=colour234,nobold,noitalics,nounderscore]#[fg=colour208,bg=colour234,nobold,noitalics,nounderscore]#W #[fg=colour234,bg=colour0,nobold,noitalics,nounderscore] " +set-window-option -g window-status-current-format "#[fg=colour0,bg=colour208,nobold,noitalics,nounderscore] #[fg=colour0,bg=colour208,nobold,noitalics,nounderscore]#I#F  #[fg=colour232,bg=colour208,bold,noitalics,nounderscore]#W #[fg=colour208,bg=colour0,nobold,noitalics,nounderscore]" + +set-option -ga terminal-overrides ',*:enacs@:smacs@:rmacs@:acsc@' +# Reload tmux conf +bind r source-file ~/.tmux.conf + +#Plugins +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +set -g @plugin 'tmux-plugins/tmux-sidebar' +set -g @plugin 'tmux-plugins/tmux-copycat' +set -g @plugin 'tmux-plugins/tmux-resurrect' +#set -g @plugin 'tmux-plugins/tmux-continuum' + +set -g default-terminal "screen-256color" + +set-option -g status on +set-option -g status-interval 2 +set-option -g status-justify "centre" +set-option -g status-left-length 60 +set-option -g status-right-length 90 +set-option -g status-left "#(~/.tmux/powerline/powerline.sh left)" +set-option -g status-right "#(~/.tmux/powerline/powerline.sh right)" + +## set the default TERM +set -g default-terminal screen + +## update the TERM variable of terminal emulator when creating a new session or attaching a existing session +set -g update-environment 'DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY TERM' +## determine if we should enable 256-colour support +if "[[ ${TERM} =~ 256color || ${TERM} == fbterm ]]" 'set -g default-terminal screen-256color' + +run '~/.tmux/plugins/tpm/tpm' + diff --git a/.zshrc b/.zshrc new file mode 100644 index 0000000..ad4627a --- /dev/null +++ b/.zshrc @@ -0,0 +1,156 @@ +################################################################################# +# +#__ __ _____ _ ____ __ _ +#| \/ |_ _|__ /___| |__ / ___|___ _ __ / _(_) __ _ +#| |\/| | | | | / // __| '_ \ | | / _ \| '_ \| |_| |/ _` | +#| | | | |_| |/ /_\__ \ | | || |__| (_) | | | | _| | (_| | +#|_| |_|\__, /____|___/_| |_(_)____\___/|_| |_|_| |_|\__, | +# |___/ |___/ +# by @paramah +# +################################################################################# + +#Load my environment exports +[ -f ~/.exports ] && source ~/.exports + + +export PATH=$HOME/bin:/usr/local/bin:$PATH +export PATH="${PATH}:${HOME}/.local/bin/" +export PATH="${PATH}:${HOME}/.config/composer/vendor/bin" + +# paramah configuration +export PATH="/usr/bin/core_perl:$PATH" +export PATH="/home/paramah/.gem/ruby/2.4.0/bin:$PATH" +export PATH="/home/paramah/.gem/ruby/2.3.0/bin:$PATH" +export PATH="/home/paramah/.gem/ruby/2.5.0/bin:$PATH" +export PATH="/home/paramah/.local/bin:$PATH" + +#Home bin (last always!) +export PATH="/home/paramah/bin:$PATH" + + +# Path to your oh-my-zsh installation. +export ZSH=$HOME/.oh-my-zsh +ZSH_THEME="powerlevel9k/powerlevel9k" +POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status background_jobs_joined) + +source /usr/bin/virtualenvwrapper.sh + +plugins=( + zsh-autosuggestions + virtualenvwrapper + taskwarrior + archlinux + systemd + themes + git +) + + + +source ~/.zplug/init.zsh + +zplug 'ytet5uy4/fzf-widgets' +zplug 'zsh-users/zaw' + + +# Map widgets to key +bindkey '^ge' fzf-select-widget +bindkey '^@.' fzf-edit-dotfiles +bindkey '^@c' fzf-change-directory +bindkey '^@n' fzf-change-named-directory +bindkey '^@f' fzf-edit-files +bindkey '^@k' fzf-kill-processes +bindkey '^gs' fzf-exec-ssh +bindkey '^/' fzf-change-recent-directory +bindkey '^r' fzf-insert-history +bindkey '^xf' fzf-insert-files +bindkey '^xd' fzf-insert-directory +bindkey '^xn' fzf-insert-named-directory + +## Git +bindkey '^@g' fzf-select-git-widget +bindkey '^@ga' fzf-git-add-files +bindkey '^@gc' fzf-git-change-repository + +# GitHub +bindkey '^@h' fzf-select-github-widget +bindkey '^@hs' fzf-github-show-issue +bindkey '^@hc' fzf-github-close-issue + +## Docker +bindkey '^@d' fzf-select-docker-widget +bindkey '^@dc' fzf-docker-remove-containers +bindkey '^@di' fzf-docker-remove-images +bindkey '^@dv' fzf-docker-remove-volumes + +zplug load + +source $ZSH/oh-my-zsh.sh + +# Preferred editor for local and remote sessions +if [[ -n $SSH_CONNECTION ]]; then + export EDITOR='vim' +else + export EDITOR='nvim' +fi + +TMPDIR=/home/paramah/.tmp/ + +eval "$(jira --completion-script-zsh)" + +[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh + +TRAPWINCH() { + zle && { zle reset-prompt; zle -R } +} + + +autoload bashcompinit +bashcompinit +dsh(){ + docker exec -it $1 sh -c "stty cols $COLUMNS rows $LINES && sh"; +} + +dbash(){ + docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash"; +} + +_goinside(){ + COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=$2) ); +} +complete -F _goinside dsh; +complete -F _goinside dbash; +export goinside; + +################################### +# _ _ +# __ _| (_) __ _ ___ ___ ___ +# / _` | | |/ _` / __|/ _ \/ __| +# | (_| | | | (_| \__ \ __/\__ \ +# (_)__,_|_|_|\__,_|___/\___||___/ +# +########################################################################################## + + +alias l="tmuxp load -d" +alias dc="docker-compose" +alias d="docker" +alias t="tmux" +alias b="buku --suggest" +alias j="jrnl" +alias wh="curl wttr.in/Gliwice" + +alias drestart="sudo systemctl restart docker" +alias dstop="sudo systemctl stop docker" +alias dstart="sudo systemctl start docker" +alias ls="exa" + +# alias cat="bat" +alias ping='~/bin/prettyping --nolegend' + +alias sourcec="docker run --publish 7080:7080 --rm --volume ~/.sourcegraph/config:/etc/sourcegraph --volume ~/.sourcegraph/data:/var/opt/sourcegraph --volume /var/run/docker.sock:/var/run/docker.sock sourcegraph/server:2.11.2" + +alias hadolint="docker run --rm -i hadolint/hadolint" + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..bf35a79 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +``` + ____ ____ ___ _____ +| _ \ __ _ _ __ __ _| _ \ / _ \_ _| +| |_) / _` | '__/ _` | | | | | | || | +| __/ (_| | | | (_| | |_| | |_| || | +|_| \__,_|_| \__,_|____/ \___/ |_| +``` + +## Konfiguracja dla: + +- neovim +- tmux +- tmuxp +- zsh +- taskwarrior +- eg + + diff --git a/bin/bash2048.sh b/bin/bash2048.sh new file mode 100755 index 0000000..7d10a56 --- /dev/null +++ b/bin/bash2048.sh @@ -0,0 +1,365 @@ +#!/usr/bin/env bash + +#important variables +declare -ia board # array that keeps track of game status +declare -i pieces # number of pieces present on board +declare -i score=0 # score variable +declare -i flag_skip # flag that prevents doing more than one operation on + # single field in one step +declare -i moves # stores number of possible moves to determine if player lost + # the game +declare ESC=$'\e' # escape byte +declare header="Bash 2048 v1.1 (https://github.com/mydzor/bash2048)" + +declare -i start_time=$(date +%s) + +#default config +declare -i board_size=4 +declare -i target=2048 +declare -i reload_flag=0 +declare config_dir="$HOME/.bash2048" + +#for colorizing numbers +declare -a colors +colors[2]=33 # yellow text +colors[4]=32 # green text +colors[8]=34 # blue text +colors[16]=36 # cyan text +colors[32]=35 # purple text +colors[64]="33m\033[7" # yellow background +colors[128]="32m\033[7" # green background +colors[256]="34m\033[7" # blue background +colors[512]="36m\033[7" # cyan background +colors[1024]="35m\033[7" # purple background +colors[2048]="31m\033[7" # red background (won with default target) + +exec 3>/dev/null # no logging by default + +trap "end_game 0 1" INT #handle INT signal + +#simplified replacement of seq command +function _seq { + local cur=1 + local max + local inc=1 + case $# in + 1) let max=$1;; + 2) let cur=$1 + let max=$2;; + 3) let cur=$1 + let inc=$2 + let max=$3;; + esac + while test $max -ge $cur; do + printf "$cur " + let cur+=inc + done +} + +# print currect status of the game, last added pieces are marked red +function print_board { + clear + printf "$header pieces=$pieces target=$target score=$score\n" + printf "Board status:\n" >&3 + printf "\n" + printf '/------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '\\\n' + for l in $(_seq 0 $index_max); do + printf '|' + for m in $(_seq 0 $index_max); do + if let ${board[l*$board_size+m]}; then + if let '(last_added==(l*board_size+m))|(first_round==(l*board_size+m))'; then + printf '\033[1m\033[31m %4d \033[0m|' ${board[l*$board_size+m]} + else + printf "\033[1m\033[${colors[${board[l*$board_size+m]}]}m %4d\033[0m |" ${board[l*$board_size+m]} + fi + printf " %4d |" ${board[l*$board_size+m]} >&3 + else + printf ' |' + printf ' |' >&3 + fi + done + let l==$index_max || { + printf '\n|------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '|\n' + printf '\n' >&3 + } + done + printf '\n\\------' + for l in $(_seq 1 $index_max); do + printf '+------' + done + printf '/\n' +} + +# Generate new piece on the board +# inputs: +# $board - original state of the game board +# $pieces - original number of pieces +# outputs: +# $board - new state of the game board +# $pieces - new number of pieces +function generate_piece { + while true; do + let pos=RANDOM%fields_total + let board[$pos] || { + let value=RANDOM%10?2:4 + board[$pos]=$value + last_added=$pos + printf "Generated new piece with value $value at position [$pos]\n" >&3 + break; + } + done + let pieces++ +} + +# perform push operation between two pieces +# inputs: +# $1 - push position, for horizontal push this is row, for vertical column +# $2 - recipient piece, this will hold result if moving or joining +# $3 - originator piece, after moving or joining this will be left empty +# $4 - direction of push, can be either "up", "down", "left" or "right" +# $5 - if anything is passed, do not perform the push, only update number +# of valid moves +# $board - original state of the game board +# outputs: +# $change - indicates if the board was changed this round +# $flag_skip - indicates that recipient piece cannot be modified further +# $board - new state of the game board +function push_pieces { + case $4 in + "up") + let "first=$2*$board_size+$1" + let "second=($2+$3)*$board_size+$1" + ;; + "down") + let "first=(index_max-$2)*$board_size+$1" + let "second=(index_max-$2-$3)*$board_size+$1" + ;; + "left") + let "first=$1*$board_size+$2" + let "second=$1*$board_size+($2+$3)" + ;; + "right") + let "first=$1*$board_size+(index_max-$2)" + let "second=$1*$board_size+(index_max-$2-$3)" + ;; + esac + let ${board[$first]} || { + let ${board[$second]} && { + if test -z $5; then + board[$first]=${board[$second]} + let board[$second]=0 + let change=1 + printf "move piece with value ${board[$first]} from [$second] to [$first]\n" >&3 + else + let moves++ + fi + return + } + return + } + let ${board[$second]} && let flag_skip=1 + let "${board[$first]}==${board[second]}" && { + if test -z $5; then + let board[$first]*=2 + let "board[$first]==$target" && end_game 1 + let board[$second]=0 + let pieces-=1 + let change=1 + let score+=${board[$first]} + printf "joined piece from [$second] with [$first], new value=${board[$first]}\n" >&3 + else + let moves++ + fi + } +} + +function apply_push { + printf "\n\ninput: $1 key\n" >&3 + for i in $(_seq 0 $index_max); do + for j in $(_seq 0 $index_max); do + flag_skip=0 + let increment_max=index_max-j + for k in $(_seq 1 $increment_max); do + let flag_skip && break + push_pieces $i $j $k $1 $2 + done + done + done +} + +function check_moves { + let moves=0 + apply_push up fake + apply_push down fake + apply_push left fake + apply_push right fake +} + +function key_react { + let change=0 + read -d '' -sn 1 + test "$REPLY" = "$ESC" && { + read -d '' -sn 1 -t1 + test "$REPLY" = "[" && { + read -d '' -sn 1 -t1 + case $REPLY in + A) apply_push up;; + B) apply_push down;; + C) apply_push right;; + D) apply_push left;; + esac + } + } || { + case $REPLY in + k) apply_push up;; + j) apply_push down;; + l) apply_push right;; + h) apply_push left;; + + w) apply_push up;; + s) apply_push down;; + d) apply_push right;; + a) apply_push left;; + esac + } +} + +function save_game { + rm -rf "$config_dir" + mkdir "$config_dir" + echo "${board[@]}" > "$config_dir/board" + echo "$board_size" > "$config_dir/board_size" + echo "$pieces" > "$config_dir/pieces" + echo "$target" > "$config_dir/target" +# echo "$log_file" > "$config_dir/log_file" + echo "$score" > "$config_dir/score" + echo "$first_round" > "$config_dir/first_round" +} + +function reload_game { + printf "Loading saved game...\n" >&3 + + if test ! -d "$config_dir"; then + return + fi + board=(`cat "$config_dir/board"`) + board_size=(`cat "$config_dir/board_size"`) + board=(`cat "$config_dir/board"`) + pieces=(`cat "$config_dir/pieces"`) + first_round=(`cat "$config_dir/first_round"`) + target=(`cat "$config_dir/target"`) + score=(`cat "$config_dir/score"`) + + fields_total=board_size*board_size + index_max=board_size-1 +} + +function end_game { + # count game duration + end_time=$(date +%s) + let total_time=end_time-start_time + + print_board + printf "Your score: $score\n" + + printf "This game lasted " + + `date --version > /dev/null 2>&1` + if [[ "$?" -eq 0 ]]; then + date -u -d @${total_time} +%T + else + date -u -r ${total_time} +%T + fi + + stty echo + let $1 && { + printf "Congratulations you have achieved $target\n" + exit 0 + } + let test -z $2 && { + read -n1 -p "Do you want to overwrite saved game? [y|N]: " + test "$REPLY" = "Y" || test "$REPLY" = "y" && { + save_game + printf "\nGame saved. Use -r option next to load this game.\n" + exit 0 + } + test "$REPLY" = "" && { + printf "\nGame not saved.\n" + exit 0 + } + } + printf "\nYou have lost, better luck next time.\033[0m\n" + exit 0 +} + +function help { + cat <=3)&(board_size<=9)' || { + printf "Invalid board size, please choose size between 3 and 9\n" + exit -1 + };; + t ) target="$OPTARG" + printf "obase=2;$target\n" | bc | grep -e '^1[^1]*$' + let $? && { + printf "Invalid target, has to be power of two\n" + exit -1 + };; + r ) reload_flag="1";; + h ) help $0 + exit 0;; + l ) exec 3>$OPTARG;; + \?) printf "Invalid option: -"$opt", try $0 -h\n" >&2 + exit 1;; + : ) printf "Option -"$opt" requires an argument, try $0 -h\n" >&2 + exit 1;; + esac +done + +#init board +let fields_total=board_size*board_size +let index_max=board_size-1 +for i in $(_seq 0 $fields_total); do board[$i]="0"; done +let pieces=0 +generate_piece +first_round=$last_added +generate_piece + +#load saved game if flag is set +if test $reload_flag = "1"; then + reload_game +fi + +while true; do + print_board + key_react + let change && generate_piece + first_round=-1 + let pieces==fields_total && { + check_moves + let moves==0 && end_game 0 #lose the game + } +done diff --git a/bin/changelog b/bin/changelog new file mode 100755 index 0000000..12642f5 --- /dev/null +++ b/bin/changelog @@ -0,0 +1,18 @@ +#!/bin/bash +echo "" +echo "CHANGELOG" +git tag -l | sort -u -r | while read TAG ; do + echo + if [ $NEXT ];then + echo [$NEXT] + else + echo "[Current]" + fi + GIT_PAGER=cat git log --no-merges --format=" * %s" $TAG..$NEXT + NEXT=$TAG +done +FIRST=$(git tag -l | head -1) +echo +echo [$FIRST] +GIT_PAGER=cat git log --no-merges --format=" * %s" $FIRST + diff --git a/bin/christtree.sh b/bin/christtree.sh new file mode 100755 index 0000000..8859797 --- /dev/null +++ b/bin/christtree.sh @@ -0,0 +1,66 @@ +#!/bin/bash +trap "tput reset; tput cnorm; exit" 2 +clear +tput civis +lin=2 +col=$(($(tput cols) / 2)) +c=$((col-1)) +est=$((c-2)) +color=0 +tput setaf 2; tput bold + +for ((i=1; i<40; i+=2)) +{ + tput cup $lin $col + for ((j=1; j<=i; j++)) + { + echo -n \* + } + let lin++ + let col-- +} + +tput sgr0; tput setaf 3 + +for ((i=1; i<=2; i++)) +{ + tput cup $((lin++)) $c + echo 'mWm' +} +new_year=$(date +'%Y') +let new_year++ +tput setaf 1; tput bold +tput cup $lin $((c - 6)); echo MERRY CHRISTMAS +tput cup $((lin + 1)) $((c - 10)); echo And lots of CODE in $new_year +let c++ +k=1 + +while true; do + for ((i=1; i<=155; i++)) { + [ $k -gt 1 ] && { + tput setaf 2; tput bold + tput cup ${linea[$[k-1]$i]} ${columna[$[k-1]$i]}; echo \* + unset linea[$[k-1]$i]; unset columna[$[k-1]$i] + } + + li=$((RANDOM % 19 + 3)) + inicio=$((c-li+2)) + fin=$((c+li+2)) + co=$((RANDOM % (li-2) * 2 + 1 + inicio)) + tput setaf $color; tput bold + tput cup $li $co + echo o + linea[$k$i]=$li + columna[$k$i]=$co + color=$(((color+1)%8)) + sh=1 + for l in C O D E + do + tput cup $((lin+1)) $((c+sh)) + echo $l + let sh++ + sleep 0.01 + done + } + k=$((k % 2 + 1)) + done diff --git a/bin/crpass b/bin/crpass new file mode 100755 index 0000000..f20c7b0 --- /dev/null +++ b/bin/crpass @@ -0,0 +1,3 @@ +#!/bin/sh + +dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64 diff --git a/bin/gogs b/bin/gogs new file mode 100755 index 0000000..4db1221 --- /dev/null +++ b/bin/gogs @@ -0,0 +1,366 @@ +#!/bin/bash +# Interact with the GOGS API +# Copyright (c) 2017 Matthew Downey (mattddowney@gmail_NOSPAM_.com) +# Relased under the MIT License +# See https://raw.githubusercontent.com/mattddowney/gogs-bash/master/LICENSE for the complete license text + +action=${1:-"help"} + +# preseed for checks +response_code=0 + +# ensure GOGS_ROOT_URL is set +if [ -z $GOGS_ROOT_URL ] +then + printf "Need to set GOGS_ROOT_URL environment variable\n" >&2 + printf "\tIE: https://try.gogs.io\n" >&2 + + response_code=1 +fi + +# ensure GOGS_TOKEN is set +if [ -z $GOGS_TOKEN ] +then + printf "Need to set GOGS_TOKEN environment variable\n" >&2 + printf "\tThis can be obtained at $GOGS_ROOT_URL/user/settings/applications\n" >&2 + + response_code=1 +fi + +# exit if either of the environment variables above are not set +if [ $response_code -ne 0 ] +then + exit $response_code +fi + +# create a GOGS repository +# https://github.com/gogits/go-gogs-client/wiki/Administration-Repositories#create-a-new-repository +create-repo() { + local user_name=$1 # name of the user / organization where the repo will be created + local repo_name=$2 # name of the repo to be created + + # ensure user_name is passed in + if [ -z $user_name ] + then + response_code=1 + fi + + # ensure repo_name is passed in + if [ -z $repo_name ] + then + response_code=1 + fi + + # print help and exit either of the variables above are not passed in + if [ $response_code -ne 0 ] + then + help "create-repo" + + exit $response_code + fi + + printf "--" "---> Creating GOGS repository\n" + printf "--" "---> User/Org Name: $user_name\n" + printf "--" "---> Repo Name: $repo_name\n" + + local body=$(cat <<-END + { + "name": "$repo_name", + "private": false + } + END + ) + + curl -H "Content-Type: application/json" \ + -H "Authorization: token $GOGS_TOKEN" \ + -d "$body" \ + -v $GOGS_ROOT_URL/api/v1/admin/users/$user_name/repos +} + +# create a GOGS webhook +# https://github.com/gogits/go-gogs-client/wiki/Repositories-Webhooks#create-a-hook +create-webhook() { + local user_name=$1 # name of the user / organization that owns the repo where the webhook will be created + local repo_name=$2 # name of the repo where the webhook will be created + local webhook_url=$3 # the url for the webhook that will be created + local secret=$4 # optional secret that will be passed in the X-Gogs-Signature header + + # ensure user_name is passed in + if [ -z $user_name ] + then + response_code=1 + fi + + # ensure repo_name is passed in + if [ -z $repo_name ] + then + response_code=1 + fi + + # ensure that webhook_url is passed in + if [ -z $webhook_url ] + then + response_code=1 + fi + + # print help and exit either of the variables above are not passed in + if [ $response_code -ne 0 ] + then + help "create-webhook" + + exit $response_code + fi + + printf "--" "---> Creating GOGS webhook\n" + printf "--" "---> Repo Name: $repo_name\n" + printf "--" "---> Webhook URL: $webhook_url\n" + + local body=$(cat <<-END + { + "type": "gogs", + "config": { + "content_type": "json", + "url": "$webhook_url" + }, + "events": [ "create", "push" ], + "active": true + } + END + ) + + # add secret to body if one is passed in + if [ -n $secret ] + then + body=$(echo "$body" | jq ".config.secret=\"$secret\"") + fi + + curl -H "Content-Type: application/json" \ + -H "Authorization: token $GOGS_TOKEN" \ + -d "$body" \ + -v $GOGS_ROOT_URL/api/v1/repos/$user_name/$repo_name/hooks +} + +# delete a GOGS webhook for a repo +# https://github.com/gogits/go-gogs-client/wiki/Repositories-Webhooks#delete-a-hook +delete-webhook() { + local user_name=$1 + local repo_name=$2 + local webhook_id=$3 + + # ensuer user_name is passed in + if [ -z $user_name ] + then + response_code=1 + fi + + # ensure repo_name is passed in + if [ -z $repo_name ] + then + response_code=1 + fi + + # ensure webhook_id is passed in + if [ -z $webhook_id ] + then + response_code=1 + fi + + # print help and exit any of the variables above are not passed in + if [ $reponse_code -ne 0 ] + then + help "delete-webhook" + + exit $response_code + fi + + printf "--" "---> Deleting GOGS webhook\n" + printf "--" "---> User Name: $user_name\n" + printf "--" "---> Repo Name: $repo_name\n" + printf "--" "---> Webhook Id: $webhook_id\n" + + curl -H "Authorization: token $GOGS_TOKEN" \ + -X DELETE \ + -v $GOGS_ROOT_URL/api/v1/repos/$user_name/$repo_name/hooks/$webhook_id +} + +# print environment information +env() { + printf "GOGS_ROOT_URL=$GOGS_ROOT_URL\n" + printf "GOGS_TOKEN=$GOGS_TOKEN\n" +} + +# get a list of GOGS repos for a user +# https://github.com/gogits/go-gogs-client/wiki/Repositories#list-user-repositories +get-user-repos() { + local user_name=$1 # name of the user who's repos to list + + # ensure user_name is passed in + if [ -z $user_name ] + then + help "get-user-repos" + + exit 1 + fi + + printf "--" "---> Getting list of GOGS repos\n" + printf "--" "---> User Name: $user_name\n" + + curl -H "Content-Type: application/json" \ + -H "Authorization: token $GOGS_TOKEN" \ + -v $GOGS_ROOT_URL/api/v1/users/$user_name/repos +} + +# get a list of GOGS webhooks for a repo +# https://github.com/gogits/go-gogs-client/wiki/Repositories-Webhooks#list-hooks +get-webhooks() { + local user_name=$1 # name of the user / organization that owns the repo + local repo_name=$2 # name of the repo to list webhooks for + + # ensure user_name is passed in + if [ -z $user_name ] + then + response_code=1 + fi + + # ensure repo_name is passed in + if [ -z $repo_name ] + then + response_code=1 + fi + + # print help and exit either of the variables above are not passed in + if [ $response_code -ne 0 ] + then + help "get-webhooks" + + exit $response_code + fi + + printf "--" "---> Getting list of GOGS webhooks\n" + printf "--" "---> User Name: $user_name\n" + printf "--" "---> Repo Name: $repo_name\n" + + curl -H "Authorization: token $GOGS_TOKEN" \ + -v $GOGS_ROOT_URL/api/v1/repos/$user_name/$repo_name/hooks +} + +# print help +help() { + local prog_name=$(echo "$0" | rev | cut -d'/' -f1 | rev) + local topic=$1 + + case "$topic" in + create-repo) + cat <<-END + Create a GOGS repository. + + Usage: + + $prog_name $1 + + Arguments: + + user_name name of the user or organization where the repo will be created + repo_name name of the repository to be created + END + ;; + + create-webhook) + cat <<-END + Create a GOGS webhook. + + Usage: + + $prog_name $1 [secret] + + Arguments: + + user_name name of the user / organizationo that owns the repo where the webhook will be created + repo_name name of the repo where the webhook will be created + webhook_url the url for the webhook that will be created + secret optional secret that will be passed in the X-Gogs-Signature header + END + ;; + + delete-webhook) + cat <<-END + Delete a GOGS webhook. + + Usage: + + $prog_name $1 + + Arguments: + + user_name name of the user / organizationo that owns the repo containing the webhook + repo_name name of the repo that contains the webhook + webhook_id id of the webhook that will be deleted + END + ;; + + env) + cat <<-END + Prints environment variables needed by this script. + + Variables: + + GOGS_ROOT_URL The url of the GOGS server + (IE: https://try.gogs.io) + + GOGS_TOKEN Application token configured in GOGS + (Obtained from $GOGS_ROOT_URL/user/settings/applications) + END + ;; + + get-user-repos) + cat <<-END + Get a list of GOGS repos for a user. + + Usage: + + $prog_name $1 + + Arguments: + + user_name name of the user who's repos to list + END + ;; + + get-webhooks) + cat <<-END + Get a list of GOGS webhooks for a repo. + + Usage: + + $prog_name $1 + + Arguments: + + user_name name of the user / organization that owns the repo + repo_name name of the repo to list webhooks for + END + ;; + + *) + cat <<-END + $prog_name is a tool for interacting with the GOGS API. + + Usage: + $prog_name command [arguments] + + The commands are: + + create-repo create a repository + create-webhook create a webhook + delete-webhook delete a webhook + env print environment information + get-user-repos get a list of repos for a user + get-webhooks get a list of webhooks for a repo + + Use "$prog_name help [command]" for more information about a command. + END + ;; + esac +} + +"$action" "${@:2}" diff --git a/bin/jsawk b/bin/jsawk new file mode 100755 index 0000000..05a26f7 --- /dev/null +++ b/bin/jsawk @@ -0,0 +1,1326 @@ +#!/usr/bin/env bash + +# +# Jsawk: It's like awk for JSON, in bash. +# +# Fork me on github: +# http://github.com/micha/jsawk +# +# Author: +# Micha Niskin +# Copyright 2009, no rights reserved, other than as required by the +# licenses of the incorporated software below. +# + +TMP1=`mktemp /tmp/tmp.XXXXXX` +TMP2=`mktemp /tmp/tmp.XXXXXX` + +trap "rm -f $TMP1 $TMP2" SIGINT SIGTERM SIGHUP SIGQUIT + +cat <<'__END__' > $TMP1 + +window = this; // the global object +window.IS = []; // the input set +window.RS = []; // the result set +window.$_ = {}; // the current element index +window.$$ = {}; // the current element + + +/** +sprintf() for JavaScript 0.7-beta1 +http://www.diveintojavascript.com/projects/javascript-sprintf + +Copyright (c) Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Changelog: +2010.09.06 - 0.7-beta1 + - features: vsprintf, support for named placeholders + - enhancements: format cache, reduced global namespace pollution + +2010.05.22 - 0.6: + - reverted to 0.4 and fixed the bug regarding the sign of the number 0 + Note: + Thanks to Raphael Pigulla (http://www.n3rd.org/) + who warned me about a bug in 0.5, I discovered that the last update was + a regress. I appologize for that. + +2010.05.09 - 0.5: + - bug fix: 0 is now preceeded with a + sign + - bug fix: the sign was not at the right position on padded results (Kamal Abdali) + - switched from GPL to BSD license + +2007.10.21 - 0.4: + - unit test and patch (David Baird) + +2007.09.17 - 0.3: + - bug fix: no longer throws exception on empty paramenters (Hans Pufal) + +2007.09.11 - 0.2: + - feature: added argument swapping + +2007.04.03 - 0.1: + - initial release +**/ + +var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw('[sprintf] huh?'); + } + } + } + else { + throw('[sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw('[sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; +})(); + +var vsprintf = function(fmt, argv) { + argv.unshift(fmt); + return sprintf.apply(null, argv); +}; + +// Underscore.js 1.8.2 +// http://underscorejs.org +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. +(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=d(e,i,4);var o=!w(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=b(r,e);for(var u=null!=t&&t.length,i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t){var r=S.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||o,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=S[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var e=this,u=e._,i=Array.prototype,o=Object.prototype,a=Function.prototype,c=i.push,l=i.slice,f=o.toString,s=o.hasOwnProperty,p=Array.isArray,h=Object.keys,v=a.bind,g=Object.create,y=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):e._=m,m.VERSION="1.8.2";var d=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},b=function(n,t,r){return null==n?m.identity:m.isFunction(n)?d(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return b(n,t,1/0)};var x=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var l=o[c];t&&r[l]!==void 0||(r[l]=i[l])}return r}},_=function(n){if(!m.isObject(n))return{};if(g)return g(n);y.prototype=n;var t=new y;return y.prototype=null,t},j=Math.pow(2,53)-1,w=function(n){var t=n&&n.length;return"number"==typeof t&&t>=0&&j>=t};m.each=m.forEach=function(n,t,r){t=d(t,r);var e,u;if(w(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=w(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=b(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(b(t)),r)},m.every=m.all=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=b(t,r);for(var e=!w(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r){return w(n)||(n=m.values(n)),m.indexOf(n,t,"number"==typeof r&&r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=w(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=b(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=w(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=b(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=w(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(w(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=b(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var A=function(n){return function(t,r,e){var u={};return r=b(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=A(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=A(function(n,t,r){n[r]=t}),m.countBy=A(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):w(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:w(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=b(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var k=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=n&&n.length;a>o;o++){var c=n[o];if(w(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=k(c,t,r));var l=0,f=c.length;for(u.length+=f;f>l;)u[i++]=c[l++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return k(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){if(null==n)return[];m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=b(r,e));for(var u=[],i=[],o=0,a=n.length;a>o;o++){var c=n[o],l=r?r(c,o,n):c;t?(o&&i===l||u.push(c),i=l):r?m.contains(i,l)||(i.push(l),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(k(arguments,!0,!0))},m.intersection=function(n){if(null==n)return[];for(var t=[],r=arguments.length,e=0,u=n.length;u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=k(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,"length").length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=n&&n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.indexOf=function(n,t,r){var e=0,u=n&&n.length;if("number"==typeof r)e=0>r?Math.max(0,u+r):r;else if(r&&u)return e=m.sortedIndex(n,t),n[e]===t?e:-1;if(t!==t)return m.findIndex(l.call(n,e),m.isNaN);for(;u>e;e++)if(n[e]===t)return e;return-1},m.lastIndexOf=function(n,t,r){var e=n?n.length:0;if("number"==typeof r&&(e=0>r?e+r+1:Math.min(e,r+1)),t!==t)return m.findLastIndex(l.call(n,0,e),m.isNaN);for(;--e>=0;)if(n[e]===t)return e;return-1},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=b(r,e,1);for(var u=r(t),i=0,o=n.length;o>i;){var a=Math.floor((i+o)/2);r(n[a])i;i++,n+=r)u[i]=n;return u};var O=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=_(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(v&&n.bind===v)return v.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return O(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var l=m.now();a||r.leading!==!1||(a=l);var f=t-(l-a);return e=this,u=arguments,0>=f||f>t?(o&&(clearTimeout(o),o=null),a=l,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,f)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var l=m.now()-o;t>l&&l>=0?e=setTimeout(c,t-l):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var F=!{toString:null}.propertyIsEnumerable("toString"),S=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(h)return h(n);var t=[];for(var e in n)m.has(n,e)&&t.push(e);return F&&r(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var e in n)t.push(e);return F&&r(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=b(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=x(m.allKeys),m.extendOwn=m.assign=x(m.keys),m.findKey=function(n,t,r){t=b(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=d(t,r)):(u=k(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var l=u[a],f=o[l];e(f,l,o)&&(i[l]=f)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(k(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=x(m.allKeys,!0),m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var E=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=f.call(n);if(u!==f.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!E(n[c],t[c],r,e))return!1}else{var l,s=m.keys(n);if(c=s.length,m.keys(t).length!==c)return!1;for(;c--;)if(l=s[c],!m.has(t,l)||!E(n[l],t[l],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return E(n,t)},m.isEmpty=function(n){return null==n?!0:w(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=p||function(n){return"[object Array]"===f.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return f.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===f.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&s.call(n,t)},m.noConflict=function(){return e._=u,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=function(n){return function(t){return null==t?void 0:t[n]}},m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=d(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var M={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},N=m.invert(M),I=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=I(M),m.unescape=I(N),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var B=0;m.uniqueId=function(n){var t=++B+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,R={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},q=/\\|'|\r|\n|\u2028|\u2029/g,K=function(n){return"\\"+R[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||T).source,(t.interpolate||T).source,(t.evaluate||T).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(q,K),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},l=t.variable||"obj";return c.source="function("+l+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var z=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return c.apply(n,arguments),z(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=i[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],z(this,r)}}),m.each(["concat","join","slice"],function(n){var t=i[n];m.prototype[n]=function(){return z(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); +//# sourceMappingURL=underscore-min.map + +(function() { + +/* +Copyright Jason E. Smith 2008 Licensed under the Apache License, Version 2.0 (the "License"); +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +*/ + + +/* +* CREDITS: +* Thanks to Kris Zyp from SitePen for contributing his source for +* a standalone port of JSONQuery (from the dojox.json.query module). +* +* OVERVIEW: +* JSONQuery.js is a standalone port of the dojox.json.query module. It is intended as +* a dropin solution with zero dependencies. JSONQuery is intended to succeed and improve upon +* the JSONPath api (http://goessner.net/articles/JsonPath/) which offers rich powerful +* querying capabilities similar to those of XQuery. +* +* EXAMPLES / USAGE: +* see http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/ +* +* *Ripped from original source. +* JSONQuery(queryString,object) + and + JSONQuery(queryString)(object) + always return identical results. The first one immediately evaluates, the second one returns a + function that then evaluates the object. + + example: + JSONQuery("foo",{foo:"bar"}) + This will return "bar". + + example: + evaluator = JSONQuery("?foo='bar'&rating>3"); + This creates a function that finds all the objects in an array with a property + foo that is equals to "bar" and with a rating property with a value greater + than 3. + evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}]) + This returns: + {foo:"bar",rating:4} + + example: + evaluator = JSONQuery("$[?price<15.00][\rating][0:10]"); + This finds objects in array with a price less than 15.00 and sorts then + by rating, highest rated first, and returns the first ten items in from this + filtered and sorted list. + + + example: + var data = {customers:[ + {name:"Susan", purchases:29}, + {name:"Kim", purchases:150}, + {name:"Jake", purchases:27} + ]}; + + var results = json.JSONQuery("$.customers[?purchases > 21 & name='Jake'][\\purchases]",data); + results + + returns customers sorted by higest number of purchases to lowest. + +*/ + + + + function map(arr, fun /*, thisp*/){ + var len = arr.length; + if (typeof fun != "function") + throw new TypeError(); + + var res = new Array(len); + var thisp = arguments[2]; + for (var i = 0; i < len; i++) { + if (i in arr) + res[i] = fun.call(thisp, arr[i], i, arr); + } + + return res; + } + + function filter(arr, fun /*, thisp*/){ + var len = arr.length; + if (typeof fun != "function") + throw new TypeError(); + + var res = new Array(); + var thisp = arguments[2]; + for (var i = 0; i < len; i++) { + if (i in arr) { + var val = arr[i]; // in case fun mutates this + if (fun.call(thisp, val, i, arr)) + res.push(val); + } + } + + return res; + }; + + + function slice(obj,start,end,step){ + // handles slice operations: [3:6:2] + var len=obj.length,results = []; + end = end || len; + start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start); + end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end); + for(var i=start; i, <=, >=, != - These operators behave just as they do + // in JavaScript. + // + // + // + // | dojox.json.query(queryString,object) + // and + // | dojox.json.query(queryString)(object) + // always return identical results. The first one immediately evaluates, the second one returns a + // function that then evaluates the object. + // + // example: + // | dojox.json.query("foo",{foo:"bar"}) + // This will return "bar". + // + // example: + // | evaluator = dojox.json.query("?foo='bar'&rating>3"); + // This creates a function that finds all the objects in an array with a property + // foo that is equals to "bar" and with a rating property with a value greater + // than 3. + // | evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}]) + // This returns: + // | {foo:"bar",rating:4} + // + // example: + // | evaluator = dojox.json.query("$[?price<15.00][\rating][0:10]"); + // This finds objects in array with a price less than 15.00 and sorts then + // by rating, highest rated first, and returns the first ten items in from this + // filtered and sorted list. + tokens = []; + var depth = 0; + var str = []; + query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){ + depth += t == '[' ? 1 : t == ']' ? -1 : 0; // keep track of bracket depth + return (t == ']' && depth > 0) ? '`]' : // we mark all the inner brackets as skippable + (t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :// and replace all the strings + t; + }); + var prefix = ''; + function call(name){ + // creates a function call and puts the expression so far in a parameter for a call + prefix = name + "(" + prefix; + } + function makeRegex(t,a,b,c,d){ + // creates a regular expression matcher for when wildcards and ignore case is used + return str[d].match(/[\*\?]/) || c == '~' ? + "/^" + str[d].substring(1,str[d].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,".$1") + (c == '~' ? '$/i' : '$/') + ".test(" + a + ")" : + t; + } + query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){ + throw new Error("Unsafe function call"); + }); + + query = query.replace(/([^=]=)([^=])/g,"$1=$2"). // change the equals to comparisons + replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){ + return t.charAt(0) == '.' ? t : // leave .prop alone + t == '@' ? "$obj" :// the reference to the current object + (t.match(/:|^(\$|Math|true|false|null)$/) ? "" : "$obj.") + t; // plain names should be properties of root... unless they are a label in object initializer + }). + replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){ + var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/); // [?expr] and ?expr and [=expr and =expr + if(oper){ + var prefix = ''; + if(t.match(/^\./)){ + // recursive object search + call("expand"); + prefix = ",true)"; + } + call(oper[1].match(/\=/) ? "map" : oper[1].match(/\^/) ? "distinctFilter" : "filter"); + return prefix + ",function($obj){return " + oper[2] + "})"; + } + oper = t.match(/^\[\s*([\/\\].*)\]/); // [/sortexpr,\sortexpr] + if(oper){ + // make a copy of the array and then sort it using the sorting expression + return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){ + return "var av= " + b.replace(/\$obj/,"a") + ",bv= " + b.replace(/\$obj/,"b") + // FIXME: Should check to make sure the $obj token isn't followed by characters + ";if(av>bv||bv==null){return " + (a== "/" ? 1 : -1) +";}\n" + + "if(bv>av||av==null){return " + (a== "/" ? -1 : 1) +";}\n"; + }) + "})"; + } + oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/); // slice [0:3] + if(oper){ + call("slice"); + return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")"; + } + if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){ // ..prop and [*] + call("expand"); + return (t.charAt(1) == '.' ? + ",'" + b + "'" : // ..prop + t.match(/,/) ? + "," + t : // [prop1,prop2] + "") + ")"; // [*] + } + return t; + }). + replace(/(\$obj\s*(\.\s*[\w_$]+\s*)*)(==|~)\s*`([0-9]+)/g,makeRegex). // create regex matching + replace(/`([0-9]+)\s*(==|~)\s*(\$obj(\s*\.\s*[\w_$]+)*)/g,function(t,a,b,c,d){ // and do it for reverse = + return makeRegex(t,c,d,b,a); + }); + query = prefix + (query.charAt(0) == '$' ? "" : "$") + query.replace(/`([0-9]+|\])/g,function(t,a){ + //restore the strings + return a == ']' ? ']' : str[a]; + }); + // create a function within this scope (so it can use expand and slice) + + var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}"); + for(var i = 0;i 0) { + args = args.length > 1 ? args : args[0]; + var ret = typeof(args) == "string" ? args : json(args); + doPrint(type, ret); + } + }; + window.Q = function() { + try { + var ret = JSONQuery.apply(window, arguments); + ret.length; + return ret; + } catch (e) { + err("jsawk: JSONQuery parse error: '"+arguments[0]+"'"); + quit(4); + } + }; + window.out = function() { + var args = Array.prototype.slice.call(arguments); + args.unshift("OUT:"); + doJsonPrint.apply(window, args); + }; + window.err = function() { + var args = Array.prototype.slice.call(arguments); + args.unshift("ERR:"); + doJsonPrint.apply(window, args); + }; + window.alert = p; + window.doJson = function(input) { + if (typeof input !== "string") { + return input; + } else { + input = input.replace(/\s*$/,""); + if (!input.length) { + return {}; + } else { + try { + return eval("("+input+")"); + } catch (e) { + err("jsawk: JSON parse error: '"+input+"'"); + quit(2); + } + } + } + }; + window.doCall = function(fun, obj) { + try { + return fun.call(obj); + } catch (e) { + err("jsawk: js error: "+e); + quit(3); + } + }; + window.makeFilter = function(fun) { + try { + return eval("(function() { "+fun+"; return this })"); + } catch (e) { + err("jsawk: script parse error: '"+fun+"'"); + quit(3); + } + }; + window.json = function() { + try { + return JSON.stringify.apply(window, arguments); + } catch (e) { + err("jsawk: JSON stringify error: "+e); + quit(5); + } + }; + window.get = function() { + return $$ = IS[++$_]; + }; + window.put = function(record) { + IS = IS.slice(0, $_+1).concat([record]).concat(IS.slice($_+1)); + }; + window.forEach = function(ary, fun) { + fun = eval("function(index,item) { "+fun+"; }"); + for (var i=0; i $TMP2 + elif [ -n "$input_file" ]; then + # Pass in the input file contents specified, first checking the file exists + if ! [ -e "$input_file" ]; then + echo "Error: Input file cannot be found: $input_file" + exit 1 + fi + cat "$input_file" > $TMP2 + else + # Read input from STDIN + echo "$(cat 2>/dev/null)" > $TMP2 + fi + nlines=$(grep -c '$' $TMP2 2>/dev/null || echo 0) +fi + +if [ -e /etc/jsawkrc ]; then + . /etc/jsawkrc +fi + +if [ -e ~/.jsawkrc ]; then + . ~/.jsawkrc +fi + +JSBIN=${js_arg:-${JS:-js}} + +ret=$? +res=$(cat $TMP2 2>/dev/null | $JSBIN $TMP1 $nlines "$@") +out=$(echo "$res" |sed '/^OUT: /s/^.....//p;d') +err=$(echo "$res" |sed '/^ERR: /s/^.....//p;d') + +[ -n "$err" ] && echo "$err" 1>&2 +[ -n "$out" ] && echo "$out" + +rm -f $TMP1 $TMP2 + +exit $ret diff --git a/bin/make_archive b/bin/make_archive new file mode 100755 index 0000000..57c78a9 --- /dev/null +++ b/bin/make_archive @@ -0,0 +1,14 @@ +#!/bin/bash -x + +ARCHDIR="/home/paramah/Backups" +GIT=`which git` +PROJEKT=${PWD##*/} +DATE=`date +%Y-%m-%d` + +dir=$ARCHDIR/$PROJEKT + +if [[ ! -e $dir ]]; then + mkdir $dir +fi + +$GIT archive master --format=zip --output=$ARCHDIR/$PROJEKT/$DATE.zip diff --git a/bin/pipes.sh b/bin/pipes.sh new file mode 100755 index 0000000..ce0d399 --- /dev/null +++ b/bin/pipes.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# pipes.sh: Animated pipes terminal screensaver. +# +# This modified version is maintained at: +# +# https://github.com/livibetter/pipes.sh + +VERSION=0.1.1 + +M=32768 +p=1 +f=75 s=13 r=2000 t=0 +w=$(tput cols) h=$(tput lines) +# ab -> idx = a*4 + b +# 0: up, 1: right, 2: down, 3: left +# 00 means going up , then going up -> ┃ +# 12 means going right, then going down -> ┓ +sets=( + "┃┏ ┓┛━┓ ┗┃┛┗ ┏━" + "│╭ ╮╯─╮ ╰│╯╰ ╭─" + "│┌ ┐┘─┐ └│┘└ ┌─" + "║╔ ╗╝═╗ ╚║╝╚ ╔═" + "|+ ++-+ +|++ +-" + "|/ \/-\ \|/\ /-" +) +v=() +RNDSTART=0 +NOCOLOR=0 + +OPTIND=1 +while getopts "p:t:f:s:r:RChv" arg; do +case $arg in + p) ((p=(OPTARG>0)?OPTARG:p));; + t) ((OPTARG>=0 && OPTARG<${#sets[@]})) && V+=($OPTARG);; + f) ((f=(OPTARG>19 && OPTARG<101)?OPTARG:f));; + s) ((s=(OPTARG>4 && OPTARG<16 )?OPTARG:s));; + r) ((r=(OPTARG>=0)?OPTARG:r));; + R) RNDSTART=1;; + C) NOCOLOR=1;; + h) echo -e "Usage: $(basename $0) [OPTION]..." + echo -e "Animated pipes terminal screensaver.\n" + echo -e " -p [1-]\tnumber of pipes (D=1)." + echo -e " -t [0-$((${#sets[@]} - 1))]\ttype of pipes, can be used more than once (D=0)." + echo -e " -f [20-100]\tframerate (D=75)." + echo -e " -s [5-15]\tprobability of a straight fitting (D=13)." + echo -e " -r LIMIT\treset after x characters, 0 if no limit (D=2000)." + echo -e " -R \t\trandom starting point." + echo -e " -C \t\tno color." + echo -e " -h\t\thelp (this screen)." + echo -e " -v\t\tprint version number.\n" + exit 0;; + v) echo "$(basename -- "$0") $VERSION" + exit 0 + esac +done + +# set default values if not by options +((${#V[@]})) || V=(0) + +# Attempt to workaround for Bash versions < 4, such as 3.2 on Mac: +# https://gist.github.com/livibetter/4689307/#comment-892368 +# Untested--in conduction of using shebang `env bash`--should fall back to +# `sleep` +printf -v SLEEP "read -t0.0$((1000/f)) -n 1" +if $SLEEP &>/dev/null; (($? != 142)); then + printf -v SLEEP "sleep 0.0$((1000/f))" +fi + +cleanup() { + # clear up standard input + read -t 0 && cat /dev/null + + # terminal has no smcup and rmcup capabilities + ((FORCE_RESET)) && reset && exit 0 + + tput rmcup + tput cnorm + stty echo + ((NOCOLOR)) && echo -ne '\e[0m' + exit 0 +} +trap cleanup HUP TERM +trap 'break 2' INT + +for (( i=1; i<=p; i++ )); do + c[i]=$((i%8)) n[i]=0 l[i]=0 + ((x[i]=RNDSTART==1?RANDOM*w/32768:w/2)) + ((y[i]=RNDSTART==1?RANDOM*h/32768:h/2)) + v[i]=${V[${#V[@]} * RANDOM / M]} +done + +stty -echo +tput smcup || FORCE_RESET=1 +tput civis +tput clear +# any key press exits the loop and this script +while REPLY=; $SLEEP; [[ -z $REPLY ]] ; do + for (( i=1; i<=p; i++ )); do + # New position: + ((${l[i]}%2)) && ((x[i]+=-${l[i]}+2,1)) || ((y[i]+=${l[i]}-1)) + + # Loop on edges (change color on loop): + ((${x[i]}>w||${x[i]}<0||${y[i]}>h||${y[i]}<0)) && ((c[i]=RANDOM%8, v[i]=V[${#V[@]}*RANDOM/M])) + ((x[i]=(x[i]+w)%w)) + ((y[i]=(y[i]+h)%h)) + + # New random direction: + ((n[i]=RANDOM%s-1)) + ((n[i]=(${n[i]}>1||${n[i]}==0)?${l[i]}:${l[i]}+${n[i]})) + ((n[i]=(${n[i]}<0)?3:${n[i]}%4)) + + # Print: + tput cup ${y[i]} ${x[i]} + [[ $NOCOLOR == 0 ]] && echo -ne "\033[1;3${c[i]}m" + echo -n "${sets[v[i]]:l[i]*4+n[i]:1}" + l[i]=${n[i]} + done + ((r>0 && t*p>=r)) && tput reset && tput civis && t=0 || ((t++)) +done + +cleanup diff --git a/nvim/init.vim b/nvim/init.vim new file mode 100644 index 0000000..332e3b1 --- /dev/null +++ b/nvim/init.vim @@ -0,0 +1,344 @@ +source ~/.vim/common.vim +set shell=/bin/bash +set hidden + + +" ____ _ +" | _ \| |_ _ __ _ +" | |_) | | | | |/ _` | +" | __/| | |_| | (_| | +" |_| |_|\__,_|\__, | +" |___/ +" ######################################################################## +" + +call plug#begin('~/.vim/plugged') + +" Powerline vim +" @site: https://github.com/powerline/powerline +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'powerline/powerline' " Powerline VIM +Plug 'vim-airline/vim-airline' " AirLine (tabs,etc..) +Plug 'vim-airline/vim-airline-themes' " AirLine Themes (for sexy working) + +Plug 'echuraev/translate-shell.vim', { 'do': 'wget -O ~/.vim/trans git.io/trans && chmod +x ~/.vim/trans' } + +" Vim addons (nice & sexy) +Plug 'mhinz/vim-startify' +Plug 'terryma/vim-expand-region' +Plug 'terryma/vim-multiple-cursors' +Plug 'editorconfig/editorconfig-vim' + +Plug 'dylanaraps/wal' + +"Plug 'yggdroot/indentline' + +Plug 'sbdchd/neoformat' +Plug 'neomake/neomake' +Plug 'ludovicchabant/vim-gutentags' +Plug 'junegunn/fzf' +Plug 'ncm2/ncm2' +Plug 'roxma/nvim-yarp' +Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' } +Plug 'KabbAmine/zeavim.vim' +Plug 'tpope/vim-commentary' +Plug 'Shougo/vimproc.vim', {'do' : 'make'} +Plug 'wincent/ferret' +Plug 'moll/vim-bbye' + +Plug 'shime/vim-livedown' + +Plug 'tpope/vim-unimpaired' + +" NOTE: you need to install completion sources to get completions. Check +" our wiki page for a list of sources: https://github.com/ncm2/ncm2/wiki +Plug 'ncm2/ncm2-bufword' +Plug 'ncm2/ncm2-tmux' +Plug 'ncm2/ncm2-path' +Plug 'ncm2/ncm2-vim-lsp' + +Plug 'vim-vdebug/vdebug' + +" NERDTree +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'scrooloose/nerdtree' +Plug 'zefei/vim-wintabs' +Plug 'tiagofumo/vim-nerdtree-syntax-highlight' +Plug 'ryanoasis/vim-devicons' +Plug 'jistr/vim-nerdtree-tabs' + +" Vim colorscheme plugins +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'fcpg/vim-complimentary' +Plug 'fcpg/vim-farout' +Plug 'fcpg/vim-orbital' +Plug 'fcpg/vim-fahrenheit' + +" Vim Git +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'tpope/vim-fugitive' +Plug 'mhinz/vim-signify' +Plug 'junegunn/gv.vim' + + +" Vim Snippets +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'SirVer/ultisnips' +Plug 'honza/vim-snippets' +Plug 'ssh://gogs@git.cynarski.pl:65522/myEnv/my-snips.git' + +" PHP +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'StanAngeloff/php.vim' +Plug 'arnaud-lb/vim-php-namespace' +Plug 'lumiliet/vim-twig' + +Plug 'phpactor/phpactor' , {'do': 'composer install'} +Plug 'phpactor/ncm2-phpactor' + +Plug 'tobyS/vmustache' +Plug 'tobyS/pdv' +Plug 'StanAngeloff/php.vim', {'for': 'php'} +Plug 'adoy/vim-php-refactoring-toolbox' + +Plug 'stephpy/vim-php-cs-fixer' + +" TypeScript +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'leafgarland/typescript-vim' +" Plug 'mhartington/nvim-typescript' +Plug 'Quramy/tsuquyomi' + + +" HasiCorp +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'hashivim/vim-terraform' +Plug 'hashivim/vim-consul' + + +" Salt-Stack (.:REACTIVATE:.) +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'saltstack/salt-vim' + +" GoLang +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'fatih/vim-go' + +" DevOps Syntax +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Plug 'chr4/nginx.vim' + +call plug#end() +" +" ######################################################################## +" +source ~/.vim/powerline.vim + +let g:trans_bin = "~/.vim" + +set laststatus=2 +nnoremap n :NERDTreeToggle +nnoremap v :vsplit +nnoremap s :split + +map d :NERDTreeClose + + +set number relativenumber + +augroup numbertoggle + autocmd! + autocmd BufEnter,FocusGained,InsertLeave * set relativenumber + autocmd BufLeave,FocusLost,InsertEnter * set norelativenumber +augroup END + + +set statusline+=%#warningmsg# +set statusline+=%* + +" +" +" +" +" +""""""""""""""""""""""""""""""" + +if filereadable(".bookmarks") + let g:NERDTreeBookmarksFile = ".bookmarks" +endif + +nmap p :FZF +syntax enable +filetype plugin indent on + +"autocmd VimEnter * colorscheme farout +autocmd VimEnter * colorscheme fahrenheit +"autocmd VimEnter * + + +map (wintabs_previous) +map (wintabs_next) + +set mouse=a +let g:vrc_connect_timeout = 10 +let g:vrc_cookie_jar = '/tmp' +let g:vrc_follow_redirects = 1 +let g:vrc_include_response_header = 1 +let g:vrc_max_time = 60 +let g:vrc_resolve_to_ipv4 = 1 +let g:vrc_ssl_secure = 1 + +set foldmethod=syntax +set foldnestmax=10 +set foldenable +set foldlevel=4 + +set foldnestmax=10 +"set nofoldenable +"set foldlevel=1 +"let g:tex_fold_enabled=1 +"let g:vimsyn_folding='af' +"let g:xml_syntax_folding = 1 +"let g:php_folding = 1 +"let g:perl_fold = 1 + +let g:SimpylFold_docstring_preview = 1 + +let g:startify_custom_header = [] + +function! s:list_commits() + let git = 'git -C ./' + let commits = systemlist(git .' log --oneline | head -n10') + let git = 'G'. git[1:] + return map(commits, '{"line": matchstr(v:val, "\\s\\zs.*"), "cmd": "'. git .' show ". matchstr(v:val, "^\\x\\+") }') +endfunction + +let g:startify_session_dir = $HOME . '/.vim/sessions/' + +let g:startify_lists = [ + \ { 'header': [' Ostatnio edytowane'], 'type': 'dir' }, + \ { 'header': [' Zapisane sesje'], 'type': 'sessions' }, + \ { 'header': [' Ostatnie zmiany'], 'type': function('s:list_commits') }, + \ { 'header': [' Zakładki'], 'type': 'bookmarks' }, +\ ] + +let g:startify_files_number = 6 + +let g:startify_bookmarks = [ + \ {'c': '~/.vimrc'}, + \ {'z': '~/.zshrc'}, + \ {'v': '~/.vim/common.vim'}, + \ {'b': '~/.vim/binds.vim'}, + \ {'p': '~/.vim/powerline.vim'}, +\ ] + +let g:startify_update_oldfiles = 1 +let g:startify_disable_at_vimenter = 0 +let g:startify_session_autoload = 1 +let g:startify_session_persistence = 1 +"let g:startify_session_delete_buffers = 0 +let g:startify_change_to_dir = 0 +"let g:startify_change_to_vcs_root = 0 " vim-rooter has same feature +let g:startify_skiplist = [ + \ 'COMMIT_EDITMSG', + \ escape(fnamemodify(resolve($VIMRUNTIME), ':p'), '\') .'doc', + \ 'bundle/.*/doc', + \ ] + +augroup startify_map + au! + autocmd FileType startify nnoremap + if !exists('g:startify_custom_header') + autocmd FileType startify call update_logo() + endif + autocmd FileType startify setl nowrap +augroup END + + +" enable ncm2 for all buffers +autocmd BufEnter * call ncm2#enable_for_buffer() + +" IMPORTANTE: :help Ncm2PopupOpen for more information +set completeopt=noinsert,menuone,noselect + +set hidden + +" _____ ____ _ _ +" |_ _| _ _ __ ___/ ___| ___ _ __(_)_ __ | |_ +" | || | | | '_ \ / _ \___ \ / __| '__| | '_ \| __| +" _| || |_| | |_) | __/___) | (__| | | | |_) | |_ +" (_)_| \__, | .__/ \___|____/ \___|_| |_| .__/ \__| +" |___/|_| |_| +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + + + +" _ +" _ __ | |__ _ __ +" | '_ \| '_ \| '_ \ +" _| |_) | | | | |_) | +" (_) .__/|_| |_| .__/ +" |_| |_| +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +nnoremap pcf :call PhpCsFixerFixFile() + +let g:pdv_template_dir = $HOME ."/.vim/plugged/pdv/templates_snip" + +autocmd BufWritePost *.php silent! call PhpCsFixerFixFile() +autocmd FileType php setlocal omnifunc=phpactor#Complete + +" Include use statement +nmap u :call phpactor#UseAdd() +" Invoke the context menu +nmap mm :call phpactor#ContextMenu() +" Invoke the navigation menu +nmap nn :call phpactor#Navigate() +" Goto definition of class or class member under the cursor +" Include use statement +nmap u :call phpactor#UseAdd() +" Invoke the context menu +nmap mm :call phpactor#ContextMenu() +" Invoke the navigation menu +nmap nn :call phpactor#Navigate() +" Goto definition of class or class member under the cursor +nmap o :call phpactor#GotoDefinition() +" Transform the classes in the current file +nmap tt :call phpactor#Transform() +" Generate a new class (replacing the current file) +nmap cc :call phpactor#ClassNew() +" Extract expression (normal mode) +nmap ee :call phpactor#ExtractExpression(v:false) +" Extract expression from selection +vmap ee :call phpactor#ExtractExpression(v:true) +" Extract method from selection +vmap em :call phpactor#ExtractMethod() +nmap o :call phpactor#GotoDefinition() +" Transform the classes in the current file +nmap tt :call phpactor#Transform() +" Generate a new class (replacing the current file) +nmap cc :call phpactor#ClassNew() + +let g:vim_php_refactoring_use_default_mapping = 0 + +" nnoremap rlvar :call PhpRenameLocalVariable() +"nnoremap rcvar :call PhpRenameClassVariable() +"nnoremap rm :call PhpRenameMethod() +"nnoremap eu :call PhpExtractUse() +vnoremap ec :call PhpExtractConst() +"nnoremap ep :call PhpExtractClassProperty() +" vnoremap emm :call PhpExtractMethod() +"nnoremap np :call PhpCreateProperty() +nnoremap du :call PhpDetectUnusedUseStatements() +vnoremap aa :call PhpAlignAssigns() +nnoremap sg :call PhpCreateSettersAndGetters() +"nnoremap cog :call PhpCreateGetters() +"nnoremap da :call PhpDocAll() +nnoremap da :call pdv#DocumentWithSnip() + + + +" Extract expression (normal mode) + +" let $NVIM_PYTHON_LOG_FILE="/tmp/nvim_log" +" let $NVIM_PYTHON_LOG_LEVEL="DEBUG" diff --git a/tmux/powerline/AUTHORS b/tmux/powerline/AUTHORS new file mode 100644 index 0000000..e61c72c --- /dev/null +++ b/tmux/powerline/AUTHORS @@ -0,0 +1,34 @@ +Please append you name/nick here when you have contributed with something! + +Erik Westrup +Suvash Thapaliya +Erik Jansson +Yuku Takahashi +Oscar Olsson +Ryo Katsuma +negipo +Sina Siadat +Vivien Leroy +Gino Lucero +Derek Ashley Thomas +LuRsT +Tomokazu Hirai +Matt Black +krieiter +Viktor Jackson +flytreeleft +Conner McDaniel +David Francos +Travis Thompson +Jonathon Klobucar +Dylan Copeland +Pete Johns +Robert Murray McMahon +Jeff Felchner +tobetoby +Matthew Lanigan +Hadret +antiAgainst +Alexander Luberg +Stanislaw Pusep +Austin Beam diff --git a/tmux/powerline/LICENSE b/tmux/powerline/LICENSE new file mode 100644 index 0000000..a8ba532 --- /dev/null +++ b/tmux/powerline/LICENSE @@ -0,0 +1,14 @@ +tmux-powerline - Statusbar configuration for tmux that looks like vim-powerline and consist of dynamic segments. + +Copyright (c) 2012, see AUTHORS +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +http://opensource.org/licenses/BSD-3-Clause diff --git a/tmux/powerline/README.md b/tmux/powerline/README.md new file mode 100644 index 0000000..1c2c70a --- /dev/null +++ b/tmux/powerline/README.md @@ -0,0 +1,209 @@ +# DEPRECATION WARNING +This project is in a maintenance mode and no future functionality is likely to be added. tmux-powerline, with all other powerline projects, is replaced by the new unifying [powerline](https://github.com/Lokaltog/powerline). However this project is still functional and can serve as a lightweight alternative for non-python users. + +# tmux-powerline +This is a set of scripts for making a nice and dynamic tmux statusbar consisting of segments. This is much like [Lokaltog/vim-powerline](https://github.com/Lokaltog/vim-powerline) but for tmux. + +The following segments exists for now: +* LAN & WAN IP addresses. +* Now Playing for MPD, Spotify (GNU/Linux native or wine, OS X), iTunes (OS X), Rhythmbox, Banshee, MOC, Audacious, Rdio (OS X), cmus, Pithos and Last.fm (last scrobbled track). +* New mail count for GMail, Maildir, mbox, mailcheck, and Apple Mail. +* GNU/Linux and Macintosh OS X battery status (uses [richo/dotfiles/bin/battery](https://github.com/richoH/dotfiles/blob/master/bin/battery)). +* Weather in Celsius, Fahrenheit and Kelvin using Yahoo Weather. +* System load, cpu usage and uptime. +* Git, SVN and Mercurial branch in CWD. +* Date and time. +* Hostname. +* tmux info. +* CWD in pane. +* Current X keyboard layout. +* Network download/upload speed. +* Earthquake warnings. + +# Screenshots +**Full screenshot** + +![Full screenshot](img/full.png) + +**left-status** + +Current tmux session, window and pane, hostname and LAN & WAN IP address. + +![left-status](img/left-status.png) + +**right-status** + +New mails, now playing, average load, weather, date and time. + +![right-status](img/right-status.png) + +Now I've read my inbox so the mail segment disappears! + +![right-status, no mail](img/right-status_no_mail.png) + +After pausing the music there's no need for showing NP anymore. Also the weather has become much nicer! + +![right-status, no mpd](img/right-status_no_mpd.png) + +Remaining battery. + +![right-status, weather and battery](img/right-status_weather_battery.png) + +# Requirements +Requirements for the lib to work are: + +* Recent tmux version +* `bash --version` >= 3.2 (Does not have to be your default shell.) +* A patched font. Follow instructions at [Powerline Installation](http://powerline.readthedocs.org/en/latest/installation/linux.html) or [download](https://github.com/powerline/fonts) a new one. However you can use other substitute symbols as well; see `config.sh`. + +## Segment Requirements +Requirements for some segments. You only need to fulfill the requirements for those segments you want to use. + +* `wan_ip.sh`, `now_playing.sh` (last.fm), `weather_yahoo.sh`: curl, bc +* `now_playing.sh` (mpd) : [libmpdclient](http://sourceforge.net/projects/musicpd/files/libmpdclient/) +* `xkb_layout.sh`: X11, XKB +* `mailcount.sh` (gmail): wget, (mailcheck): [mailcheck](http://packages.debian.org/sid/mailcheck). +* `ifstat.sh`: ifstat (there is a simpler segment not using ifstat but samples /sys/class/net) +* `tmux_mem_cpu_load.sh`: [tmux-mem-cpu-load](https://github.com/thewtex/tmux-mem-cpu-load) +* `rainbarf.sh`: [rainbarf](https://github.com/creaktive/rainbarf) +* `weather.sh`: GNU `grep` with Perl regexp enabled (FreeBSD specific) + +## OS X specific requirements + +The `grep` tool is outdated on OS X 10.8 Mountain Lion so you might have to upgrade it. Unfortunately the main homebrew repo +[does not contain grep](https://github.com/mxcl/homebrew/pull/3473) so use the following command to get the lastest version. + +```bash +brew install https://raw.github.com/Homebrew/homebrew-dupes/master/grep.rb +``` + +or if you have heightened security set up, just tap the homebrew dupes and install grep + +```bash +brew tap homebrew/dupes +brew install homebrew/dupes/grep +``` + +## FreeBSD specific requirements + +Preinstalled `grep` in FreeBSD doesn't support Perl regexp. Solution is rather simple -- you need to use `textproc/gnugrep` port instead. You also need to make sure, that it has support for PCRE and is compiled with `--enable-perl-regexp` flag. + + +# Installation +Start with checking out the repository with: + +```console +$ cd ~/some/path/ +$ git clone https://github.com/erikw/tmux-powerline.git +``` + +Now edit your `~/.tmux.conf` to use the scripts: + + +```vim +set-option -g status on +set-option -g status-interval 2 +set-option -g status-utf8 on +set-option -g status-justify "centre" +set-option -g status-left-length 60 +set-option -g status-right-length 90 +set-option -g status-left "#(~/path/to/tmux-powerline/powerline.sh left)" +set-option -g status-right "#(~/path/to/tmux-powerline/powerline.sh right)" +``` + +Set the maximum lengths to something that suits your configuration of segments and size of terminal (the maximum segments length will be handled better in the future). + +The window list can be powerlineified if you'd like by adding the following line to the same file: + +```vim +set-window-option -g window-status-current-format "#[fg=colour235, bg=colour27]⮀#[fg=colour255, bg=colour27] #I ⮁ #W #[fg=colour27, bg=colour235]⮀" +``` + +You can toggle the visibility of the statusbars by adding the following lines: + +```vim +bind C-[ run '~/path/to/tmux-powerline/mute_powerline.sh left' # Mute left statusbar. +bind C-] run '~/path/to/tmux-powerline/mute_powerline.sh right' # Mute right statusbar. +``` + +Some segments e.g. cwd and cvs_branch needs to find the current working directory of the active pane. To achieve this we let tmux save the path each time the shell prompt is displayed. Put the line below in your `~/.bashrc` or where you define you PS1 variable. zsh users can put it in e.g. `~/.zshrc` and may change `PS1` to `PROMPT` (but that's not necessary). + +```bash +PS1="$PS1"'$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#D" | tr -d %) "$PWD")' +``` + + +If the active shell is Fish, PS1 is not being set normally. Instead, it has a `fish_prompt` function that is being called when prompt rendering is required. This means that one can append the following command at the end of the function in `fish_prompt.fish` file: + +```fish +if set -q TMUX; tmux setenv TMUXPWD_(tmux display -p "#D" | tr -d '%') $PWD; end +``` + +# Configuration + +The default segments that are shown are defined in `themes/default.sh`. You will probably want to change those to fit your needs. To do so you can edit that file directly but preferable, for easier updating of the repo, you can make a copy and edit that one (or see how to use custom themes directory below). A palette of colors that can be used can be obtained by running the script `color_palette.sh`. + +```console +$ cp themes/default.sh themes/mytheme.sh +$ $EDITOR themes/mytheme.sh +``` +Now generate a default configuration file by doing + +```console +$ ./generate_rc.sh +$ mv ~/.tmux-powerlinerc.default ~/.tmux-powerlinerc +$ $EDITOR ~/.tmux-powerlinerc +``` +and change theme to use and values for segments you want to use. If you want to keep the repo checkout clean you can set custom segment and theme paths in the general section and then store your files outside the repo. + +# Debugging + +Some segments might not work on your system for various reasons such as missing programs or different versions not having the same options. To find out which segment is not working it may help to enable the debug setting in `~/.tmux-powerlinerc`. However this may not be enough to determine the error so you can inspect all executed bash commands (will be a long output) by doing + +```console +$ bash -x powerline.sh (left|right) +``` + +To debug smaller portions of code, say if you think the problem lies in a specific segment, insert these lines at the top and bottom of the relevant code portions e.g. inside a function: + +```bash +set -x +exec 2>/tmp/tmux-powerline.log + +set +x +``` + +and then inspect the outputs like + +```console +less /tmp/tmux-powerline.log +tail -f /tmp/tmux-powerline.log # or follow output like this. +``` + +If you can not solve the problems you can post an [issue](https://github.com/erikw/tmux-powerline/issues?state=open) and be sure to include relevant information about your system and script output (from bash -x) and/or screenshots if needed. Be sure to search in the [resolved issues](https://github.com/erikw/tmux-powerline/issues?page=1&state=closed) section for similar problems you're experiencing before posting. + +## Common problems + + +### VCS_branch / PWD is not updating +The issue is probably that the update of the current directory in the active pane is not updated correctly. Make sure that your PS1 or PROMPT variable actually contains the line from the installation step above by simply inspecting the output of `echo $PS1`. You might have placed the PS1 line in you shell configuration such that it is overwritten later. The simplest solution is to put it at the very end to make sure that nothing overwrites it. See [issue #52](https://github.com/erikw/tmux-powerline/issues/52). + +### Nothing is displayed +You have edited `~/.tmux.conf` but no powerline is displayed. This might be because tmux is not aware of the changes so you have to restart your tmux session or reloaded that file by typing this on the command line (or in tmux command mode with `prefix :`) + +```console +$ tmux source-file ~/.tmux.conf +``` +### Multiple lines in bash or no powerline in zsh using iTerm (OS X) +If your tmux looks like [this](https://github.com/erikw/tmux-powerline/issues/125) then you may have to in iTerm uncheck [Unicode East Asian Ambiguous characters are wide] in Preferences -> Settings -> Advanced. + +# Hacking + +This project can only gain positively from contributions. Fork today and make your own enhancements and segments to share back! If you'd like, add your name and E-mail to AUTHORS before making a pull request so you can get some credit for your work :-) + +## How to make a segment +If you want to (of course you do!) send a pull request for a cool segment you written make sure that it follows the style of existing segments, unless you have good reason for it. Each segment resides in the `segments/` directory with a descriptive and simple name. A segment must have at least one function and that is `run_segment` which is like the main function that is called from the tmux-powerline lib. What ever text is echoed out from this function to stdout is the text displayed in the tmux statusbar. If the segment at a certain point does not have anything to show, simply don't echo anything out and the segment will be hidden. A successful execution of the `run_segment` function should return an exit code of 0. If the segment failed to execute in a fatal way return a non-zero exit code so the user can pick up the error and fix it when debug mode is on (e.g. missing program that is needed for the segment). + +Usage of helper function to organize the work of a segment is encourage and should be named in the format `__helper_func`. If a segment has settings it should have a function `generate_rc` which outputs default values of all settings and a short explanation of the setting and its values. Study e.g. `segments/now_playing.sh` to see how it is done. A segment having settings should typically call a helper function `__process_settings` as the first statement in `run_segment` that sets default values to the settings that has not been set by the user. + +Also, don't use bash4 features as requiring bash4 complicates installation for OS X user quite a bit. Use tabs for indentation ([discussion](https://github.com/erikw/tmux-powerline/pull/92)), diff --git a/tmux/powerline/color_palette.sh b/tmux/powerline/color_palette.sh new file mode 100755 index 0000000..3762fae --- /dev/null +++ b/tmux/powerline/color_palette.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# Print tmux color palette. +# Idea from http://superuser.com/questions/285381/how-does-the-tmux-color-palette-work + +for i in $(seq 0 4 255); do + for j in $(seq $i $(expr $i + 3)); do + for k in $(seq 1 $(expr 3 - ${#j})); do + printf " " + done + printf "\x1b[38;5;${j}mcolour${j}" + [[ $(expr $j % 4) != 3 ]] && printf " " + done + printf "\n" +done diff --git a/tmux/powerline/config/defaults.sh b/tmux/powerline/config/defaults.sh new file mode 100644 index 0000000..dfeb48d --- /dev/null +++ b/tmux/powerline/config/defaults.sh @@ -0,0 +1,5 @@ +# Default values for non segment configuration options. + +export TMUX_POWERLINE_DEBUG_MODE_ENABLED_DEFAULT="false" +export TMUX_POWERLINE_PATCHED_FONT_IN_USE_DEFAULT="true" +export TMUX_POWERLINE_THEME_DEFAULT="paramah" diff --git a/tmux/powerline/config/helpers.sh b/tmux/powerline/config/helpers.sh new file mode 100644 index 0000000..caba053 --- /dev/null +++ b/tmux/powerline/config/helpers.sh @@ -0,0 +1,9 @@ +# Other settings and helper functions. + +debug_mode_enabled() { + [ -n "$TMUX_POWERLINE_DEBUG_MODE_ENABLED" -a "$TMUX_POWERLINE_DEBUG_MODE_ENABLED" != "false" ]; +} + +patched_font_in_use() { + [ -z "$TMUX_POWERLINE_PATCHED_FONT_IN_USE" -o "$TMUX_POWERLINE_PATCHED_FONT_IN_USE" != "false" ]; +} diff --git a/tmux/powerline/config/paths.sh b/tmux/powerline/config/paths.sh new file mode 100644 index 0000000..c238bb5 --- /dev/null +++ b/tmux/powerline/config/paths.sh @@ -0,0 +1,14 @@ +# Paths + +export TMUX_POWERLINE_DIR_LIB="$TMUX_POWERLINE_DIR_HOME/lib" +export TMUX_POWERLINE_DIR_SEGMENTS="$TMUX_POWERLINE_DIR_HOME/segments" +export TMUX_POWERLINE_DIR_TEMPORARY="/tmp/tmux-powerline_${USER}" +export TMUX_POWERLINE_DIR_THEMES="$TMUX_POWERLINE_DIR_HOME/themes" +if [ -z "$TMUX_POWERLINE_RCFILE" ]; then + export TMUX_POWERLINE_RCFILE="$HOME/.tmux-powerlinerc" +fi +export TMUX_POWERLINE_RCFILE_DEFAULT="${TMUX_POWERLINE_RCFILE}.default" + +if [ ! -d "$TMUX_POWERLINE_DIR_TEMPORARY" ]; then + mkdir "$TMUX_POWERLINE_DIR_TEMPORARY" +fi diff --git a/tmux/powerline/config/shell.sh b/tmux/powerline/config/shell.sh new file mode 100644 index 0000000..d24bcf8 --- /dev/null +++ b/tmux/powerline/config/shell.sh @@ -0,0 +1,20 @@ +# Shell Configuration +# vi: sw=8 ts=8 noet + +ostype() { echo $OSTYPE | tr '[A-Z]' '[a-z]'; } + +export SHELL_PLATFORM='unknown' + +case "$(ostype)" in + *'linux'* ) SHELL_PLATFORM='linux' ;; + *'darwin'* ) SHELL_PLATFORM='osx' ;; + *'bsd'* ) SHELL_PLATFORM='bsd' ;; +esac + +shell_is_linux() { [[ $SHELL_PLATFORM == 'linux' || $SHELL_PLATFORM == 'bsd' ]]; } +shell_is_osx() { [[ $SHELL_PLATFORM == 'osx' ]]; } +shell_is_bsd() { [[ $SHELL_PLATFORM == 'bsd' || $SHELL_PLATFORM == 'osx' ]]; } + +export -f shell_is_linux +export -f shell_is_osx +export -f shell_is_bsd diff --git a/tmux/powerline/generate_rc.sh b/tmux/powerline/generate_rc.sh new file mode 100755 index 0000000..5c0b98f --- /dev/null +++ b/tmux/powerline/generate_rc.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Generate default rc file. + +export TMUX_POWERLINE_DIR_HOME="$(dirname $0)" +source "${TMUX_POWERLINE_DIR_HOME}/config/paths.sh" +source "${TMUX_POWERLINE_DIR_HOME}/config/defaults.sh" +source "${TMUX_POWERLINE_DIR_HOME}/config/shell.sh" +source "${TMUX_POWERLINE_DIR_LIB}/rcfile.sh" + +generate_default_rc + +exit 0 diff --git a/tmux/powerline/img/full.png b/tmux/powerline/img/full.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6a0ec3ec2ae33d4616ad7f9b34290a2b872c97 GIT binary patch literal 12243 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 literal 0 HcmV?d00001 diff --git a/tmux/powerline/img/right-status.png b/tmux/powerline/img/right-status.png new file mode 100644 index 0000000000000000000000000000000000000000..c20b31d3c7496786c4b01c5205637f9fb806f48d GIT binary patch literal 2335 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 FV1hV1Z#n<~ literal 0 HcmV?d00001 diff --git a/tmux/powerline/img/right-status_no_mail.png b/tmux/powerline/img/right-status_no_mail.png new file mode 100644 index 0000000000000000000000000000000000000000..4da8e53451ed10b2c826492b2db9013dc1c73508 GIT binary patch literal 1933 zcmb7_`6Cky9L7g`CC3~IL)Osyy3Z6s2y+&5tkKFb5{A8wu$IPDZY6V5WOMWyvR5X& zIVwl9j2tf|EB7^buD$vb-XFf7@AEuAJ-Ofb)5uu|5 zVryyc8a=jDXdiqMA@Sgru}E9|j}cDh!((D155<3@Re8C%z7U|P@XWsHbNzXJh zN1!i4yzJ?A0b+iHfXs>kVGKe-X{_|TxUyMRg?Q%Qok~j5??U?{bh7=Xu``UKhsW=> zW`j#`{f6wF{qW_M2V}m#osa4OnC-wx$zS4G;x7U`_ep}rj9Q(3|Z}mM+KC77A;_Lgxl2(c6 z+xYHj&W|ssyvYkEIz3S$I)-eAU>81nD3~Ku_u20aHjVI$x%PHu#;jstwn+9Z0)7CvDeNqSag&mi+p&MMF6(Sq`57xo{pKUmP`8r0eAnA zmA-I&>Yeaki$hwfd};n31za_DZ_XSCd(Yc^_|s^IUQbGvl%b{`S zfXYkOLanIYG!XM)1m{alE3+I-80{Gz%DsQqU3=;W#<-8vpEbB3)rz~YG5NNKnfW*m zH$OGlcaM1qb@p;l_E7C99A%?Fp&Lm$1tj=k+aw}|om$Sbq8a>Wuv`u4R`EdsGb8 zAOd4U^DAYM*LEZFsfoE3HqNeLQRhu{yxY>uw$(I;LP8Y=8D*(m60fYK=m?oxXFPTF z^N|YvQ+iodub#jA?sJuQY?h*8`L#aI#j;tsbnvcG zW5ZK<$P6h5Tc{8#_CtU!7rMw0c`4S`tnuOVI>r@bb?n1(!4Lu68m8M-*u)`?-4*3L zmb81~s+t`}WL}}Ux!L-Rh6mnel=DY!4n**w>W*5$rLwi+i(g~?S!(C^LRoo+=_i2% zZ)x4PW($O6~(*gU*Vc z!u?&$A3>u9FB7xvx~fF&K2;F+HE&l_Lh7uCkrOBr7Cp5|YW4)lRJ{&!i`8|4k)`tZ|1tK2Mo(bex<3l?Bq?o zd>n`hU_q}nhtx~18HdKAr}dW>=X;6`pzFrmSutcIaWpKGrnuE#Jd(<+%u+#{l=S1F z*REfe01{?ms*jyOKalS8RZq9HneKgh*xkL?(Lpu3=%~R~$GvIX_Db-R?I>JWY1>*H z&AD3q`c4+tB)WEH|0i?*O;J^v;e1bjQ3<|Q8(aO#^~9tg)SpF`DZkhmAy08XqoWro zQ13YYJC__!p7YX{=6}{+A<)ipp&S~9lOp3;PWZ#S@M14kgL&?>K%!ka{4aNwzOoR=-9;t2l=tUdbf8_bwF)wQyeYwDJiFxrrs;j1PSL2? z^FOsM?BAnB%S1WS7>M{~v!zF^G65LMP~rb~|70qOp>BzW=yBBz>%H4wLEVSPu+5qAZq-xDZFZu54+q~xc! z_YV&AJ!d$SfQ+4Sx#fjY!lW8BGUZ5cvV z4uo!R_crD+!myCrPzz9tnDn0T%@o+q=MUbxd8w8PVQSZ{KtTVkMdX^xfiw5)U?3_- zt8t=vrpRV|@#Ub$We}b;CnQCwBw$u)KmZ^>)1+=HMPaY1&w}ju?NXGH3xl3Si}^K7 NwpLdxYb?Ct{{xbjqJaPa literal 0 HcmV?d00001 diff --git a/tmux/powerline/img/right-status_no_mpd.png b/tmux/powerline/img/right-status_no_mpd.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca067e60b461128c0f2c3ad8f1bc7c9852ea236 GIT binary patch literal 1561 zcmV+!2Il#RP)X0ssI2d{+0^00001b5ch_0Itp) z=>Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RX1`rT123&IFeEz$ol8+V2OKUvXgH8bCS z<9L2Mv$JrdrrVI_Iul)h#yC+FHS&JC`rB7Zzl>V|=_i zy>YHX4*Cyj!GBiHRK(8`z<-h?34*{_{@d>E{K1W-C6>ZBmX-=t*ekNfQk1D?EJMAK zs;_@OJba)%)xOf){5Tvw%;f@3Cn3Zo2>m|a51X61Zfl&GQLCJ`O*#a7E7tF5N?U&&)ah`77kF+OgKM0AH~M#)hK`sH)& z^7LQLIks3OqbtUJmMf&UOgD`Q&Ff}rE{l?NO@AX;2nDr^AP63hhuwc#defCknXsG8 znz0fd&$DaS=>8*w%**n``uZQ2E`8b6_2lBkvE}8Rbh`ZLYA>qK+ai&Ud-t^br=WO@ z&VLkxvSL_Q(A{>>^A^ntM?L84ULhrAL$GAZ*s}V9%fAu9ED+SX|0GG`c{6u`C6_np z{xh_EYA99(9c(mKabc}k@y5ov;o+3aMQ`f!&Q6Zwp6&1Z9S%asd6#RbrKPK`ZY3W7 zeq)0oFvdkr3ieQ_ePTk4#pn)DFVLyyE4uTlu2To+1A9OH*}`H4^$MYS(NDLQ)?BdA zj-iD|wUe}Jv1H2F&-CeRIaxq~pmuS&T;=%BPyxl_q@m|?^up%sSgBYn3!%$>eY*Z5 zgp94M5JFBl9MMch62+}l>Tx(MA0EYXX(rhukn(K$Ok{d{n6pJ9`y&u;JcdOw(*{kW;=m+kG_fxy_xN-~>e@n1P? zjEwm2-#@XoR?c9}SZnIH)+_IAJ$l-jO!MsiBS!Xy(5vXSQ<2q0_Ds!T;^spOJPQOh zN-md+Mx*IUJZ&PXoiBwCT^Qy}Y5iJn++`;cJyTO|2Elyl_fKwat|k&*yL~O0{APW9 zz~^K4pP`o@ipw85oohF5#sh&WjJew}`>(U!!S}c9wk*5`VU$8m1A+h((wuma2SX5qY{T83gVwtPgf7@u(-+HCU!1JTo`S$g<(An?V@ zmy80-qj)cZGCR~N!>3Yh4y(N|5b#<#)bk%y9 zfpG!T+)ELrU!|aDO3c3gp+0ZoSz!LvcqkCSf?PvGgWYbga@-1T8MRa_EwZAx(BJ?1 z%o*$cPsn82CMWCX=c^E_#gpoLJM!bx)^vtD-oG!)W|~)^fIkWaKr)#W1i{2}!E%`1 z**TW6GzF8*dKVVrUT@s8V-C;nU%221h3uiwQHPQfLTK0VNpE=mUspDFoGobCOe4Yx zLI_8CdNBe506_KeyA#obxStY{>Hl_T1_c5D0H{r{BNPAtK#lSr)bO3(uA>(R00000 LNkvXXu0mjf+Wh85 literal 0 HcmV?d00001 diff --git a/tmux/powerline/img/right-status_weather_battery.png b/tmux/powerline/img/right-status_weather_battery.png new file mode 100644 index 0000000000000000000000000000000000000000..77442d8f20189ae067e8dc9090ca35cd7148004f GIT binary patch literal 1625 zcmV-f2B!ImP)X0ssI2VxPxr00001b5ch_0Itp) z=>Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RX1`rT68Z`t=cK`qd>q$gGRCwC$ z+h0suRU8NKUvF>kZE1nJQpzYLtzu=6EzSk9$aI=4`{QEJEG|pXn8j?-caz2WXMY}? z^Fd!H5Y1d>)Fryim@IoS=ycPJm(4Atk`)+?($bAVFD-4MK6Db+`|q?MH0ApVA%}AA zJ?C7S^X)m8YoO*<0ssJ5tvFl)002M`0ssIY2mt^95QG2#00=?=000Cb0001j5C8xG zK?nc2k%c!;3@!=Jd3~|?Pw{U{z#nZb^q?7UM0li4M&eI zPg{Ps6uK`?PV*)IJ}knK226IW2mwl;)yyB<)l@wFnKTL?)^E|R)=^WlgpJ9iYZrn z@0Evz6X&&F$(H8}O78RKBc8T9V!2v{J=N9cBazum#%r+FLRSS3K&GX>n?*uB%HJ8&hoV!~`)Un~9eXEkG6 zimm6g#nMB@GwY6v@hIJq7I5bI3i5%lTzLc`z-nQ)iU)T#IV#M`zrOCKZ(GQerhV7w zhm8~yY1d79{vU-D%t<@7S2QD#h$1G-5zm%U!KzW`rX+pf^L;ir7)d5YjyvS_em*p$ zk%9}eEnAjnn>+;-%S6OaOn5pwP0^_CWL?07o5Syx8tbGBSF1B@Z7H^%lLst4)IPIz z3KkIdx+5)Y6p9&{a~?+68U-j>j&k$cFEy*CAQ25XC_|Lw>6=!Hi9|#}M}dtoWMRl; zeZT%W?Gz-UK1u2t8Tq57<&%bnOB**HzkT~&Dz*5lAx}s7>!xVbbLx~@3aZV*C-(=k zUpdpU_N4q|?R0a!RyHsO(qh6m-`FUuEtZioo>{lUh4m0CLV(ibth5~5*;G*`XjN(+ zr7MpU5vBk8OxzU8BlhOYIRz!dLiv&UwtKu;`@|pldHI$VF zS%Maobaa5DwRMb@7vv+ViY@%TB&_(OqLTtesx(o%->LizOT6dxi_U!FZI~ zx^VtH?36eOZ2BD6V3SA7qE^o`S|L7mvkl5dU5 z%a7`IZO~0YB03%n646>we2`98^88pbc|H=6W@ojJT9|?h!!KvsQ(N_g3)(5DmNW%y z$L-iO{^ccih9MjjQ!uZi6z`?U&m-R~Wm#$I<}Uk4HTp0A%t4xWNfCqqKty!*m%v*) z)_JOII`wwnpaBPkD#$uR`>qj}QC$MgN1ZOEIDGf+U&lPp_M0EmU&{(YdsWp7y}dgf zj-SWJ4|~1GgTa}(IhGV$jM0t`cXzjWcz7{WHsev>{aUl9ZS36Tnwb>Go`Q@^pPZu< z579l(BG*{?j&x<=9w9(!iYL?E7jF%WP3e6Yo}<0J#AT@cI#nbV)nv|p%{sf1 z`?|RP?YDQ_?lYm#U?Nc^2*WcoUyO{r>U6TFU|x?&EUZ6ku?!zL5chhuGiFKtI^&bV z#onsdwu}j;IrbFHH<*h7%SiJY-ID(;h{)jg`!Qtzlq!Me-rUyMu(ndC-lZnmeoH6h z)Ru<%JU)@&j3?ZiuUnlgoj>gLempS17-LyEPf%#A6xHf*$z<*6(`Ehrx^uDOLQwty zfJQ7iE0f!wiJtq-l}vNGp_{V}tM=FfHKeEiQYR`rN;K{V`IeZR+kFv3ywlnfevRaj^{> z#Bf*$hyU-Uq=Yd%A->!i>APc_%an2!7VSu*MzevMTQO4r0IVQ)MdCq%k0p7GbVd9N X+;|@=TmCVc00000NkvXXu0mjf!O{IY literal 0 HcmV?d00001 diff --git a/tmux/powerline/lib/arg_processing.sh b/tmux/powerline/lib/arg_processing.sh new file mode 100644 index 0000000..c43f454 --- /dev/null +++ b/tmux/powerline/lib/arg_processing.sh @@ -0,0 +1,9 @@ +#! Check script arguments. + +check_arg_side() { + local side="$1" + if ! [ "$side" == "left" -o "$side" == "right" ]; then + echo "Argument must be the side to handle {left, right} and not \"${side}\"." + exit 1 + fi +} diff --git a/tmux/powerline/lib/formatting.sh b/tmux/powerline/lib/formatting.sh new file mode 100644 index 0000000..d891863 --- /dev/null +++ b/tmux/powerline/lib/formatting.sh @@ -0,0 +1,5 @@ +__print_colored_content() { + echo -n "#[fg=colour$3, bg=colour$2]" + echo -n "$1" + echo -n "#[default]" +} diff --git a/tmux/powerline/lib/muting.sh b/tmux/powerline/lib/muting.sh new file mode 100644 index 0000000..595ba87 --- /dev/null +++ b/tmux/powerline/lib/muting.sh @@ -0,0 +1,20 @@ +# Muting Logic +# In all cases $1 is the side to be muted (eg left/right). + +powerline_muted() { + [ -e "$(__powerline_mute_file $1)" ]; +} + +toggle_powerline_mute_status() { + if powerline_muted $1; then + rm "$(__powerline_mute_file $1)" + else + touch "$(__powerline_mute_file $1)" + fi +} + +__powerline_mute_file() { + local tmux_session=$(tmux display -p "#S") + + echo -n "${TMUX_POWERLINE_DIR_TEMPORARY}/mute_${tmux_session}_$1" +} diff --git a/tmux/powerline/lib/powerline.sh b/tmux/powerline/lib/powerline.sh new file mode 100644 index 0000000..3a3fb68 --- /dev/null +++ b/tmux/powerline/lib/powerline.sh @@ -0,0 +1,142 @@ +# Library functions + +print_powerline() { + local side="$1" + local upper_side=$(echo "$1" | tr '[:lower:]' '[:upper:]') + eval "local input_segments=(\"\${TMUX_POWERLINE_${upper_side}_STATUS_SEGMENTS[@]}\")" + local powerline_segments=() + local powerline_segment_contents=() + + __check_platform + + __process_segment_defaults + __process_scripts + __process_colors + + __process_powerline +} + +__process_segment_defaults() { + for segment_index in "${!input_segments[@]}"; do + local input_segment=(${input_segments[$segment_index]}) + eval "local default_separator=\$TMUX_POWERLINE_DEFAULT_${upper_side}SIDE_SEPARATOR" + + powerline_segment_with_defaults=( + ${input_segment[0]:-"no_script"} \ + ${input_segment[1]:-$TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR} \ + ${input_segment[2]:-$TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR} \ + ${input_segment[3]:-$default_separator} \ + ) + + powerline_segments[$segment_index]="${powerline_segment_with_defaults[@]}" + done +} + +__process_scripts() { + for segment_index in "${!powerline_segments[@]}"; do + local powerline_segment=(${powerline_segments[$segment_index]}) + + if [ -n "$TMUX_POWERLINE_DIR_USER_SEGMENTS" ] && [ -f "$TMUX_POWERLINE_DIR_USER_SEGMENTS/${powerline_segment[0]}.sh" ] ; then + local script="$TMUX_POWERLINE_DIR_USER_SEGMENTS/${powerline_segment[0]}.sh" + else + local script="$TMUX_POWERLINE_DIR_SEGMENTS/${powerline_segment[0]}.sh" + fi + + export TMUX_POWERLINE_CUR_SEGMENT_BG="${powerline_segment[1]}" + export TMUX_POWERLINE_CUR_SEGMENT_FG="${powerline_segment[2]}" + source "$script" + local output + output=$(run_segment) + local exit_code="$?" + unset -f run_segment + + if [ "$exit_code" -ne 0 ] && debug_mode_enabled ; then + local seg_name="${script##*/}" + echo "Segment '${seg_name}' exited with code ${exit_code}. Aborting." + exit 1 + fi + + if [ -n "$output" ]; then + powerline_segment_contents[$segment_index]=" $output " + else + unset -v powerline_segments[$segment_index] + fi + done +} + +__process_colors() { + for segment_index in "${!powerline_segments[@]}"; do + local powerline_segment=(${powerline_segments[$segment_index]}) + # Find the next segment that produces content (i.e. skip empty segments). + for next_segment_index in $(eval echo {$(($segment_index + 1))..${#powerline_segments}}) ; do + [[ -n ${powerline_segments[next_segment_index]} ]] && break + done + local next_segment=(${powerline_segments[$next_segment_index]}) + + if [ $side == 'left' ]; then + powerline_segment[4]=${next_segment[1]:-$TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR} + elif [ $side == 'right' ]; then + powerline_segment[4]=${previous_background_color:-$TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR} + fi + + if __segment_separator_is_thin; then + powerline_segment[5]=${powerline_segment[2]} + else + powerline_segment[5]=${powerline_segment[1]} + fi + + local previous_background_color=${powerline_segment[1]} + + powerline_segments[$segment_index]="${powerline_segment[@]}" + done +} + +__process_powerline() { + for segment_index in "${!powerline_segments[@]}"; do + local powerline_segment=(${powerline_segments[$segment_index]}) + + local background_color=${powerline_segment[1]} + local foreground_color=${powerline_segment[2]} + local separator=${powerline_segment[3]} + local separator_background_color=${powerline_segment[4]} + local separator_foreground_color=${powerline_segment[5]} + + eval "__print_${side}_segment ${segment_index} ${background_color} ${foreground_color} ${separator} ${separator_background_color} ${separator_foreground_color}" + done +} + +__print_left_segment() { + local content=${powerline_segment_contents[$1]} + local content_background_color=$2 + local content_foreground_color=$3 + local separator=$4 + local separator_background_color=$5 + local separator_foreground_color=$6 + + __print_colored_content "$content" $content_background_color $content_foreground_color + __print_colored_content $separator $separator_background_color $separator_foreground_color +} + +__print_right_segment() { + local content=${powerline_segment_contents[$1]} + local content_background_color=$2 + local content_foreground_color=$3 + local separator=$4 + local separator_background_color=$5 + local separator_foreground_color=$6 + + __print_colored_content $separator $separator_background_color $separator_foreground_color + __print_colored_content "$content" $content_background_color $content_foreground_color +} + +__segment_separator_is_thin() { + [[ ${powerline_segment[3]} == $TMUX_POWERLINE_SEPARATOR_LEFT_THIN || \ + ${powerline_segment[3]} == $TMUX_POWERLINE_SEPARATOR_RIGHT_THIN ]]; +} + +__check_platform() { + if [ "$SHELL_PLATFORM" == "unknown" ] && debug_mode_enabled; then + echo "Unknown platform; modify config/shell.sh" &1>&2 + fi +} + diff --git a/tmux/powerline/lib/rcfile.sh b/tmux/powerline/lib/rcfile.sh new file mode 100644 index 0000000..b4ebe2c --- /dev/null +++ b/tmux/powerline/lib/rcfile.sh @@ -0,0 +1,68 @@ +# Read user rc file. + +process_settings() { + __read_rcfile + + if [ -z "$TMUX_POWERLINE_DEBUG_MODE_ENABLED" ]; then + export TMUX_POWERLINE_DEBUG_MODE_ENABLED="${TMUX_POWERLINE_DEBUG_MODE_ENABLED_DEFAULT}" + fi + + if [ -z "$TMUX_POWERLINE_PATCHED_FONT_IN_USE" ]; then + export TMUX_POWERLINE_PATCHED_FONT_IN_USE="${TMUX_POWERLINE_PATCHED_FONT_IN_USE_DEFAULT}" + fi + + if [ -z "$TMUX_POWERLINE_THEME" ]; then + export TMUX_POWERLINE_THEME="${TMUX_POWERLINE_THEME_DEFAULT}" + fi + + eval TMUX_POWERLINE_DIR_USER_SEGMENTS="$TMUX_POWERLINE_DIR_USER_SEGMENTS" + eval TMUX_POWERLINE_DIR_USER_THEMES="$TMUX_POWERLINE_DIR_USER_THEMES" + if [ -n "$TMUX_POWERLINE_DIR_USER_THEMES" ] && [ -f "${TMUX_POWERLINE_DIR_USER_THEMES}/${TMUX_POWERLINE_THEME}.sh" ]; then + source "${TMUX_POWERLINE_DIR_USER_THEMES}/${TMUX_POWERLINE_THEME}.sh" + else + source "${TMUX_POWERLINE_DIR_THEMES}/${TMUX_POWERLINE_THEME}.sh" + fi + +} + +generate_default_rc() { + read -d '' rccontents << EORC +# Default configuration file for tmux-powerline. +# Modeline { +# vi: foldmarker={,} foldmethod=marker foldlevel=0 tabstop=4 filetype=sh +# } + +# General { + # Show which segment fails and its exit code. + export TMUX_POWERLINE_DEBUG_MODE_ENABLED="${TMUX_POWERLINE_DEBUG_MODE_ENABLED_DEFAULT}" + # Use patched font symbols. + export TMUX_POWERLINE_PATCHED_FONT_IN_USE="${TMUX_POWERLINE_PATCHED_FONT_IN_USE_DEFAULT}" + # The theme to use. + export TMUX_POWERLINE_THEME="${TMUX_POWERLINE_THEME_DEFAULT}" + # Overlay directory to look for themes. There you can put your own themes outside the repo. Fallback will still be the "themes" directory in the repo. + export TMUX_POWERLINE_DIR_USER_THEMES="" + # Overlay directory to look for segments. There you can put your own segments outside the repo. Fallback will still be the "segments" directory in the repo. + export TMUX_POWERLINE_DIR_USER_SEGMENTS="" +# } +EORC + + for segment in ${TMUX_POWERLINE_DIR_SEGMENTS}/*.sh; do + source "$segment" + if declare -f generate_segmentrc >/dev/null; then + segmentrc=$(generate_segmentrc | sed -e 's/^/\\t/g') + unset -f generate_segmentrc + local seg_name="${segment##*/}" + rccontents="${rccontents}\n\n# ${seg_name} {\n${segmentrc}\n# }" + fi + done + + echo -e "$rccontents" > "$TMUX_POWERLINE_RCFILE_DEFAULT" + echo "Default configuration file generated to: ${TMUX_POWERLINE_RCFILE_DEFAULT}" + echo "Copy/move it to \"${TMUX_POWERLINE_RCFILE}\" and make your changes." +} + +__read_rcfile() { + if [ -f "$TMUX_POWERLINE_RCFILE" ]; then + source "$TMUX_POWERLINE_RCFILE" + fi +} diff --git a/tmux/powerline/lib/text_roll.sh b/tmux/powerline/lib/text_roll.sh new file mode 100644 index 0000000..e53247f --- /dev/null +++ b/tmux/powerline/lib/text_roll.sh @@ -0,0 +1,63 @@ +# Rolling anything what you want. +# arg1: text to roll. +# arg2: max length to display. +# arg3: roll speed in characters per second. +roll_text() { + local text="$1" # Text to print + + if [ -z "$text" ]; then + return; + fi + + local max_len="10" # Default max length. + + if [ -n "$2" ]; then + max_len="$2" + fi + + local speed="1" # Default roll speed in chars per second. + + if [ -n "$3" ]; then + speed="$3" + fi + + # Skip rolling if the output is less than max_len. + if [ "${#text}" -le "$max_len" ]; then + echo "$text" + return + fi + + # Anything starting with 0 is an Octal number in Shell,C or Perl, + # so we must explicitly state the base of a number using base#number + local offset=$((10#$(date +%s) * ${speed} % ${#text})) + + # Truncate text. + text=${text:offset} + + local char # Character. + local bytes # The bytes of one character. + local index + + for ((index=0; index < max_len; index++)); do + char=${text:index:1} + bytes=$(echo -n $char | wc -c) + # The character will takes twice space + # of an alphabet if (bytes > 1). + if ((bytes > 1)); then + max_len=$((max_len - 1)) + fi + done + + text=${text:0:max_len} + + #echo "index=${index} max=${max_len} len=${#text}" + # How many spaces we need to fill to keep + # the length of text that will be shown? + local fill_count=$((${index} - ${#text})) + + for ((index=0; index < fill_count; index++)); do + text="${text} " + done + + echo "${text}" +} diff --git a/tmux/powerline/lib/tmux_adapter.sh b/tmux/powerline/lib/tmux_adapter.sh new file mode 100644 index 0000000..17674e4 --- /dev/null +++ b/tmux/powerline/lib/tmux_adapter.sh @@ -0,0 +1,12 @@ +# Get the current path in the segment. +get_tmux_cwd() { + local env_name=$(tmux display -p "TMUXPWD_#D" | tr -d %) + local env_val=$(tmux show-environment | grep --color=never "$env_name") + # The version below is still quite new for tmux. Uncomment this in the future :-) + #local env_val=$(tmux show-environment "$env_name" 2>&1) + + if [[ ! $env_val =~ "unknown variable" ]]; then + local tmux_pwd=$(echo "$env_val" | sed 's/^.*=//') + echo "$tmux_pwd" + fi +} diff --git a/tmux/powerline/mute_powerline.sh b/tmux/powerline/mute_powerline.sh new file mode 100755 index 0000000..0c9316f --- /dev/null +++ b/tmux/powerline/mute_powerline.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +export TMUX_POWERLINE_DIR_HOME="$(dirname $0)" +source "${TMUX_POWERLINE_DIR_HOME}/config/paths.sh" +source "${TMUX_POWERLINE_DIR_LIB}/muting.sh" +source "${TMUX_POWERLINE_DIR_LIB}/arg_processing.sh" + +side="$1" +check_arg_side "$side" +toggle_powerline_mute_status "$side" diff --git a/tmux/powerline/powerline.sh b/tmux/powerline/powerline.sh new file mode 100755 index 0000000..92c0414 --- /dev/null +++ b/tmux/powerline/powerline.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +export TMUX_POWERLINE_DIR_HOME="$(dirname $0)" + +source "${TMUX_POWERLINE_DIR_HOME}/config/helpers.sh" +source "${TMUX_POWERLINE_DIR_HOME}/config/paths.sh" +source "${TMUX_POWERLINE_DIR_HOME}/config/shell.sh" +source "${TMUX_POWERLINE_DIR_HOME}/config/defaults.sh" + +source "${TMUX_POWERLINE_DIR_LIB}/arg_processing.sh" +source "${TMUX_POWERLINE_DIR_LIB}/formatting.sh" +source "${TMUX_POWERLINE_DIR_LIB}/muting.sh" +source "${TMUX_POWERLINE_DIR_LIB}/powerline.sh" +source "${TMUX_POWERLINE_DIR_LIB}/rcfile.sh" + +if ! powerline_muted "$1"; then + process_settings + check_arg_side "$1" + print_powerline "$1" +fi + +exit 0 diff --git a/tmux/powerline/segments/Makefile b/tmux/powerline/segments/Makefile new file mode 100644 index 0000000..07767b5 --- /dev/null +++ b/tmux/powerline/segments/Makefile @@ -0,0 +1,18 @@ +# Build the small MPD NP program. +# Enable debug printing with $ make -e DEBUG=1 +DEBUG=0 +CC = $(shell hash clang 2>/dev/null && echo clang || echo gcc) +CFLAGS = -O3 -Wall -std=c99 -I /usr/include/ -D DEBUG=${DEBUG} +LDLIBS = -lmpdclient +XKB_LAYOUT_LDLIBS= -lX11 + +.PHONY: all clean + +all: np_mpd xkb_layout + +xkb_layout: xkb_layout.c + $(CC) $(CFLAGS) $(LDFLAGS) $< $(XKB_LAYOUT_LDLIBS) -o $@ + +clean: + $(RM) np_mpd + $(RM) xkb_layout diff --git a/tmux/powerline/segments/battery.sh b/tmux/powerline/segments/battery.sh new file mode 100755 index 0000000..b0ee362 --- /dev/null +++ b/tmux/powerline/segments/battery.sh @@ -0,0 +1,150 @@ +# LICENSE This code is not under the same license as the rest of the project as it's "stolen". It's cloned from https://github.com/richoH/dotfiles/blob/master/bin/battery and just some modifications are done so it works for my laptop. Check that URL for more recent versions. + +TMUX_POWERLINE_SEG_BATTERY_TYPE_DEFAULT="percentage" +TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS_DEFAULT=5 + +HEART_FULL="♥" +HEART_EMPTY="♡" + +generate_segmentrc() { + read -d '' rccontents << EORC +# How to display battery remaining. Can be {percentage, cute}. +export TMUX_POWERLINE_SEG_BATTERY_TYPE="${TMUX_POWERLINE_SEG_BATTERY_TYPE_DEFAULT}" +# How may hearts to show if cute indicators are used. +export TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS="${TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS_DEFAULT}" +EORC + echo "$rccontents" +} + +run_segment() { + __process_settings + if shell_is_osx; then + battery_status=$(__battery_osx) + else + battery_status=$(__battery_linux) + fi + [ -z "$battery_status" ] && return + + case "$TMUX_POWERLINE_SEG_BATTERY_TYPE" in + "percentage") + output="${HEART_FULL} ${battery_status}%" + ;; + "cute") + output=$(__cutinate $battery_status) + esac + if [ -n "$output" ]; then + echo "$output" + fi +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_BATTERY_TYPE" ]; then + export TMUX_POWERLINE_SEG_BATTERY_TYPE="${TMUX_POWERLINE_SEG_BATTERY_TYPE_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS" ]; then + export TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS="${TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS_DEFAULT}" + fi +} + +__battery_osx() { + ioreg -c AppleSmartBattery -w0 | \ + grep -o '"[^"]*" = [^ ]*' | \ + sed -e 's/= //g' -e 's/"//g' | \ + sort | \ + while read key value; do + case $key in + "MaxCapacity") + export maxcap=$value;; + "CurrentCapacity") + export curcap=$value;; + "ExternalConnected") + export extconnect=$value;; + "FullyCharged") + export fully_charged=$value;; + esac + if [[ -n $maxcap && -n $curcap && -n $extconnect ]]; then + if [[ "$curcap" == "$maxcap" || "$fully_charged" == "Yes" && $extconnect == "Yes" ]]; then + return + fi + charge=`pmset -g batt | grep -o "[0-9][0-9]*\%" | rev | cut -c 2- | rev` + if [[ "$extconnect" == "Yes" ]]; then + echo "$charge" + else + if [[ $charge -lt 50 ]]; then + echo -n "#[fg=red]" + fi + echo "$charge" + fi + break + fi + done + } + + __battery_linux() { + case "$SHELL_PLATFORM" in + "linux") + BATPATH=/sys/class/power_supply/BAT0 + if [ ! -d $BATPATH ]; then + BATPATH=/sys/class/power_supply/BAT1 + fi + STATUS=$BATPATH/status + BAT_FULL=$BATPATH/charge_full + if [ ! -r $BAT_FULL ]; then + BAT_FULL=$BATPATH/energy_full + fi + BAT_NOW=$BATPATH/charge_now + if [ ! -r $BAT_NOW ]; then + BAT_NOW=$BATPATH/energy_now + fi + + if [ "$1" = `cat $STATUS` -o "$1" = "" ]; then + __linux_get_bat + fi + ;; + "bsd") + STATUS=`sysctl -n hw.acpi.battery.state` + case $1 in + "Discharging") + if [ $STATUS -eq 1 ]; then + __freebsd_get_bat + fi + ;; + "Charging") + if [ $STATUS -eq 2 ]; then + __freebsd_get_bat + fi + ;; + "") + __freebsd_get_bat + ;; + esac + ;; + esac + } + + __cutinate() { + perc=$1 + inc=$(( 100 / $TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS )) + + + for i in `seq $TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS`; do + if [ $perc -lt 99 ]; then + echo -n $HEART_EMPTY + else + echo -n $HEART_FULL + fi + echo -n " " + perc=$(( $perc + $inc )) + done + } + + __linux_get_bat() { + bf=$(cat $BAT_FULL) + bn=$(cat $BAT_NOW) + echo $(( 100 * $bn / $bf )) + } + + __freebsd_get_bat() { + echo "$(sysctl -n hw.acpi.battery.life)" + + } diff --git a/tmux/powerline/segments/cpu.sh b/tmux/powerline/segments/cpu.sh new file mode 100755 index 0000000..637bcda --- /dev/null +++ b/tmux/powerline/segments/cpu.sh @@ -0,0 +1,22 @@ +# Prints the CPU usage: user% sys% idle. + +run_segment() { + if shell_is_linux; then + cpu_line=$(top -b -n 1 | grep "Cpu(s)" ) + cpu_user=$(echo "$cpu_line" | grep -Po "(\d+(.\d+)?)(?=%?\s?(us(er)?))") + cpu_system=$(echo "$cpu_line" | grep -Po "(\d+(.\d+)?)(?=%?\s?(sys?))") + cpu_idle=$(echo "$cpu_line" | grep -Po "(\d+(.\d+)?)(?=%?\s?(id(le)?))") + elif shell_is_osx; then + cpus_line=$(top -e -l 1 | grep "CPU usage:" | sed 's/CPU usage: //') + cpu_user=$(echo "$cpus_line" | awk '{print $1}' | sed 's/%//' ) + cpu_system=$(echo "$cpus_line" | awk '{print $3}'| sed 's/%//' ) + cpu_idle=$(echo "$cpus_line" | awk '{print $5}' | sed 's/%//' ) + fi + + if [ -n "$cpu_user" ] && [ -n "$cpu_system" ] && [ -n "$cpu_idle" ]; then + echo "${cpu_user}, ${cpu_system}, ${cpu_idle}" | awk -F', ' '{printf("%5.1f,%5.1f,%5.1f",$1,$2,$3)}' + return 0 + else + return 1 + fi +} diff --git a/tmux/powerline/segments/date.sh b/tmux/powerline/segments/date.sh new file mode 100755 index 0000000..32263d5 --- /dev/null +++ b/tmux/powerline/segments/date.sh @@ -0,0 +1,23 @@ +# Print the current date. + +TMUX_POWERLINE_SEG_DATE_FORMAT_DEFAULT="%F" + +generate_segmentrc() { + read -d '' rccontents << EORC +# date(1) format for the date. If you don't, for some reason, like ISO 8601 format you might want to have "%D" or "%m/%d/%Y". +export TMUX_POWERLINE_SEG_DATE_FORMAT="${TMUX_POWERLINE_SEG_DATE_FORMAT_DEFAULT}" +EORC + echo "$rccontents" +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_DATE_FORMAT" ]; then + export TMUX_POWERLINE_SEG_DATE_FORMAT="${TMUX_POWERLINE_SEG_DATE_FORMAT_DEFAULT}" + fi +} + +run_segment() { + __process_settings + date +"$TMUX_POWERLINE_SEG_DATE_FORMAT" + return 0 +} diff --git a/tmux/powerline/segments/date_day.sh b/tmux/powerline/segments/date_day.sh new file mode 100755 index 0000000..35a42eb --- /dev/null +++ b/tmux/powerline/segments/date_day.sh @@ -0,0 +1,6 @@ +# Prints the name of the current day. + +run_segment() { + date +"%a" + return 0 +} diff --git a/tmux/powerline/segments/earthquake.sh b/tmux/powerline/segments/earthquake.sh new file mode 100755 index 0000000..3859094 --- /dev/null +++ b/tmux/powerline/segments/earthquake.sh @@ -0,0 +1,173 @@ +# Prints the most recent earthquake (currently only supports japan) +# It prints the location, time, and magnitude if the quake happened within +# a timelimit and magnitude threshold + +earthquake_symbol='#[fg=colour1]~' + +# The update period in seconds. +update_period=600 + +TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER_DEFAULT="goo" +TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD_DEFAULT="600" +TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW_DEFAULT="60" +TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT_DEFAULT='(%H:%M)' +TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE_DEFAULT='3' + +generate_segmentrc() { + read -d '' rccontents << EORC +# The data provider to use. Currently only "goo" is supported. +export TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER="${TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER_DEFAULT}" +# How often to update the earthquake data in seconds. +# Note: This is not an early warning detector, use this +# to be informed about recent earthquake magnitudes in your +# area. If this is too often, goo may decide to ban you form +# their server +export TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD_DEFAULT}" +# Only display information when earthquakes are within this many minutes +export TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW="${TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW_DEFAULT}" +# Display time with this format +export TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT='${TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT_DEFAULT}' +# Display only if magnitude is greater or equal to this number +export TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE="${TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE_DEFAULT}" +EORC + echo "$rccontents" +} + +run_segment() { + __process_settings + local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/earthquake.txt" + local earthquake + case "$TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER" in + "goo") earthquake=$(__goo_earthquake) ;; + *) + echo "Unknown earthquake-information provider [${$TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER}]"; + return 1 + esac + if [ -n "$earthquake" ]; then + echo "$earthquake_symbol #[fg=colour237]${earthquake}" + fi +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER" ]; then + export TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER="${TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD" ]; then + export TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW" ]; then + export TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW="${TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT" ]; then + export TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT="${TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE" ]; then + export TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE="${TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE_DEFAULT}" + fi +} + +__goo_earthquake() { + location="" + magnitude="" + magnitude_number="" + timestamp="" + if [[ -f "$tmp_file" ]]; then + if shell_is_osx || shell_is_bsd; then + last_update=$(stat -f "%m" ${tmp_file}) + elif shell_is_linux; then + last_update=$(stat -c "%Y" ${tmp_file}) + fi + time_now=$(date +%s) + + up_to_date=$(echo "(${time_now}-${last_update}) < ${update_period}" | bc) + if [ "$up_to_date" -eq 1 ]; then + __read_tmp_file + fi + fi + + if [ -z "$magnitude" ]; then + # get the rss file, convert encoding to UTF-8, then delete windows carriage-returns + earthquake_data=$(curl --max-time 4 -s "http://weather.goo.ne.jp/earthquake/index.rdf" | iconv -f EUC-JP -t UTF-8 | tr -d "\r") + if [ "$?" -eq "0" ]; then + # This rss feed is not very clean or easy to use, but we will use it because + # this is all that can be found for now + + # we grab the data from the title of the first item (most recent earthquake) + earthquake_data=${earthquake_data#*item\>} + # end our data at the end of the approx. time + earthquake_data=${earthquake_data%%頃*} + + # pluck our data + location=$(echo $earthquake_data | awk '{print $2}') + magnitude=$(echo $earthquake_data | awk '{print $4}') + timestamp=${earthquake_data#*\(} + + __convert_jp_magnitude + __convert_jp_timestamp + + echo $location > $tmp_file + echo $magnitude >> $tmp_file + echo $timestamp >> $tmp_file + elif [ -f "$tmp_file" ]; then + __read_tmp_file + fi + fi + __convert_timestamp_to_fmt + + # extract the numerical portion of magnitude + magnitude_number=$(echo $magnitude | sed -e 's/+//' -e 's/-//') + + if [ -n "$magnitude" ]; then + if __check_alert_time_window && __check_min_magnitude ; then + echo "${location}${timestamp_fmt}:#[fg=colour0]${magnitude}" + fi + fi +} + +__convert_jp_magnitude() { + magnitude=${magnitude#震度} + # simplify high-lower designation (only used in extreme cases: above 4) + if [[ "$magnitude" == *弱 ]] ; then + magnitude="-${magnitude%弱}" + elif [[ "$magnitude" == *強 ]] ; then + magnitude="+${magnitude%強}" + fi +} + +__check_alert_time_window() { + [[ $(( ( $(date +%s) - $timestamp ) / 60 )) -lt $TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW ]] +} + +__check_min_magnitude() { + [[ $magnitude_number -ge $TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE ]] +} + +__convert_jp_timestamp() { + if shell_is_osx ; then + timestamp=$(date -j -f "%Y年%m月%d日 %H時%M分" "$timestamp" +"%s") + else + timestamp=$(echo $timestamp | $sed -e 's/年/-/' -e 's/月/-/' -e 's/日//' -e 's/時/:/' -e 's/分//') + timestamp=$(date -d "$timestamp" +"%s") + fi +} + +__convert_timestamp_to_fmt() { + if shell_is_osx ; then + timestamp_fmt=$(date -r "$timestamp" +"$TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT") + else + timestamp_fmt=$(date -d "$timestamp" +"$TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT") + fi +} + +__read_tmp_file() { + if [ ! -f "$tmp_file" ]; then + return + fi + IFS_bak="$IFS" + IFS=$'\n' + lines=($(cat ${tmp_file})) + IFS="$IFS_bak" + location="${lines[0]}" + magnitude="${lines[1]}" + timestamp="${lines[2]}" +} diff --git a/tmux/powerline/segments/hostname.sh b/tmux/powerline/segments/hostname.sh new file mode 100755 index 0000000..c3dfbf9 --- /dev/null +++ b/tmux/powerline/segments/hostname.sh @@ -0,0 +1,31 @@ +# Prints the hostname. + +TMUX_POWERLINE_SEG_HOSTNAME_FORMAT_DEFAULT="short" + +generate_segmentrc() { + read -d '' rccontents << EORC +# Use short or long format for the hostname. Can be {"short, long"}. +export TMUX_POWERLINE_SEG_HOSTNAME_FORMAT="${TMUX_POWERLINE_SEG_HOSTNAME_FORMAT_DEFAULT}" +EORC + echo "$rccontents" +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_HOSTNAME_FORMAT" ]; then + export TMUX_POWERLINE_SEG_HOSTNAME_FORMAT="${TMUX_POWERLINE_SEG_HOSTNAME_FORMAT_DEFAULT}" + fi +} +run_segment() { + __process_settings + local opts="" + if [ "$TMUX_POWERLINE_SEG_HOSTNAME_FORMAT" == "short" ]; then + if shell_is_osx || shell_is_bsd; then + opts="-s" + else + opts="--short" + fi + fi + + hostname ${opts} + return 0 +} diff --git a/tmux/powerline/segments/ifstat.sh b/tmux/powerline/segments/ifstat.sh new file mode 100755 index 0000000..b004303 --- /dev/null +++ b/tmux/powerline/segments/ifstat.sh @@ -0,0 +1,39 @@ +# Show network statistics for all active interfaces found. + +run_segment() { + type ifstat >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return 1 + fi + + sed="sed" + type gsed >/dev/null 2>&1 + if [ "$?" -eq 0 ]; then + sed="gsed" + fi + + data=$(ifstat -z -S -q 1 1) + interfaces=$(echo -e "${data}" | head -n 1) + flow_data=$(echo -e "${data}" | tail -n 1 | ${sed} "s/\s\{1,\}/,/g") + index=1 + for inf in ${interfaces}; do + type="" + case ${inf} in + eth*) type="⎆" + ;; + wlan*) type="☫" + ;; + en*) type=" " + ;; + esac + if [ -n "${type}" ]; then + format=$(echo "${format} ${type} ⇊ %5.01f ⇈ %5.01f") + holder=$(echo "${holder},\$$((index)),\$$((index+1))") + fi + index=$((index+2)) + done + if [ -n "${format}" ]; then + echo $(echo "${flow_data#,}" | awk -F"," "{printf(\"${format}\"${holder})}") + fi + return 0 +} diff --git a/tmux/powerline/segments/ifstat_sys.sh b/tmux/powerline/segments/ifstat_sys.sh new file mode 100755 index 0000000..bd27fe5 --- /dev/null +++ b/tmux/powerline/segments/ifstat_sys.sh @@ -0,0 +1,42 @@ +# Show if stats by sampling /sys/. +# Originally stolen from http://unix.stackexchange.com/questions/41346/upload-download-speed-in-tmux-status-line + +run_segment() { + sleeptime="0.5" + if shell_is_osx; then + iface="en0" + type="⎆" # "☫" for wlan + RXB=$(netstat -i -b | grep -m 1 $iface | awk '{print $7}') + TXB=$(netstat -i -b | grep -m 1 $iface | awk '{print $10}') + sleep "$sleeptime" + RXBN=$(netstat -i -b | grep -m 1 $iface | awk '{print $7}') + TXBN=$(netstat -i -b | grep -m 1 $iface | awk '{print $10}') + else + iface="eth0" + type="⎆" # "☫" for wlan + RXB=$(</sys/class/net/"$iface"/statistics/rx_bytes) + TXB=$(</sys/class/net/"$iface"/statistics/tx_bytes) + sleep "$sleeptime" + RXBN=$(</sys/class/net/"$iface"/statistics/rx_bytes) + TXBN=$(</sys/class/net/"$iface"/statistics/tx_bytes) + fi + RXDIF=$(echo "$((RXBN - RXB)) / 1024 / ${sleeptime}" | bc ) + TXDIF=$(echo "$((TXBN - TXB)) / 1024 / ${sleeptime}" | bc ) + + if [ $RXDIF -gt 1024 ]; then + RXDIF=$(echo "scale=1;${RXDIF} / 1024" | bc) + RXDIF_UNIT="M/s" + else + RXDIF_UNIT="K/s" + fi + if [ $TXDIF -gt 1024 ]; then + TXDIF=$(echo "scale=1;${TXDIF} / 1024" | bc) + TXDIF_UNIT="M/s" + else + TXDIF_UNIT="K/s" + fi + + # NOTE: '%5.01' for fixed length always + printf "${type} ⇊ %5.01f${RXDIF_UNIT} ⇈ %5.01f${TXDIF_UNIT}" ${RXDIF} ${TXDIF} + return 0 +} diff --git a/tmux/powerline/segments/lan_ip.sh b/tmux/powerline/segments/lan_ip.sh new file mode 100755 index 0000000..fe97dad --- /dev/null +++ b/tmux/powerline/segments/lan_ip.sh @@ -0,0 +1,32 @@ +# Prints the local network IPv4 address for a statically defined NIC or search for an IPv4 address on all active NICs. + +run_segment() { + if shell_is_bsd || shell_is_osx ; then + all_nics=$(ifconfig 2>/dev/null | awk -F':' '/^[a-z]/ && !/^lo/ { print $1 }') + for nic in ${all_nics[@]}; do + ipv4s_on_nic=$(ifconfig ${nic} 2>/dev/null | awk '$1 == "inet" { print $2 }') + for lan_ip in ${ipv4s_on_nic[@]}; do + [[ -n "${lan_ip}" ]] && break + done + [[ -n "${lan_ip}" ]] && break + done + else + # Get the names of all attached NICs. + all_nics="$(ip addr show | cut -d ' ' -f2 | tr -d :)" + all_nics=(${all_nics[@]//lo/}) # Remove lo interface. + + for nic in "${all_nics[@]}"; do + # Parse IP address for the NIC. + lan_ip="$(ip addr show ${nic} | grep '\<inet\>' | tr -s ' ' | cut -d ' ' -f3)" + # Trim the CIDR suffix. + lan_ip="${lan_ip%/*}" + # Only display the last entry + lan_ip="$(echo "$lan_ip" | tail -1)" + + [ -n "$lan_ip" ] && break + done + fi + + echo "ⓛ ${lan_ip-N/a}" + return 0 +} diff --git a/tmux/powerline/segments/load.sh b/tmux/powerline/segments/load.sh new file mode 100755 index 0000000..7480d96 --- /dev/null +++ b/tmux/powerline/segments/load.sh @@ -0,0 +1,6 @@ +# Print the average load. + +run_segment() { + uptime | cut -d "," -f 3- | cut -d ":" -f2 | sed -e "s/^[ \t]*//" + exit 0 +} diff --git a/tmux/powerline/segments/mailcount.sh b/tmux/powerline/segments/mailcount.sh new file mode 100755 index 0000000..b4b6787 --- /dev/null +++ b/tmux/powerline/segments/mailcount.sh @@ -0,0 +1,204 @@ +# Report mail count for your mailbox type + +TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX_DEFAULT="$HOME/.mail/inbox/new" +TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX_DEFAULT="${MAIL}" +TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC_DEFAULT="${HOME}/.mailcheckrc" +TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER_DEFAULT="gmail.com" +TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL_DEFAULT="5" + + +generate_segmentrc() { + read -d '' rccontents << EORC +# Mailbox type to use. Can be any of {apple_mail, gmail, maildir, mbox, mailcheck} +export TMUX_POWERLINE_SEG_MAILCOUNT_MAILBOX_TYPE="" + +## Gmail +# Enter your Gmail username here WITH OUT @gmail.com.( OR @domain) +export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_USERNAME="" +# Google password. Recomenned to use application specific password (https://accounts.google.com/b/0/IssuedAuthSubTokens) Leave this empty to get password from OS X keychain. +# For OSX users : MAKE SURE that you add a key to the keychain in the format as follows +# Keychain Item name : http://<value-you-fill-in-server-variable-below> +# Account name : <username-below>@<server-below> +# Password : Your password ( Once again, try to use 2 step-verification and application-specific password) +# See http://support.google.com/accounts/bin/answer.py?hl=en&answer=185833 for more info. +export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_PASSWORD="" +# Domain name that will complete your email. For normal GMail users it probably is "gmail.com but can be "foo.tld" for Google Apps users. +export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER="${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER_DEFAULT}" +# How often in minutes to check for new mails. +export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL="${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL_DEFAULT}" + +## Maildir +# Path to the maildir to check. +export TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX="${TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX_DEFAULT}" + +## mbox +# Path to the mbox to check. +export TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX="${TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX_DEFAULT}" + +## mailcheck +# Optional path to mailcheckrc +export TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC="${TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC_DEFAULT}" +EORC + echo "${rccontents}" +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER" ]; then + export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER="${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL" ]; then + export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL="${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL_DEFAULT}" + fi + + eval TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX="$TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX" + if [ -z "$TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX" ]; then + export TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX="${TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX_DEFAULT}" + fi + + eval TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX="$TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX" + if [ -z "${TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX}" ]; then + export TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX="${TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX_DEFAULT}" + fi + + eval TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC="$TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC" + if [ -z "${TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC}" ]; then + export TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC="${TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC_DEFAULT}" + fi + +} + +run_segment() { + __process_settings + + if [ -z "$TMUX_POWERLINE_SEG_MAILCOUNT_MAILBOX_TYPE" ]; then + return 2 + fi + + local count + case "$TMUX_POWERLINE_SEG_MAILCOUNT_MAILBOX_TYPE" in + "apple_mail") count=$(__count_apple_mail) ;; + "gmail") count=$(__count_gmail) ;; + "maildir") count=$(__count_maildir) ;; + "mbox") count=$(__count_mbox) ;; + "mailcheck") count=$(__count_mailcheck) ;; + *) + echo "Unknown mailbox type [${TMUX_POWERLINE_SEG_MAILCOUNT_MAILBOX_TYPE}]"; + return 1 + esac + local exitcode="$?" + if [ "$exitcode" -ne 0 ]; then + return $exitcode + fi + + if [[ -n "$count" && "$count" -gt 0 ]]; then + echo "✉ ${count}" + fi + + return 0 +} + + +__count_apple_mail() { + count=$(${TMUX_POWERLINE_DIR_SEGMENTS}/mailcount_apple_mail.script) + echo "$count" +} + +__count_gmail() { + local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/gmail_count.txt" + local tmp_wgetrc="${TMUX_POWERLINE_DIR_TEMPORARY}/tmp_wgetrc.txt" + local override_passget="false" # When true a force reloaded will be done. + + # Create the cache file if it doesn't exist. + if [ ! -f "$tmp_file" ]; then + touch $tmp_file + override_passget=true + fi + + # Refresh mail count if the tempfile is older than $interval minutes. + let interval=60*$TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL + if shell_is_osx || shell_is_bsd; then + last_update=$(stat -f "%m" ${tmp_file}) + elif shell_is_linux; then + last_update=$(stat -c "%Y" ${tmp_file}) + fi + if [ "$(( $(date +"%s") - ${last_update} ))" -gt "$interval" ] || [ "$override_passget" == true ]; then + if [ -z "$TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_PASSWORD" ]; then # Get password from keychain if it isn't already set. + if shell_is_osx; then + __mac_keychain_get_pass "${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_USERNAME}@${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER}" "$TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER" + else + echo "Implement your own sexy password fetching mechanism here." + return 1 + fi + fi + + # Check for wget before proceeding. + which wget 2>&1 > /dev/null + if [ $? -ne 0 ]; then + echo "This script requires wget." 1>&2 + return 1 + fi + + # Hide password from command line (visible with e.g. ps(1)). + echo -e "user=${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_USERNAME}@${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER}\npassword=${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_PASSWORD}" > "$tmp_wgetrc" + mail=$(wget -q -O - https://mail.google.com/a/${TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER}/feed/atom --config "$tmp_wgetrc" | grep -E -m 1 -o '<fullcount>(.*)</fullcount>' | sed -e 's,.*<fullcount>\([^<]*\)</fullcount>.*,\1,g') + rm "$tmp_wgetrc" + + if [ "$mail" != "" ]; then + echo $mail > $tmp_file + else + return 1 + fi + fi + + count=$(cat $tmp_file) + echo "$count" + return 0; +} + +__count_maildir() { + if [ ! -d "$TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX" ]; then + return 1 + fi + + count=$(ls "$TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX" | wc -l) + + # Fix for mac, otherwise whitespace is left in output + if shell_is_osx; then + count=$(echo "$count" | sed -e "s/^[ \t]*//") + fi + + echo "$count" + return 0; +} + +__count_mbox() { + if [ ! -f "${TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX}" ]; then + return 1 + fi + + # This matches the From_ line (see man 5 mbox) e.g. + # From noreply@github.com Sun Dec 2 03:52:25 2012 + # See https://github.com/erikw/tmux-powerline/pull/91#issuecomment-10926053 for discussion. + count=$(grep -c '^From [^[:space:]]\+ ... ... .. ..:..:.. ....$' ${TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX}) + + echo "$count" + return 0; +} + +__mac_keychain_get_pass() { + result="$(security 2>&1 > /dev/null find-internet-password -ga $1 -s $2)" + if [ $? -eq 0 ]; then + TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_PASSWORD=$(echo "$result" | sed -e 's/password: \"\(.*\)\"/\1/g') + return 0 + fi + return 1 +} + +__count_mailcheck() { + count=$(mailcheck -f ${TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC} | awk '{ if (/new/) { print $3; exit } else { print 0; exit } }') + if [ $? -eq 0 ]; then + echo "$count" + return 0 + fi + return 1; +} diff --git a/tmux/powerline/segments/mailcount_apple_mail.script b/tmux/powerline/segments/mailcount_apple_mail.script new file mode 100755 index 0000000..fca8acb --- /dev/null +++ b/tmux/powerline/segments/mailcount_apple_mail.script @@ -0,0 +1,14 @@ +#!/usr/bin/env osascript +# Returns the number of unread mails in the INBOX of Apple Mail. + +tell application "System Events" + set process_list to (name of every process) +end tell + +if process_list contains "Mail" then + tell application "Mail" + if unread count of inbox > 0 then + set a to unread count of inbox + end if + end tell +end if diff --git a/tmux/powerline/segments/now_playing.sh b/tmux/powerline/segments/now_playing.sh new file mode 100755 index 0000000..1bcf3f9 --- /dev/null +++ b/tmux/powerline/segments/now_playing.sh @@ -0,0 +1,297 @@ +# Print current playing song in your music player of choice. + +source "${TMUX_POWERLINE_DIR_LIB}/text_roll.sh" + +TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN_DEFAULT="40" +TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD_DEFAULT="trim" +TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED_DEFAULT="2" +TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST_DEFAULT="localhost" +TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT_DEFAULT="6600" +TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD_DEFAULT="30" +TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT_DEFAULT="%artist% - %title%" +TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT_DEFAULT="%aa - %tt" +TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR_DEFAULT="♫" + +generate_segmentrc() { + read -d '' rccontents << EORC +# Music player to use. Can be any of {audacious, banshee, cmus, itunes, lastfm, mocp, mpd, mpd_simple, pithos, rdio, rhythmbox, spotify, spotify_wine, file}. +export TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER="" +# File to be read in case the song is being read from a file +export TMUX_POWERLINE_SEG_NOW_PLAYING_FILE_NAME="" +# Maximum output length. +export TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN="${TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN_DEFAULT}" +# How to handle too long strings. Can be {trim, roll}. +export TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD="${TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD_DEFAULT}" +# Charcters per second to roll if rolling trim method is used. +export TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED="${TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED_DEFAULT}" + +# Hostname for MPD server in the format "[password@]host" +export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST_DEFAULT}" +# Port the MPD server is running on. +export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT_DEFAULT}" +# Song display format for mpd_simple. See mpc(1) for delimiters. +export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT_DEFAULT}" +# Song display format for rhythmbox. see "FORMATS" in rhythmbox-client(1). +export TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT="${TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT_DEFAULT}" + +# Username for Last.fm if that music player is used. +export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_USERNAME="" +# How often in seconds to update the data from last.fm. +export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD_DEFAULT}" +# Fancy char to display before now playing track +export TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR="${TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR_DEFAULT}" +EORC + echo "$rccontents" +} + +run_segment() { + __process_settings + + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER" ]; then + return 1 + fi + + local np + local app_exit + IFS=',' read -ra PLAYERS <<< "$TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER" + for i in "${PLAYERS[@]}"; do + case "$i" in + "audacious") np=$(__np_audacious) ;; + "banshee") np=$(__np_banshee) ;; + "cmus") np=$(__np_cmus) ;; + "itunes") np=$(__np_itunes) ;; + "lastfm") np=$(__np_lastfm) ;; + "mocp") np=$(__np_mocp) ;; + "mpd") np=$(__np_mpd) ;; + "mpd_simple") np=$(__np_mpd_simple) ;; + "pithos") np=$(__np_pithos) ;; + "rdio") np=$(__np_rdio) ;; + "rhythmbox") np=$(__np_rhythmbox) ;; + "spotify") np=$(__np_spotify) ;; + "file") np=$(__np_file) ;; + "spotify_wine") np=$(__np_spotify_native) ;; + *) + echo "Unknown music player type [${TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER}]"; + return 1 + esac + app_exit="$?" + [ -n "$np" ] && break + done + + local exitcode="$app_exit" + if [ "${exitcode}" -ne 0 ]; then + return ${exitcode} + fi + if [ -n "$np" ]; then + case "$TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD" in + "roll") + np=$(roll_text "${np}" ${TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN} ${TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED_DEFAULT}) + ;; + "trim") + np=${np:0:TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN} + ;; + esac + echo "${TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR} ${np}" + fi + return 0 +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN="${TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD="${TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED="${TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT="${TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR="${TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT" ]; then + export TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT="${TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT}" + fi; +} + +__np_mpd() { + cd "$TMUX_POWERLINE_DIR_SEGMENTS" + + if [ ! -x "np_mpd" ]; then + make clean np_mpd &>/dev/null + fi + + if [ ! -x "np_mpd" ]; then + return 2 + fi + + np=$(MPD_HOST="$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST" MPD_PORT="$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT" ./np_mpd) + echo "$np" +} + +__np_file() { + + np=$(cat $TMUX_POWERLINE_SEG_NOW_PLAYING_FILE_NAME | tr '\n' '|') + echo "$np" +} + + +__np_mpd_simple() { + np=$(MPD_HOST="$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST" MPD_PORT="$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT" mpc current -f "$TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT" 2>&1) + if [ $? -eq 0 ] && [ -n "$np" ]; then + mpc | grep "paused" > /dev/null + if [ $? -eq 0 ]; then + return 1 + fi + echo "$np" + fi +} + + +__np_audacious() { + audacious_pid=$(pidof audacious) + if [ -n "$audacious_pid" ]; then + if $(audtool playback-playing); then + np=$(audtool current-song) + echo "$np" + fi + fi +} + +__np_banshee() { + banshee_pid=$(pidof banshee) + if [ -n "$banshee_pid" ]; then + banshee_status=$(banshee --query-current-state 2> /dev/null) + if [[ "$banshee_status" == "current-state: playing" ]]; then + np=$(banshee --query-artist --query-title | cut -d ":" -f2 | sed -e 's/ *$//g' -e 's/^ *//g'| sed -e ':a;N;$!ba;s/\n/ - /g' ) + echo "$np" + fi + fi +} + +__np_cmus() { + #cmus-remote returns EXIT_FAILURE/EXIT_SUCCESS depending on whether or not cmus is running. + if cmus-remote -Q > /dev/null 2>&1; then + status=$(cmus-remote -Q | grep "status" | cut -d ' ' -f 2) + artist=$(cmus-remote -Q | grep -m 1 "artist" | cut -d ' ' -f 3-) + title=$(cmus-remote -Q | grep "title" | cut -d ' ' -f 3-) + #The lines below works fine. Just uncomment them and add them + # in np below if you want the track number or album name. + #tracknumber=$(cmus-remote -Q | grep "tracknumber" | cut -d ' ' -f 3) + #album=$(cmus-remote -Q | grep "album" | cut -d ' ' -f 3-) + + np=$(echo "${artist} - ${title}") + + if [ "$status" == "playing" ]; then + echo "$np" + fi + fi +} + +__np_itunes() { + [ ! shell_is_osx ] && return 1 + np=$(${TMUX_POWERLINE_DIR_SEGMENTS}/np_itunes.script) + echo "$np" +} + +__np_lastfm() { + local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/np_lastfm.txt" + if [ -f "$tmp_file" ]; then + if shell_is_osx || shell_is_bsd; then + last_update=$(stat -f "%m" ${tmp_file}) + elif shell_is_linux; then + last_update=$(stat -c "%Y" ${tmp_file}) + fi + time_now=$(date +%s) + + up_to_date=$(echo "(${time_now}-${last_update}) < ${TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD}" | bc) + if [ "$up_to_date" -eq 1 ]; then + np=$(cat ${tmp_file}) + fi + fi + + if [ -z "$np" ]; then + np=$(curl --max-time 2 -s http://ws.audioscrobbler.com/1.0/user/${TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_USERNAME}/recenttracks.txt | head -n 1 | sed -e 's/^[0-9]*,//' | sed 's/\xe2\x80\x93/-/') + if [ "$?" -eq "0" ] && [ -n "$np" ]; then + echo "${np}" > $tmp_file + fi + fi + echo "$np" +} + +__np_pithos() { + if [ "$(dbus-send --reply-timeout=10 --print-reply --dest=net.kevinmehall.Pithos /net/kevinmehall/Pithos net.kevinmehall.Pithos.IsPlaying 2>/dev/null | grep boolean | cut -d' ' -f5)" == "true" ]; then + np=$(${TMUX_POWERLINE_DIR_SEGMENTS}/np_pithos.py) + echo "$np" + fi +} + +__np_mocp() { + mocp_pid=$(pidof mocp) + if [ -n "$mocp_pid" ]; then + np=$(mocp -i | grep ^Title | sed "s/^Title://") + mocp_paused=$(mocp -i | grep ^State | sed "s/^State: //") + if [ -n "$np" -a "$mocp_paused" != "PAUSE" ]; then + echo "$np" + fi + fi +} + +__np_rdio() { + [ ! shell_is_osx ] && return 1 + np=$(osascript ${TMUX_POWERLINE_DIR_SEGMENTS}/np_rdio_mac.script) + echo "$np" +} + +__np_rhythmbox() { + rhythmbox_pid=$(pidof rhythmbox) + if [ -n "$rhythmbox_pid" ]; then + np=$(rhythmbox-client --no-start --print-playing-format="$TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT") + rhythmbox_paused=$(xwininfo -root -tree | grep "$np" | sed "s/${np}//;s/ //g" | cut -f2 -d '"') + # TODO I cant produce the output "Not playing", using rhythmbox 2.97. + #STATUS=$(rhythmbox-client --no-start --print-playing) + if [[ "$rhythmbox_paused" != "(Paused)" ]]; then + echo "$np" + fi + fi +} + +__np_spotify() { + if shell_is_linux; then + metadata=$(dbus-send --reply-timeout=42 --print-reply --dest=org.mpris.MediaPlayer2.spotify / org.freedesktop.MediaPlayer2.GetMetadata 2>/dev/null) + if [ "$?" -eq 0 ] && [ -n "$metadata" ]; then + # TODO how do one express this with dbus-send? It works with qdbus but the problem is that it's probably not as common as dbus-send. + state=$(qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get org.mpris.MediaPlayer2.Player PlaybackStatus) + if [[ $state == "Playing" ]]; then + artist=$(echo "$metadata" | grep -PA2 "string\s\"xesam:artist\"" | tail -1 | grep -Po "(?<=\").*(?=\")") + track=$(echo "$metadata" | grep -PA1 "string\s\"xesam:title\"" | tail -1 | grep -Po "(?<=\").*(?=\")") + np=$(echo "${artist} - ${track}") + fi + fi + elif shell_is_osx; then + np=$(${TMUX_POWERLINE_DIR_SEGMENTS}/np_spotify_mac.script) + fi + echo "$np" +} + +__np_spotify_wine() { + [ ! shell_is_linux ] && return 1 + spotify_id=$(xwininfo -root -tree | grep '("spotify' | cut -f1 -d'"' | sed 's/ //g') + echo $spotify_id + if [ -n "$spotify_id" ]; then + np=$(xwininfo -id "$spotify_id" | grep "xwininfo.*Spotify -" | grep -Po "(?<=\"Spotify - ).*(?=\"$)") + echo "$np" + fi +} diff --git a/tmux/powerline/segments/np_itunes.script b/tmux/powerline/segments/np_itunes.script new file mode 100755 index 0000000..8ac66bd --- /dev/null +++ b/tmux/powerline/segments/np_itunes.script @@ -0,0 +1,24 @@ +#!/usr/bin/env osascript +# Returns the current playing song in iTunes for OSX + +tell application "System Events" + set process_list to (name of every process) +end tell + +if process_list contains "iTunes" then + tell application "iTunes" + if player state is playing then + set track_name to name of current track + set artist_name to artist of current track + # set album_name to album of current track + set trim_length to 40 + set now_playing to artist_name & " - " & track_name + if length of now_playing is less than trim_length then + set now_playing_trim to now_playing + else + set now_playing_trim to characters 1 thru trim_length of now_playing as string + end if + end if + end tell +end if + diff --git a/tmux/powerline/segments/np_mpd.c b/tmux/powerline/segments/np_mpd.c new file mode 100644 index 0000000..97c4a6a --- /dev/null +++ b/tmux/powerline/segments/np_mpd.c @@ -0,0 +1,179 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <mpd/client.h> + +#ifdef DEBUG + #define DO_DEBUG DEBUG +#else + #define DO_DEBUG 0 +#endif +#define DEBUG_PRINTF(...) do{ if (DO_DEBUG) { printf(__VA_ARGS__);} } while(0) + +/* Output the current song if MPD is in a playing state. The connection password, host and port is + * specified like for mpc with environment variables + * MPD_HOST=[password@]host + * MPD_PORT=port + * If they are empty they defaults to localhost on port 6600. + */ +int main(int argc, const char *argv[]) +{ + char *mpd_host = NULL; + char *mpd_password = NULL; + unsigned int mpd_port = 0; + + char *mpd_host_m = NULL; + char *mpd_password_m = NULL; + + const char *mpd_host_str = getenv("MPD_HOST"); + if (mpd_host_str == NULL || strlen(mpd_host_str) == 0) { + DEBUG_PRINTF("No envvar MPD_HOST set or empty. Using default value (localhost).\n"); + mpd_host = "localhost"; + } else { + size_t mpd_host_len = strlen(mpd_host_str); + char mpd_host_env[mpd_host_len + 1]; + strncpy(mpd_host_env, mpd_host_str, mpd_host_len); + mpd_host_env[mpd_host_len] = '\0'; + + char *pch = strtok(mpd_host_env, "@"); + char *first = NULL; + char *second = NULL; + if (pch != NULL) { + first = pch; + } + pch = strtok(NULL, "@"); + if (pch != NULL) { + second = pch; + } + + if (first != NULL && second != NULL) { + DEBUG_PRINTF("%s - %s\n", first, second); + size_t first_len = strlen(first); + size_t second_len = strlen(second); + mpd_password_m = (char *) malloc(first_len + 1); + mpd_host_m= (char *) malloc(second_len + 1); + if (mpd_password_m == NULL || mpd_host_m == NULL) { + DEBUG_PRINTF("Failed alloc password/host.\n"); + return EXIT_FAILURE; + } + strncpy(mpd_password_m, first, first_len); + mpd_password_m[first_len] = '\0'; + strncpy(mpd_host_m, second, second_len); + mpd_host_m[second_len] = '\0'; + } else if (first != NULL) { + DEBUG_PRINTF("%s\n", first); + size_t first_len = strlen(first); + mpd_host_m = (char *) malloc(first_len + 1); + if (mpd_host_m == NULL ) { + DEBUG_PRINTF("Failed alloc host.\n"); + return EXIT_FAILURE; + } + strncpy(mpd_host_m, first, first_len); + mpd_host_m[first_len] = '\0'; + } + } + + if (mpd_host_m != NULL) { + mpd_host = mpd_host_m; + } + + if (mpd_password_m != NULL) { + mpd_password = mpd_password_m; + } + + const char *mpd_port_env = getenv("MPD_PORT"); + if (mpd_port_env == NULL || strlen(mpd_port_env) == 0) { + DEBUG_PRINTF("No envvar MPD_PORT set or empty. Using default value (6600).\n"); + mpd_port = 6600; + } else { + int mpd_port_m = atoi(mpd_port_env); + if (mpd_port_m == 0) { + DEBUG_PRINTF("Could not convert MPD_PORT to int.\n"); + return EXIT_FAILURE; + } else if (mpd_port_m < 0) { + DEBUG_PRINTF("Negative port?!\n"); + return EXIT_FAILURE; + } else { + mpd_port = mpd_port_m; + DEBUG_PRINTF("Using port %i\n", mpd_port); + } + } + + + struct mpd_connection *mpd_connection = mpd_connection_new(mpd_host, mpd_port, 1000); + if (mpd_connection == NULL) { + DEBUG_PRINTF("%s\n", "Could Not connect"); + return EXIT_FAILURE; + } + + if (mpd_password != NULL) { + bool authenticated = mpd_run_password(mpd_connection, mpd_password); + if (!authenticated) { + DEBUG_PRINTF("Failed to authenticate.\n"); + return EXIT_FAILURE; + } + } + + free(mpd_host_m); + free(mpd_password_m); + + bool sent_status = mpd_send_status(mpd_connection); + if (!sent_status) { + DEBUG_PRINTF("Could not send status request."); + return EXIT_FAILURE; + } + struct mpd_status *mpd_status = mpd_recv_status(mpd_connection); + if (mpd_status == NULL) { + DEBUG_PRINTF("Could not get mpd status.\n"); + return EXIT_FAILURE; + } + + enum mpd_state mpd_state = mpd_status_get_state(mpd_status); + DEBUG_PRINTF("State: "); + if (mpd_state == MPD_STATE_PLAY) { + DEBUG_PRINTF("Playing."); + } else if (mpd_state == MPD_STATE_PAUSE) { + DEBUG_PRINTF("Paused."); + } else if (mpd_state == MPD_STATE_UNKNOWN) { + DEBUG_PRINTF("Unknown state."); + } else if (mpd_state == MPD_STATE_STOP) { + DEBUG_PRINTF("Stopped."); + } + DEBUG_PRINTF("\n"); + + if (mpd_state != MPD_STATE_PLAY) { + // Nothing to do. + mpd_status_free(mpd_status); + mpd_connection_free(mpd_connection); + return EXIT_SUCCESS; + } + + int song_id = mpd_status_get_song_id(mpd_status); + DEBUG_PRINTF("songid = %i\n", song_id); + + mpd_status_free(mpd_status); + + struct mpd_song *song = mpd_run_get_queue_song_id(mpd_connection, song_id); + if (song == NULL) { + DEBUG_PRINTF("Could not get song.\n"); + return EXIT_FAILURE; + } + + const char *song_artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0); + if (song_artist == NULL) { + DEBUG_PRINTF("Could not get song artist."); + return EXIT_FAILURE; + } + + const char *song_title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0); + if (song_title == NULL) { + DEBUG_PRINTF("Could not get song title."); + return EXIT_FAILURE; + } + printf("%s - %s\n", song_artist, song_title); + + mpd_song_free(song); + mpd_connection_free(mpd_connection); + return EXIT_SUCCESS; +} diff --git a/tmux/powerline/segments/np_pithos.py b/tmux/powerline/segments/np_pithos.py new file mode 100755 index 0000000..9d022e6 --- /dev/null +++ b/tmux/powerline/segments/np_pithos.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +import dbus + +pithos_bus = dbus.SessionBus() + +pithos = pithos_bus.get_object('net.kevinmehall.Pithos', '/net/kevinmehall/Pithos') +props = pithos.get_dbus_method('GetCurrentSong', 'net.kevinmehall.Pithos') + +print props()["artist"] + " - " + props()["title"] diff --git a/tmux/powerline/segments/np_rdio_mac.script b/tmux/powerline/segments/np_rdio_mac.script new file mode 100755 index 0000000..d46bd0f --- /dev/null +++ b/tmux/powerline/segments/np_rdio_mac.script @@ -0,0 +1,20 @@ +#!/usr/bin/env osascript +# Returns the current playing song in Rdio for OS X. + +tell application "System Events" + set process_list to (name of every process) +end tell + +if process_list contains "Rdio" then + tell application "Rdio" + if player state is playing then + set track_name to name of current track + set artist_name to artist of current track + set album_name to album of current track + set now_playing to artist_name & " - " & track_name + # Uncomment if Album name is wanted + #set now_playing to now_playing & " - " & album_name + end if + end tell +end if + diff --git a/tmux/powerline/segments/np_spotify_mac.script b/tmux/powerline/segments/np_spotify_mac.script new file mode 100755 index 0000000..9b2a0a8 --- /dev/null +++ b/tmux/powerline/segments/np_spotify_mac.script @@ -0,0 +1,27 @@ +#!/usr/bin/env osascript +# Returns the current playing song in Spotify for OSX + +tell application "System Events" + set process_list to (name of every process) +end tell + +if process_list contains "Spotify" then + tell application "Spotify" + if player state is playing or player state is paused then + set track_name to name of current track + set artist_name to artist of current track + #set album_name to album of current track + set trim_length to 40 + if player state is playing then + set now_playing to "► " & artist_name & " - " & track_name + else + set now_playing to "❙❙ " & artist_name & " - " & track_name + end if + if length of now_playing is less than trim_length then + set now_playing_trim to now_playing + else + set now_playing_trim to characters 1 thru trim_length of now_playing as string + end if + end if + end tell +end if diff --git a/tmux/powerline/segments/pwd.sh b/tmux/powerline/segments/pwd.sh new file mode 100755 index 0000000..2499762 --- /dev/null +++ b/tmux/powerline/segments/pwd.sh @@ -0,0 +1,39 @@ +# Print the current working directory (trimmed to max length). +# NOTE The trimming code's stolen from the web. Courtesy to who ever wrote it. + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +TMUX_POWERLINE_SEG_PWD_MAX_LEN_DEFAULT="40" + +generate_segmentrc() { + read -d '' rccontents << EORC +# Maximum length of output. +export TMUX_POWERLINE_SEG_PWD_MAX_LEN="${TMUX_POWERLINE_SEG_PWD_MAX_LEN_DEFAULT}" +EORC + echo "$rccontents" +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_PWD_MAX_LEN" ]; then + export TMUX_POWERLINE_SEG_PWD_MAX_LEN="${TMUX_POWERLINE_SEG_PWD_MAX_LEN_DEFAULT}" + fi +} + +run_segment() { + __process_settings + # Truncate from the left. + tcwd=$(get_tmux_cwd) + trunc_symbol="···" + dir=${tcwd##*/} + local max_len="$TMUX_POWERLINE_SEG_PWD_MAX_LEN" + max_len=$(( ( max_len < ${#dir} ) ? ${#dir} : max_len )) + ttcwd=${tcwd/#$HOME/\~} + pwdoffset=$(( ${#ttcwd} - max_len )) + if [ ${pwdoffset} -gt "0" ]; then + ttcwd=${ttcwd:$pwdoffset:$max_len} + ttcwd=${trunc_symbol}/${ttcwd#*/} + fi + echo "$ttcwd" + return 0 +} diff --git a/tmux/powerline/segments/rainbarf.sh b/tmux/powerline/segments/rainbarf.sh new file mode 100755 index 0000000..55f2ed6 --- /dev/null +++ b/tmux/powerline/segments/rainbarf.sh @@ -0,0 +1,16 @@ +# Print out Memory and CPU using https://github.com/creaktive/rainbarf + +run_segment() { + type rainbarf >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + echo 'rainbarf was not found' + return + fi + + # Customize via ~/.rainbarf.conf + stats=$(rainbarf --tmux) + if [ -n "$stats" ]; then + echo "$stats"; + fi + return 0 +} diff --git a/tmux/powerline/segments/thyme.sh b/tmux/powerline/segments/thyme.sh new file mode 100755 index 0000000..e034ad4 --- /dev/null +++ b/tmux/powerline/segments/thyme.sh @@ -0,0 +1,9 @@ +# Print out Memory and CPU using https://github.com/creaktive/rainbarf + +run_segment() { + stats=$(cat ~/.thyme-tmux) + if [ -n "$stats" ]; then + echo "$stats"; + fi + return 0 +} diff --git a/tmux/powerline/segments/time.sh b/tmux/powerline/segments/time.sh new file mode 100755 index 0000000..e307399 --- /dev/null +++ b/tmux/powerline/segments/time.sh @@ -0,0 +1,23 @@ +# Prints the current time. + +TMUX_POWERLINE_SEG_TIME_FORMAT_DEFAULT="%H:%M" + +generate_segmentrc() { + read -d '' rccontents << EORC +# date(1) format for the time. Americans might want to have "%I:%M %p". +export TMUX_POWERLINE_SEG_TIME_FORMAT="${TMUX_POWERLINE_SEG_TIME_FORMAT_DEFAULT}" +EORC + echo "$rccontents" +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_TIME_FORMAT" ]; then + export TMUX_POWERLINE_SEG_TIME_FORMAT="${TMUX_POWERLINE_SEG_TIME_FORMAT_DEFAULT}" + fi +} + +run_segment() { + __process_settings + date +"$TMUX_POWERLINE_SEG_TIME_FORMAT" + return 0 +} diff --git a/tmux/powerline/segments/tmux_mem_cpu_load.sh b/tmux/powerline/segments/tmux_mem_cpu_load.sh new file mode 100755 index 0000000..c05be3e --- /dev/null +++ b/tmux/powerline/segments/tmux_mem_cpu_load.sh @@ -0,0 +1,14 @@ +# Print out Memory, cpu and load using https://github.com/thewtex/tmux-mem-cpu-load + +run_segment() { + type tmux-mem-cpu-load >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + stats=$(tmux-mem-cpu-load) + if [ -n "$stats" ]; then + echo "$stats"; + fi + return 0 +} diff --git a/tmux/powerline/segments/tmux_session_info.sh b/tmux/powerline/segments/tmux_session_info.sh new file mode 100755 index 0000000..ce2dacc --- /dev/null +++ b/tmux/powerline/segments/tmux_session_info.sh @@ -0,0 +1,7 @@ +# Prints tmux session info. +# Assuems that [ -n "$TMUX"]. + +run_segment() { + tmux display-message -p '#S:#I.#P' + return 0 +} diff --git a/tmux/powerline/segments/uptime.sh b/tmux/powerline/segments/uptime.sh new file mode 100755 index 0000000..04650d9 --- /dev/null +++ b/tmux/powerline/segments/uptime.sh @@ -0,0 +1,30 @@ +# Prints the uptime. + + +if shell_is_bsd; then + TMUX_POWERLINE_SEG_UPTIME_GREP_DEFAULT="/usr/local/bin/grep" +else + TMUX_POWERLINE_SEG_UPTIME_GREP_DEFAULT="grep" +fi + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_UPTIME_GREP" ]; then + export TMUX_POWERLINE_SEG_UPTIME_GREP="${TMUX_POWERLINE_SEG_UPTIME_GREP_DEFAULT}" + fi +} + +generate_segmentrc() { + read -d '' rccontents << EORC +# Name of GNU grep binary if in PATH, or path to it. +export TMUX_POWERLINE_SEG_UPTIME_GREP="${TMUX_POWERLINE_SEG_UPTIME_GREP_DEFAULT}" +EORC + echo "$rccontents" +} + +run_segment() { + __process_settings + # Assume latest grep is in PATH + gnugrep="${TMUX_POWERLINE_SEG_UPTIME_GREP}" + uptime | $gnugrep -PZo "(?<=up )[^,]*" + return 0 +} diff --git a/tmux/powerline/segments/utc_time.sh b/tmux/powerline/segments/utc_time.sh new file mode 100755 index 0000000..4da6149 --- /dev/null +++ b/tmux/powerline/segments/utc_time.sh @@ -0,0 +1,6 @@ +# Prints the current time in UTC. + +run_segment() { + date -u +"%H:%M" + return 0 +} diff --git a/tmux/powerline/segments/vcs_branch.sh b/tmux/powerline/segments/vcs_branch.sh new file mode 100755 index 0000000..3079459 --- /dev/null +++ b/tmux/powerline/segments/vcs_branch.sh @@ -0,0 +1,90 @@ +# Prints current branch in a VCS directory if it could be detected. + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +branch_symbol="" +git_colour="5" +svn_colour="220" +hg_colour="45" + + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + branch="" + if [ -n "${git_branch=$(__parse_git_branch)}" ]; then + branch="$git_branch" + elif [ -n "${svn_branch=$(__parse_svn_branch)}" ]; then + branch="$svn_branch" + elif [ -n "${hg_branch=$(__parse_hg_branch)}" ]; then + branch="$hg_branch" + fi + + if [ -n "$branch" ]; then + echo "${branch}" + fi + return 0 +} + + +# Show git banch. +__parse_git_branch() { + type git >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + #git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/' + + # Quit if this is not a Git repo. + branch=$(git symbolic-ref HEAD 2> /dev/null) + if [[ -z $branch ]] ; then + # attempt to get short-sha-name + branch=":$(git rev-parse --short HEAD 2> /dev/null)" + fi + if [ "$?" -ne 0 ]; then + # this must not be a git repo + return + fi + + # Clean off unnecessary information. + branch=${branch##*/} + + echo -n "#[fg=colour${git_colour}]${branch_symbol} #[fg=colour${TMUX_POWERLINE_CUR_SEGMENT_FG}]${branch}" +} + +# Show SVN branch. +__parse_svn_branch() { + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + local svn_info=$(svn info 2>/dev/null) + if [ -z "${svn_info}" ]; then + return + fi + + + local svn_root=$(echo "${svn_info}" | sed -ne 's#^Repository Root: ##p') + local svn_url=$(echo "${svn_info}" | sed -ne 's#^URL: ##p') + + local branch=$(echo "${svn_url}" | egrep -o '[^/]+$') + echo "#[fg=colour${svn_colour}]${branch_symbol} #[fg=colour${TMUX_POWERLINE_CUR_SEGMENT_FG}]${branch}" +} + +__parse_hg_branch() { + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + summary=$(hg summary) + if [ "$?" -ne 0 ]; then + return + fi + + local branch=$(echo "$summary" | grep 'branch:' | cut -d ' ' -f2) + echo "#[fg=colour${hg_colour}]${branch_symbol} #[fg=colour${TMUX_POWERLINE_CUR_SEGMENT_FG}]${branch}" +} diff --git a/tmux/powerline/segments/vcs_compare.sh b/tmux/powerline/segments/vcs_compare.sh new file mode 100755 index 0000000..46d6287 --- /dev/null +++ b/tmux/powerline/segments/vcs_compare.sh @@ -0,0 +1,71 @@ +# This checks if the current branch is ahead of +# or behind the remote branch with which it is tracked + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +flat_symbol="⤚" + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + stats="" + if [ -n "${git_stats=$(__parse_git_stats)}" ]; then + stats="$git_stats" + elif [ -n "${svn_stats=$(__parse_svn_stats)}" ]; then + stats="$svn_stats" + elif [ -n "${hg_stats=$(__parse_hg_stats)}" ]; then + stats="$hg_stats" + fi + + if [ -n "$stats" ]; then + echo "${stats}" + fi + return 0 +} + +__parse_git_stats() { + type git >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + # check if git + [[ -z $(git rev-parse --git-dir 2> /dev/null) ]] && return + + symbolic_ref=$(git symbolic-ref -q HEAD) + [[ -z "${symbolic_ref}" ]] && return + + tracking_branch=$(git for-each-ref --format='%(upstream:short)' ${symbolic_ref}) + + # creates global variables $1 and $2 based on left vs. right tracking + set -- $(git rev-list --left-right --count $tracking_branch...HEAD) + + behind=$1 + ahead=$2 + + # print out the information + if [[ $behind -gt 0 ]] ; then + local ret="↓ $behind" + fi + if [[ $ahead -gt 0 ]] ; then + local ret="${ret}↑ $ahead" + fi + echo "$ret" +} + +__parse_hg_stats() { + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} + +__parse_svn_stats() { + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} diff --git a/tmux/powerline/segments/vcs_modified.sh b/tmux/powerline/segments/vcs_modified.sh new file mode 100755 index 0000000..59b8b9c --- /dev/null +++ b/tmux/powerline/segments/vcs_modified.sh @@ -0,0 +1,70 @@ +# This checks if the current branch is ahead of +# or behind the remote branch with which it is tracked + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +mod_symbol="﹢" + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + + stats="" + if [ -n "${git_stats=$(__parse_git_stats)}" ]; then + stats="$git_stats" + elif [ -n "${svn_stats=$(__parse_svn_stats)}" ]; then + stats="$svn_stats" + elif [ -n "${hg_stats=$(__parse_hg_stats)}" ]; then + stats="$hg_stats" + fi + if [[ -n "$stats" && $stats -gt 0 ]]; then + echo "${mod_symbol}${stats}" + fi +} + +__parse_git_stats(){ + type git >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + # check if git + [[ -z $(git rev-parse --git-dir 2> /dev/null) ]] && return + + # return the number of modified but not staged items + modified=$(git status -s | cut -c 2 | awk '$1 != "" && $1 != "?" { print $1 }' | wc -l) + echo $modified +} +__parse_hg_stats(){ + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} +__parse_svn_stats() { + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + local svn_info=$(svn info 2>/dev/null) + if [ -z "${svn_info}" ]; then + return + fi + + local svn_wcroot=$(echo "${svn_info}" | sed -ne 's#^Working Copy Root Path: ##p') + local svn_st=$(cd "${svn_wcroot}"; svn st) + local modified=$(echo "${svn_st}" | egrep '^M' | wc -l) + local conflicted=$(echo "${svn_st}" | egrep '^!?\s*C' | wc -l) + + #print + if [[ $modified -gt 0 ]] ; then + local ret="#[fg=colour${TMUX_POWERLINE_CUR_SEGMENT_FG}]±${modified}" + fi + if [[ $conflicted -gt 0 ]] ; then + local ret="#[fg=colour${svn_colour}]ϟ${conflicted} ${ret}" + fi + echo "${ret}" +} diff --git a/tmux/powerline/segments/vcs_others.sh b/tmux/powerline/segments/vcs_others.sh new file mode 100755 index 0000000..2ffd6f2 --- /dev/null +++ b/tmux/powerline/segments/vcs_others.sh @@ -0,0 +1,51 @@ +# This checks if the current branch is ahead of or behind the remote branch with which it is tracked. + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +other_symbol="⋯ " + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + stats="" + if [ -n "${git_stats=$(__parse_git_stats)}" ]; then + stats="$git_stats" + elif [ -n "${svn_stats=$(__parse_svn_stats)}" ]; then + stats="$svn_stats" + elif [ -n "${hg_stats=$(__parse_hg_stats)}" ]; then + stats="$hg_stats" + fi + if [[ -n "$stats" && $stats -gt 0 ]]; then + echo "${other_symbol}${stats}" + fi + return 0 +} + +__parse_git_stats(){ + type git >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + # check if git + [[ -z $(git rev-parse --git-dir 2> /dev/null) ]] && return + + # return the number of untracked items + other=$(git status -s | awk '$1 == "??" { print $1 }' | wc -l) + echo $other +} +__parse_hg_stats(){ + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} +__parse_svn_stats(){ + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} diff --git a/tmux/powerline/segments/vcs_revision.sh b/tmux/powerline/segments/vcs_revision.sh new file mode 100755 index 0000000..0ff0f74 --- /dev/null +++ b/tmux/powerline/segments/vcs_revision.sh @@ -0,0 +1,43 @@ +# This prints the vcs revision in the working directory +# currently only used in SVN + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + + stats="" + if [[ -n "${svn_stats=$(__parse_svn_stats)}" ]]; then + stats="$svn_stats" + elif [[ -n "${hg_stats=$(__parse_hg_stats)}" ]]; then + stats="$hg_stats" + fi + if [[ -n "$stats" ]]; then + echo "${stats}" + fi +} + +__parse_hg_stats(){ + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} +__parse_svn_stats(){ + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + local svn_info=$(svn info 2>/dev/null) + if [ -z "${svn_info}" ]; then + return + fi + + local svn_ref=$(echo "${svn_info}" | sed -ne 's#^Revision: ##p') + + echo "r${svn_ref}" +} diff --git a/tmux/powerline/segments/vcs_staged.sh b/tmux/powerline/segments/vcs_staged.sh new file mode 100755 index 0000000..8818b3c --- /dev/null +++ b/tmux/powerline/segments/vcs_staged.sh @@ -0,0 +1,57 @@ +# This checks if the current branch is ahead of +# or behind the remote branch with which it is tracked + +# Source lib to get the function get_tmux_pwd +source "${TMUX_POWERLINE_DIR_LIB}/tmux_adapter.sh" + +staged_symbol="⊕ " + +run_segment() { + tmux_path=$(get_tmux_cwd) + cd "$tmux_path" + + stats="" + if [ -n "${git_stats=$(__parse_git_stats)}" ]; then + stats="$git_stats" + elif [ -n "${svn_stats=$(__parse_svn_stats)}" ]; then + stats="$svn_stats" + elif [ -n "${hg_stats=$(__parse_hg_stats)}" ]; then + stats="$hg_stats" + fi + if [[ -n "$stats" && $stats -gt 0 ]]; then + stats=$(echo $stats | sed -e "s/^[ \t]*//") + echo "${staged_symbol}${stats}" + fi + return 0 +} + + +__parse_git_stats(){ + type git >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + # Check if git. + [[ -z $(git rev-parse --git-dir 2> /dev/null) ]] && return + + # Return the number of staged items. + staged=$(git diff --staged --name-status | wc -l) + echo "$staged" +} + +__parse_hg_stats(){ + type svn >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} + +__parse_svn_stats(){ + type hg >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + # not yet implemented +} diff --git a/tmux/powerline/segments/wan_ip.sh b/tmux/powerline/segments/wan_ip.sh new file mode 100755 index 0000000..811d100 --- /dev/null +++ b/tmux/powerline/segments/wan_ip.sh @@ -0,0 +1,43 @@ +# Prints the WAN IP address. The result is cached and updated according to $update_period. + +run_segment() { + local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/wan_ip.txt" + local wan_ip + + if [ -f "$tmp_file" ]; then + if shell_is_osx || shell_is_bsd; then + stat >/dev/null 2>&1 && is_gnu_stat=false || is_gnu_stat=true + if [ "$is_gnu_stat" == "true" ];then + last_update=$(stat -c "%Y" ${tmp_file}) + else + last_update=$(stat -f "%m" ${tmp_file}) + fi + elif shell_is_linux || [ -z $is_gnu_stat]; then + last_update=$(stat -c "%Y" ${tmp_file}) + fi + + time_now=$(date +%s) + update_period=900 + up_to_date=$(echo "(${time_now}-${last_update}) < ${update_period}" | bc) + + if [ "$up_to_date" -eq 1 ]; then + wan_ip=$(cat ${tmp_file}) + fi + fi + + if [ -z "$wan_ip" ]; then + wan_ip=$(curl --max-time 2 -s http://whatismyip.akamai.com/) + + if [ "$?" -eq "0" ]; then + echo "${wan_ip}" > $tmp_file + elif [ -f "${tmp_file}" ]; then + wan_ip=$(cat "$tmp_file") + fi + fi + + if [ -n "$wan_ip" ]; then + echo "ⓦ ${wan_ip}" + fi + + return 0 +} diff --git a/tmux/powerline/segments/weather.sh b/tmux/powerline/segments/weather.sh new file mode 100755 index 0000000..775cefc --- /dev/null +++ b/tmux/powerline/segments/weather.sh @@ -0,0 +1,191 @@ +# Prints the current weather in Celsius, Fahrenheits or lord Kelvins. The forecast is cached and updated with a period of $update_period. + +# The update period in seconds. +update_period=600 + +TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT="yahoo" +TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT="c" +TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT="600" +if shell_is_bsd; then + TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT="/usr/local/bin/grep" +else + TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT="grep" +fi + + +generate_segmentrc() { + read -d '' rccontents << EORC +# The data provider to use. Currently only "yahoo" is supported. +export TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER="${TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT}" +# What unit to use. Can be any of {c,f,k}. +export TMUX_POWERLINE_SEG_WEATHER_UNIT="${TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT}" +# How often to update the weather in seconds. +export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT}" +# Name of GNU grep binary if in PATH, or path to it. +export TMUX_POWERLINE_SEG_WEATHER_GREP="${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT}" + +# Your location. Find a code that works for you: +# 1. Go to Yahoo weather http://weather.yahoo.com/ +# 2. Find the weather for you location +# 3. Copy the last numbers in that URL. e.g. "http://weather.yahoo.com/united-states/california/newport-beach-12796587/" has the numbers "12796587" +export TMUX_POWERLINE_SEG_WEATHER_LOCATION="" +EORC + echo "$rccontents" +} + +run_segment() { + __process_settings + local tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/weather_yahoo.txt" + local weather + case "$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER" in + "yahoo") weather=$(__yahoo_weather) ;; + *) + echo "Unknown weather provider [${$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER}]"; + return 1 + esac + if [ -n "$weather" ]; then + echo "$weather" + fi +} + +__process_settings() { + if [ -z "$TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER" ]; then + export TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER="${TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_WEATHER_UNIT" ]; then + export TMUX_POWERLINE_SEG_WEATHER_UNIT="${TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD" ]; then + export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_WEATHER_GREP" ]; then + export TMUX_POWERLINE_SEG_WEATHER_GREP="${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT}" + fi + if [ -z "$TMUX_POWERLINE_SEG_WEATHER_LOCATION" ]; then + echo "No weather location specified."; + exit 8 + fi +} + +__yahoo_weather() { + degree="" + if [ -f "$tmp_file" ]; then + if shell_is_osx || shell_is_bsd; then + last_update=$(stat -f "%m" ${tmp_file}) + elif shell_is_linux; then + last_update=$(stat -c "%Y" ${tmp_file}) + fi + time_now=$(date +%s) + + up_to_date=$(echo "(${time_now}-${last_update}) < ${update_period}" | bc) + if [ "$up_to_date" -eq 1 ]; then + __read_tmp_file + fi + fi + + if [ -z "$degree" ]; then + weather_data=$(curl --max-time 4 -s "https://query.yahooapis.com/v1/public/yql?format=xml&q=SELECT%20*%20FROM%20weather.forecast%20WHERE%20u=%27${TMUX_POWERLINE_SEG_WEATHER_UNIT}%27%20AND%20woeid%20=%20%27${TMUX_POWERLINE_SEG_WEATHER_LOCATION}%27") + if [ "$?" -eq "0" ]; then + error=$(echo "$weather_data" | grep "problem_cause\|DOCTYPE"); + if [ -n "$error" ]; then + echo "error" + exit 1 + fi + + # Assume latest grep is in PATH + gnugrep="${TMUX_POWERLINE_SEG_WEATHER_GREP}" + + # <yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/> + unit=$(echo "$weather_data" | "$gnugrep" -Zo "<yweather:units [^<>]*/>" | sed 's/.*temperature="\([^"]*\)".*/\1/') + condition=$(echo "$weather_data" | "$gnugrep" -Zo "<yweather:condition [^<>]*/>") + # <yweather:condition text="Clear" code="31" temp="66" date="Mon, 01 Oct 2012 8:00 pm CST" /> + degree=$(echo "$condition" | sed 's/.*temp="\([^"]*\)".*/\1/') + condition=$(echo "$condition" | sed 's/.*text="\([^"]*\)".*/\1/') + # Pull the times for sunrise and sunset so we know when to change the day/night indicator + # <yweather:astronomy sunrise="6:56 am" sunset="6:21 pm"/> + if shell_is_osx || shell_is_bsd; then + date_arg='-j -f "%H:%M %p "' + else + date_arg='-d' + fi + sunrise=$(date ${date_arg}"$(echo "$weather_data" | "$gnugrep" "yweather:astronomy" | sed 's/^\(.*\)sunset.*/\1/' | sed 's/^.*sunrise="\(.*m\)".*/\1/')" +%H%M) + sunset=$(date ${date_arg}"$(echo "$weather_data" | "$gnugrep" "yweather:astronomy" | sed 's/^.*sunset="\(.*m\)".*/\1/')" +%H%M) + elif [ -f "${tmp_file}" ]; then + __read_tmp_file + fi + fi + + if [ -n "$degree" ]; then + if [ "$TMUX_POWERLINE_SEG_WEATHER_UNIT" == "k" ]; then + degree=$(echo "${degree} + 273.15" | bc) + fi + condition_symbol=$(__get_condition_symbol "$condition" "$sunrise" "$sunset") + echo "${condition_symbol} ${degree}°$(echo "$TMUX_POWERLINE_SEG_WEATHER_UNIT" | tr '[:lower:]' '[:upper:]')" | tee "${tmp_file}" + fi +} + +# Get symbol for condition. Available conditions: http://developer.yahoo.com/weather/#codes +__get_condition_symbol() { + local condition=$(echo "$1" | tr '[:upper:]' '[:lower:]') + local sunrise="$2" + local sunset="$3" + case "$condition" in + "sunny" | "hot") + hourmin=$(date +%H%M) + if [ "$hourmin" -ge "$sunset" -o "$hourmin" -le "$sunrise" ]; then + #echo "☽" + echo "☾" + else + #echo "☀" + echo "☼" + fi + ;; + "rain" | "mixed rain and snow" | "mixed rain and sleet" | "freezing drizzle" | "drizzle" | "light drizzle" | "freezing rain" | "showers" | "mixed rain and hail" | "scattered showers" | "isolated thundershowers" | "thundershowers" | "light rain with thunder" | "light rain" | "rain and snow") + #echo "☂" + echo "☔" + ;; + "snow" | "mixed snow and sleet" | "snow flurries" | "light snow showers" | "blowing snow" | "sleet" | "hail" | "heavy snow" | "scattered snow showers" | "snow showers" | "light snow" | "snow/windy" | "snow grains" | "snow/fog") + #echo "☃" + echo "❅" + ;; + "cloudy" | "mostly cloudy" | "partly cloudy" | "partly cloudy/windy") + echo "☁" + ;; + "tornado" | "tropical storm" | "hurricane" | "severe thunderstorms" | "thunderstorms" | "isolated thunderstorms" | "scattered thunderstorms") + #echo "⚡" + echo "☈" + ;; + "dust" | "foggy" | "fog" | "haze" | "smoky" | "blustery" | "mist") + #echo "♨" + #echo "﹌" + echo "〰" + ;; + "breezy") + #echo "🌬" + echo "🍃" + ;; + "windy" | "fair/windy") + #echo "⚐" + echo "⚑" + ;; + "clear" | "fair" | "cold") + hourmin=$(date +%H%M) + if [ "$hourmin" -ge "$sunset" -o "$hourmin" -le "$sunrise" ]; then + echo "☾" + else + echo "〇" + fi + ;; + *) + echo "?" + ;; + esac +} + +__read_tmp_file() { + if [ ! -f "$tmp_file" ]; then + return + fi + cat "${tmp_file}" + exit +} diff --git a/tmux/powerline/segments/xkb_layout.c b/tmux/powerline/segments/xkb_layout.c new file mode 100644 index 0000000..7c94f96 --- /dev/null +++ b/tmux/powerline/segments/xkb_layout.c @@ -0,0 +1,64 @@ +/* xkb_layout + * Description: + * This program will connect to the X Server and print the id of the currently + * active keyboard layout. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <X11/XKBlib.h> + +#ifdef DEBUG + #define DO_DEBUG DEBUG +#else + #define DO_DEBUG 0 +#endif +#define DEBUG_PRINTF(...) do{ if (DO_DEBUG) { printf(__VA_ARGS__);} } while(0) + +int main() { + // Get X display + char *displayName = ""; + int eventCode; + int errorReturn; + int major = XkbMajorVersion; + int minor = XkbMinorVersion;; + int reasonReturn; + Display *_display = XkbOpenDisplay(displayName, &eventCode, &errorReturn, + &major, &minor, &reasonReturn); + bool error = false; + switch (reasonReturn) { + case XkbOD_BadLibraryVersion: + DEBUG_PRINTF("Bad XKB library version.\n"); + error = true; + break; + case XkbOD_ConnectionRefused: + DEBUG_PRINTF("Connection to X server refused.\n"); + error = true; + break; + case XkbOD_BadServerVersion: + DEBUG_PRINTF("Bad X11 server version.\n"); + error = true; + break; + case XkbOD_NonXkbServer: + DEBUG_PRINTF("XKB not present.\n"); + error = true; + break; + case XkbOD_Success: + break; + } + + if (error) { + return EXIT_FAILURE; + } + + // Get current state of keyboard. + int _deviceId = XkbUseCoreKbd; + XkbStateRec xkbState; + XkbGetState(_display, _deviceId, &xkbState); + // print the groupnumber, may be used with setxkbmap -query to get name + // of current layout + printf("%d\n", xkbState.group); + return 0; + return EXIT_SUCCESS; +} diff --git a/tmux/powerline/segments/xkb_layout.sh b/tmux/powerline/segments/xkb_layout.sh new file mode 100755 index 0000000..c8f38c1 --- /dev/null +++ b/tmux/powerline/segments/xkb_layout.sh @@ -0,0 +1,32 @@ +# Print the currently used keyboard layout +# This depends on a specifically developed program which prints the group id of +# the currently used layout. +# I developed the simple program myself with some guidance as I was unable to +# find anything already developed. +# Some people might suggest: +# $ setxkbmod -query -v | awk -F "+" '{print $2}' +# this will only work if you have set up XKB with a single layout which is true +# for some. + +# This script will print the correct layout even if layout is set per window. +# Exit if platform is not linux as this script is dependant on X11 + +run_segment() { + if ! shell_is_linux; then + return 1 + fi + + cd "$TMUX_POWERLINE_DIR_SEGMENTS" + if [ ! -x "xkb_layout" ]; then + make clean xkb_layout &>/dev/null + fi + + if [ -x ./xkb_layout ]; then + cur_layout_nbr=$(($(./xkb_layout)+1)); + cur_layout=$(setxkbmap -query | grep layout | sed 's/layout:\s\+//g' | \ + awk -F ',' '{print $'$(echo "$cur_layout_nbr")'}') + echo "⌨ $cur_layout" + else + return 1 + fi +} diff --git a/tmux/powerline/themes/default.sh b/tmux/powerline/themes/default.sh new file mode 100644 index 0000000..dbb06d7 --- /dev/null +++ b/tmux/powerline/themes/default.sh @@ -0,0 +1,58 @@ +# Default Theme + +if patched_font_in_use; then + TMUX_POWERLINE_SEPARATOR_LEFT_BOLD="" + TMUX_POWERLINE_SEPARATOR_LEFT_THIN="" + TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD="" + TMUX_POWERLINE_SEPARATOR_RIGHT_THIN="" +else + TMUX_POWERLINE_SEPARATOR_LEFT_BOLD="◀" + TMUX_POWERLINE_SEPARATOR_LEFT_THIN="❮" + TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD="▶" + TMUX_POWERLINE_SEPARATOR_RIGHT_THIN="❯" +fi + +TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR:-'235'} +TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR:-'255'} + +TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} +TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_LEFT_BOLD} + + +# Format: segment_name background_color foreground_color [non_default_separator] + +if [ -z $TMUX_POWERLINE_LEFT_STATUS_SEGMENTS ]; then + TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=( + "tmux_session_info 148 234" \ + "hostname 33 0" \ + #"ifstat 30 255" \ + #"ifstat_sys 30 255" \ + "lan_ip 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}" \ + "wan_ip 24 255" \ + "vcs_branch 29 88" \ + "vcs_compare 60 255" \ + "vcs_staged 64 255" \ + "vcs_modified 9 255" \ + "vcs_others 245 0" \ + ) +fi + +if [ -z $TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS ]; then + TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=( + #"earthquake 3 0" \ + "pwd 89 211" \ + "mailcount 9 255" \ + "now_playing 234 37" \ + #"cpu 240 136" \ + "load 237 167" \ + #"tmux_mem_cpu_load 234 136" \ + "battery 137 127" \ + "weather 37 255" \ + #"rainbarf 0 ${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR}" \ + #"xkb_layout 125 117" \ + "date_day 235 136" \ + "date 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + "time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + #"utc_time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + ) +fi diff --git a/tmux/powerline/themes/paramah.sh b/tmux/powerline/themes/paramah.sh new file mode 100644 index 0000000..daa91f2 --- /dev/null +++ b/tmux/powerline/themes/paramah.sh @@ -0,0 +1,59 @@ +# Default Theme + +if patched_font_in_use; then + TMUX_POWERLINE_SEPARATOR_LEFT_BOLD="" + TMUX_POWERLINE_SEPARATOR_LEFT_THIN="" + TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD="" + TMUX_POWERLINE_SEPARATOR_RIGHT_THIN="" +else + TMUX_POWERLINE_SEPARATOR_LEFT_BOLD="◀" + TMUX_POWERLINE_SEPARATOR_LEFT_THIN="❮" + TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD="▶" + TMUX_POWERLINE_SEPARATOR_RIGHT_THIN="❯" +fi + +TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR:-'0'} +TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR:-'255'} + +TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} +TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_LEFT_BOLD} + + +# Format: segment_name background_color foreground_color [non_default_separator] + +if [ -z $TMUX_POWERLINE_LEFT_STATUS_SEGMENTS ]; then + TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=( + "hostname 228 234" \ + "tmux_session_info 208 232" \ + #"ifstat 30 255" \ + #"ifstat_sys 30 255" \ + "lan_ip 124 234" \ + #"wan_ip 234 255" \ + #"vcs_branch 29 88" \ + #"vcs_compare 60 255" \ + #"vcs_staged 64 255" \ + #"vcs_modified 9 255" \ + #"vcs_others 245 0" \ + ) +fi + +if [ -z $TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS ]; then + TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=( + #"earthquake 3 0" \ + #"pwd 89 211" \ + #"mailcount 9 255" \ + #"now_playing 234 37" \ + #"cpu 240 136" \ + #"tmux_mem_cpu_load 234 136" \ + "battery 124 234" \ + #"weather 37 255" \ + #"rainbarf 0 ${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR}" \ + #"xkb_layout 125 117" \ + "date_day 235 136" \ + "date 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + "time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + "thyme 124 167" \ + "powerline_taskwarrior.context" \ + #"utc_time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \ + ) +fi