diff options
author | Cody Hiar <chiar@hybridforge.com> | 2015-08-12 12:06:23 -0600 |
---|---|---|
committer | Cody Hiar <chiar@hybridforge.com> | 2015-08-12 12:06:23 -0600 |
commit | 07fc2644a237187dd4c5680e88f4adadbf533603 (patch) | |
tree | bb6335e180df48c5a6f0b893312857d36ad470f7 /segments |
Initial commit of the working files
Diffstat (limited to 'segments')
36 files changed, 2085 insertions, 0 deletions
diff --git a/segments/Makefile b/segments/Makefile new file mode 100644 index 0000000..07767b5 --- /dev/null +++ b/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/segments/battery.sh b/segments/battery.sh new file mode 100755 index 0000000..9b7084d --- /dev/null +++ b/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=$(( 100 * $curcap / $maxcap )) + 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/segments/cpu.sh b/segments/cpu.sh new file mode 100755 index 0000000..637bcda --- /dev/null +++ b/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/segments/date.sh b/segments/date.sh new file mode 100755 index 0000000..32263d5 --- /dev/null +++ b/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/segments/date_day.sh b/segments/date_day.sh new file mode 100755 index 0000000..35a42eb --- /dev/null +++ b/segments/date_day.sh @@ -0,0 +1,6 @@ +# Prints the name of the current day. + +run_segment() { + date +"%a" + return 0 +} diff --git a/segments/earthquake.sh b/segments/earthquake.sh new file mode 100755 index 0000000..3859094 --- /dev/null +++ b/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\><title>} + # 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/segments/hostname.sh b/segments/hostname.sh new file mode 100755 index 0000000..c3dfbf9 --- /dev/null +++ b/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/segments/ifstat.sh b/segments/ifstat.sh new file mode 100755 index 0000000..2666496 --- /dev/null +++ b/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 + formate=$(echo "${formate} ${type} ⇊ %.2f ⇈ %.2f") + holder=$(echo "${holder},\$$((index)),\$$((index+1))") + fi + index=$((index+2)) + done + if [ -n "${formate}" ]; then + echo $(echo "${flow_data#,}" | awk -F"," "{printf(\"${formate}\"${holder})}") + fi + return 0 +} diff --git a/segments/ifstat_sys.sh b/segments/ifstat_sys.sh new file mode 100755 index 0000000..1059dc4 --- /dev/null +++ b/segments/ifstat_sys.sh @@ -0,0 +1,28 @@ +# 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" + iface="eth0" + 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) + RXDIF=$(echo "$((RXBN - RXB)) / 1024 / ${sleeptime}" | bc ) + TXDIF=$(echo "$((TXBN - TXB)) / 1024 / ${sleeptime}" | bc ) + + if [ $RXDIF -gt 1024 ]; then + RXDIF_ECHO="↓ $(echo "scale=1;${RXDIF} / 1024" | bc)M/s" + else + RXDIF_ECHO="↓ ${RXDIF}K/s" + fi + if [ $TXDIF -gt 1024 ]; then + TXDIF_ECHO="↑ $(echo "scale=1;${TXDIF} / 1024" | bc)M/s" + else + TXDIF_ECHO="↑ ${TXDIF}K/s" + fi + + echo -e "${RXDIF_ECHO} ${TXDIF_ECHO}" + return 0 +} diff --git a/segments/lan_ip.sh b/segments/lan_ip.sh new file mode 100755 index 0000000..fe97dad --- /dev/null +++ b/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/segments/load.sh b/segments/load.sh new file mode 100755 index 0000000..7480d96 --- /dev/null +++ b/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/segments/mailcount.sh b/segments/mailcount.sh new file mode 100755 index 0000000..68029aa --- /dev/null +++ b/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 fullcount | sed 's/<[^0-9]*>//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/segments/mailcount_apple_mail.script b/segments/mailcount_apple_mail.script new file mode 100755 index 0000000..fca8acb --- /dev/null +++ b/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/segments/now_playing.sh b/segments/now_playing.sh new file mode 100755 index 0000000..6fdf251 --- /dev/null +++ b/segments/now_playing.sh @@ -0,0 +1,274 @@ +# 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_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}. +export TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER="" +# 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}" + +# 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 + case "$TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER" 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) ;; + "spotify_wine") np=$(__np_spotify_native) ;; + *) + echo "Unknown music player type [${TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER}]"; + return 1 + esac + local exitcode="$?" + 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 +} + +__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_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) # Does not tell if the music is playing or paused. + 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/segments/np_itunes.script b/segments/np_itunes.script new file mode 100755 index 0000000..8ac66bd --- /dev/null +++ b/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/segments/np_mpd.c b/segments/np_mpd.c new file mode 100644 index 0000000..97c4a6a --- /dev/null +++ b/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/segments/np_pithos.py b/segments/np_pithos.py new file mode 100755 index 0000000..9d022e6 --- /dev/null +++ b/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/segments/np_rdio_mac.script b/segments/np_rdio_mac.script new file mode 100755 index 0000000..d46bd0f --- /dev/null +++ b/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/segments/np_spotify_mac.script b/segments/np_spotify_mac.script new file mode 100755 index 0000000..91fbb63 --- /dev/null +++ b/segments/np_spotify_mac.script @@ -0,0 +1,23 @@ +#!/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 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/segments/pwd.sh b/segments/pwd.sh new file mode 100755 index 0000000..2499762 --- /dev/null +++ b/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/segments/rainbarf.sh b/segments/rainbarf.sh new file mode 100755 index 0000000..a9c6c1f --- /dev/null +++ b/segments/rainbarf.sh @@ -0,0 +1,15 @@ +# Print out Memory and CPU using https://github.com/creaktive/rainbarf + +run_segment() { + type rainbarf >/dev/null 2>&1 + if [ "$?" -ne 0 ]; then + return + fi + + # Customize via ~/.rainbarf.conf + stats=$(rainbarf --tmux) + if [ -n "$stats" ]; then + echo "$stats"; + fi + return 0 +} diff --git a/segments/time.sh b/segments/time.sh new file mode 100755 index 0000000..e307399 --- /dev/null +++ b/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/segments/tmux_mem_cpu_load.sh b/segments/tmux_mem_cpu_load.sh new file mode 100755 index 0000000..c05be3e --- /dev/null +++ b/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/segments/tmux_session_info.sh b/segments/tmux_session_info.sh new file mode 100755 index 0000000..fbfddc2 --- /dev/null +++ b/segments/tmux_session_info.sh @@ -0,0 +1,7 @@ +# Prints tmux session info. +# Assuems that [ -n "$TMUX"]. + +run_segment() { + tmux display-message -p '#S' + return 0 +} diff --git a/segments/uptime.sh b/segments/uptime.sh new file mode 100755 index 0000000..276cfbe --- /dev/null +++ b/segments/uptime.sh @@ -0,0 +1,6 @@ +# Prints the uptime. + +run_segment() { + uptime | grep -PZo "(?<=up )[^,]*" + return 0 +} diff --git a/segments/utc_time.sh b/segments/utc_time.sh new file mode 100755 index 0000000..4da6149 --- /dev/null +++ b/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/segments/vcs_branch.sh b/segments/vcs_branch.sh new file mode 100755 index 0000000..f8d973d --- /dev/null +++ b/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/segments/vcs_compare.sh b/segments/vcs_compare.sh new file mode 100755 index 0000000..988751c --- /dev/null +++ b/segments/vcs_compare.sh @@ -0,0 +1,68 @@ +# 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 + + tracking_branch=$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) + + # 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/segments/vcs_modified.sh b/segments/vcs_modified.sh new file mode 100755 index 0000000..ebec1f4 --- /dev/null +++ b/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 staged items + staged=$(git ls-files --modified | wc -l) + echo $staged +} +__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/segments/vcs_others.sh b/segments/vcs_others.sh new file mode 100755 index 0000000..0911468 --- /dev/null +++ b/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 staged items + other=$(git ls-files --others --exclude-standard | 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/segments/vcs_revision.sh b/segments/vcs_revision.sh new file mode 100755 index 0000000..0ff0f74 --- /dev/null +++ b/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/segments/vcs_staged.sh b/segments/vcs_staged.sh new file mode 100755 index 0000000..8818b3c --- /dev/null +++ b/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/segments/wan_ip.sh b/segments/wan_ip.sh new file mode 100755 index 0000000..811d100 --- /dev/null +++ b/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/segments/weather.sh b/segments/weather.sh new file mode 100755 index 0000000..74e352e --- /dev/null +++ b/segments/weather.sh @@ -0,0 +1,182 @@ +# 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="8691" +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 "http://weather.yahooapis.com/forecastrss?w=${TMUX_POWERLINE_SEG_WEATHER_LOCATION}&u=${TMUX_POWERLINE_SEG_WEATHER_UNIT}") + 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" -PZo "<yweather:units [^<>]*/>" | sed 's/.*temperature="\([^"]*\)".*/\1/') + condition=$(echo "$weather_data" | "$gnugrep" -PZo "<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"/> + sunrise=$(date -d"$(echo "$weather_data" | "$gnugrep" "yweather:astronomy" | sed 's/^\(.*\)sunset.*/\1/' | sed 's/^.*sunrise="\(.*m\)".*/\1/')" +%H%M) + sunset=$(date -d"$(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 "〰" + ;; + "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/segments/xkb_layout.c b/segments/xkb_layout.c new file mode 100644 index 0000000..7c94f96 --- /dev/null +++ b/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/segments/xkb_layout.sh b/segments/xkb_layout.sh new file mode 100755 index 0000000..c8f38c1 --- /dev/null +++ b/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 +} |