dotfiles

Linux and macOS dotfiles
git clone https://github.com/michaelneuper/dotfiles.git
README | Files | Log | Refs

commit 26092b3d2cf0b6727c894a2c3ac2fb6c31371e34
parent 15fa2136411b21a8598f78faa0fbf67dd5493b3f
Author: Michael Neuper <73108749+michaelneuper@users.noreply.github.com>
Date:   Fri,  2 Dec 2022 20:33:36 +0200

Completely change polybar

Diffstat:
C.config/polybar/config.ini -> .config/polybar/config.bak | 0
M.config/polybar/config.ini | 50++++++++++----------------------------------------
M.config/polybar/launch.sh | 13+++++++------
M.config/polybar/modules.ini | 151+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
A.config/polybar/scripts/env.sh | 3+++
A.config/polybar/scripts/ixwindow/generate-icon | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/polybar/scripts/ixwindow/ixwindow | 226+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/polybar/scripts/ixwindow/polybar-xwindow-icon | 0
A.config/polybar/scripts/ixwindow/polybar-xwindow-icon.cpp | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/polybar/scripts/redshift.sh | 47+++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 612 insertions(+), 91 deletions(-)

diff --git a/.config/polybar/config.ini b/.config/polybar/config.bak diff --git a/.config/polybar/config.ini b/.config/polybar/config.ini @@ -25,55 +25,25 @@ padding = 2 border-size = 0 border-color = ${color.foreground} height = 30 -;radius = 20 +radius = 0 ;Works very well with a radius like this! Put it on every bar. background = ${color.background} foreground = ${color.foreground} override-redirect=false -offset-y = 10 +offset-y = 0 wm-restack = bspwm separator = " " -[bar/workspaces] +[bar/mybar] inherit = bar/root -width = 20.5% -offset-x = 0.5% -line-size = 1 -modules-left = arch sep workspaces +override-redirect = true +width = 100% +offset-x = 0% +line-size = 0 +modules-left = arch sep workspaces sep title +modules-right = cpu memory filesystem redshift updates sep time sep powermenu +modules-center = mpris alsa scroll-up = bspwm-desknext scroll-down = bspwm-deskprev -[bar/win-title] -inherit = bar/root -enable-ipc = true -width = 28.25% -offset-x = 21.5% -modules-left = title - -[bar/music] -inherit = bar/root -enable-ipc = true -width = 26.75% -offset-x = 50.25% -modules-left = alsa -modules-center = mpris mpris-play-pause - -[bar/info] -inherit = bar/root -width = 14.5% -offset-x = 77.5% -modules-center = cpu memory filesystem updates - -[bar/time] -inherit = bar/root -width = 4.4% -offset-x = 92.5% -modules-center = time - -[bar/power] -inherit = bar/root -width = 2% -offset-x = 97.5% -modules-center = powermenu - diff --git a/.config/polybar/launch.sh b/.config/polybar/launch.sh @@ -11,12 +11,13 @@ while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done # Launch the bar # polybar -q main -c "$DIR"/config.ini & -polybar -q workspaces & -polybar -q win-title & -polybar -q music & -polybar -q info & -polybar -q time & -polybar -q power & +# polybar -q workspaces & +# polybar -q win-title & +# polybar -q music & +# polybar -q info & +# polybar -q time & +# polybar -q power & +polybar -q mybar & # IPC settings and test ln -sf /tmp/polybar_mqueue.$! /tmp/ipc-main diff --git a/.config/polybar/modules.ini b/.config/polybar/modules.ini @@ -56,29 +56,29 @@ label-private-foreground = #bd2c40 ;; Modules by @adi1090x and @raven2cz ; Modified by me -;[module/bspwm] -; type = internal/bspwm +[module/bspwm] +type = internal/bspwm ; Only show workspaces defined on the same output as the bar ; NOTE: The bspwm and XRandR monitor names must match, which they do by default. ; Default: true -; pin-workspaces = true +pin-workspaces = true ; Output mode flags after focused state label ; Default: false -; inline-mode = false +inline-mode = false ; Create click handler used to focus workspace ; Default: true -; enable-click = false +enable-click = true ; Create scroll handlers used to cycle workspaces ; Default: true -; enable-scroll = false +enable-scroll = true ; Set the scroll cycle direction ; Default: true -; reverse-scroll = false +reverse-scroll = false ; Use fuzzy (partial) matching on labels when assigning ; icons to workspaces @@ -89,24 +89,29 @@ label-private-foreground = #bd2c40 ; ws-icon-[0-9]+ = label;icon ; Note that the label needs to correspond with the bspwm workspace name -;;ws-icon-0 = code;♚ -;;ws-icon-1 = office;♛ -;;ws-icon-2 = graphics;♜ -;;ws-icon-3 = mail;♝ -;;ws-icon-4 = web;♞ -;;ws-icon-default = ♟ +ws-icon-0 = 1;一 +ws-icon-1 = 2;二 +ws-icon-2 = 3;三 +ws-icon-3 = 4;四 +ws-icon-4 = 5;五 +ws-icon-5 = 6;六 +ws-icon-6 = 7;七 +ws-icon-7 = 8;八 +ws-icon-8 = 9;九 +ws-icon-9 = 10;十 +ws-icon-default =  ; Available tags: ; <label-monitor> ; <label-state> - gets replaced with <label-(focused|urgent|occupied|empty)> ; <label-mode> - gets replaced with <label-(monocle|tiled|fullscreen|floating|locked|sticky|private)> ; Default: <label-state> -;;format = <label-state> <label-mode> +format = <label-state> | <label-mode> ; Available tokens: ; %name% ; Default: %name% -;;label-monitor = %name% +label-monitor = %name% ; If any values for label-dimmed-N are defined, the workspace/mode ; colors will get overridden with those values if the monitor is out of focus @@ -115,67 +120,66 @@ label-private-foreground = #bd2c40 ; label-dimmed-occupied ; label-dimmed-urgent ; label-dimmed-empty -;;label-dimmed-foreground = #555 -;;label-dimmed-underline = ${bar/top.background} -;;label-dimmed-focused-background = #f00 +; label-dimmed-foreground = #555 +; label-dimmed-underline = ${bar/top.background} +; label-dimmed-focused-background = #f00 ; Available tokens: ; %name% ; %icon% ; %index% ; Default: %icon% %name% -;;label-focused = %icon% -;;label-focused-foreground = #ffffff -;;label-focused-background = #3f3f3f -;;label-focused-underline = #fba922 +label-focused = [%index%:%icon%] +label-focused-foreground = ${color.purple} +; label-focused-background = #3f3f3f +label-focused-underline = ${color.purple} ; Available tokens: ; %name% ; %icon% ; %index% ; Default: %icon% %name% -;;label-occupied = %icon% -;;label-occupied-underline = #55555 +label-occupied = %icon% +label-occupied-foreground = ${color.cyan} ; Available tokens: ; %name% ; %icon% ; %index% ; Default: %icon% %name% -;;label-urgent = %icon% -;;label-urgent-foreground = #000000 -;;label-urgent-background = #bd2c40 -;;label-urgent-underline = #9b0a20 +label-urgent = %icon% +label-urgent-foreground = ${color.red} +; label-urgent-underline = ${color.red} ; Available tokens: ; %name% ; %icon% ; %index% ; Default: %icon% %name% -;;label-empty = %icon% -;;label-empty-foreground = #55 +label-empty = %icon% +label-empty-foreground = ${color.foreground} ; The following labels will be used to indicate the layout/mode ; for the focused workspace. Requires <label-mode> ; ; Available tokens: ; None -;label-monocle =  -;label-tiled =  -;label-fullscreen =  -;label-floating =  -;label-pseudotiled = P -;label-locked =  -;label-locked-foreground = #bd2c40 -;label-sticky =  -;label-sticky-foreground = #fba922 -;label-private =  -;label-private-foreground = #bd2c40 +label-monocle = M +label-tiled = T +label-fullscreen = F +label-floating = f +label-pseudotiled = P +label-locked = ? +label-locked-foreground = ${color.red} +label-sticky = S +label-sticky-foreground = ${color.yellow} +label-private = p +label-private-foreground = ${color.red} ; Separator in between workspaces -;;label-separator = | -;;label-separator-padding = 2 -;;label-separator-foreground = #ffb52a +label-separator = " " +label-separator-padding = 0.75 +label-separator-foreground = #ffb52a [module/workspaces] type = internal/xworkspaces @@ -403,7 +407,7 @@ interval = 5 ; <label> (default) format = <label> format-prefix =  -format-prefix-foreground = ${color.yellow} +format-prefix-foreground = ${color.indigo} ; Available tokens: ; %output% @@ -605,3 +609,60 @@ ramp-volume-0 =  ramp-volume-1 =  ramp-volume-2 =  ramp-volume-foreground = ${color.blue} + +[module/mpd] +type = internal/mpd + +;;host = 127.0.0.1 +;;port = 6600 +;;password = mysecretpassword + +interval = 2 + +format-online = <label-song> <icon-prev> <toggle> <icon-next> +format-online-prefix = " " +format-online-prefix-foreground = ${color.green} + +format-playing = ${self.format-online} +format-paused = <label-song> <toggle> + +format-offline = <label-offline> +format-offline-prefix = " " +format-offline-prefix-foreground = ${color.red} +label-offline = "Offline" + +label-song = "%title% | %artist%" +label-song-maxlen = 40 +label-song-ellipsis = true + +icon-play =  +icon-play-font = 2 +icon-play-foreground = ${color.green} +icon-pause =  +icon-pause-font = 2 +icon-pause-foreground = ${color.yellow} +icon-stop =  +icon-stop-foreground = ${color.red} +icon-prev = 玲 +icon-prev-font = 2 +icon-prev-foreground = ${color.cyan} +icon-next = 怜 +icon-next-font = 2 +icon-next-foreground = ${color.cyan} + +; https://github.com/VineshReddy/polybar-redshift.git +[module/redshift] +type = custom/script +format-prefix = " " +format-prefix-foreground = ${color.amber} +exec = source ~/.config/polybar/scripts/env.sh && ~/.config/polybar/scripts/redshift.sh temperature +click-left = source ~/.config/polybar/scripts/env.sh && ~/.config/polybar/scripts/redshift.sh toggle +scroll-up = source ~/.config/polybar/scripts/env.sh && ~/.config/polybar/scripts/redshift.sh increase +scroll-down = source ~/.config/polybar/scripts/env.sh && ~/.config/polybar/scripts/redshift.sh decrease +interval=0.5 + +; https://github.com/andreykaere/ixwindow.git +[module/ixwindow] +type = custom/script +exec = ~/.config/polybar/scripts/ixwindow/ixwindow +tail = true diff --git a/.config/polybar/scripts/env.sh b/.config/polybar/scripts/env.sh @@ -0,0 +1,3 @@ + +export REDSHIFT=on +export REDSHIFT_TEMP=2900 diff --git a/.config/polybar/scripts/ixwindow/generate-icon b/.config/polybar/scripts/ixwindow/generate-icon @@ -0,0 +1,65 @@ +#!/bin/bash + + +# Most of the code taken from +# https://unix.stackexchange.com/questions/48860/how-to-dump-the-icon-of-a-running-x-program + + +SIZE=$$SIZE +COLOR=$$COLOR + +wid="$2" +# wid="$(xdotool selectwindow)" +# class="$(bspc query -T -n "$wid" | jq -r '.client.className')" +WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')" + +name="$WM_CLASS" + + +CACHE="$1/$name" + +if [ -f "$CACHE.jpg" ]; then + exit 0 +fi + + +# Check if there is an icon for us in xprop, +# so it won't break the behavior of the script +if [ -z "$(xprop -id "$wid" | grep "Icon")" ]; then + exit 0 +fi + + +# Resize it in advance, so icons will look better, but it's not necessary, so +# you can remove "-resize" flag if you prefer it the other way +cmd=(convert -resize "$SIZE"x"$SIZE" -set 'filename:w' '%w' - "${name}.png") + +split_icons() { + xprop -id "$wid" -notype 32c _NET_WM_ICON | + awk -v RS=', | = ' ' + NR == 1 { h = $1; i++; next } + NR == i + 1 { x = $1; printf "%s = %s", h, x; next } + NR == i + 2 { s = x * $1 } { printf ", %s", $1 } + NR == i + 2 + s { i += s + 2; printf "\n" } + ' +} + +to_pam() { + perl -0777 -pe '@_=/\d+/g; + printf "P7\nWIDTH %d\nHEIGHT %d\n", splice@_,0,2; + printf "DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n"; + $_=pack "N*", @_; + s/(.)(...)/$2$1/gs' +} + + + +while read -r data; do to_pam <<< "$data" | "${cmd[@]}"; done < <(split_icons) + +convert "$name.png" -background $COLOR -flatten -alpha off "$name.jpg" +mv "$name.jpg" "$CACHE.jpg" && rm "$name.png" + + + + + diff --git a/.config/polybar/scripts/ixwindow/ixwindow b/.config/polybar/scripts/ixwindow/ixwindow @@ -0,0 +1,226 @@ +#!/bin/bash + + +# Folder for icons +CACHE=$$CACHE + +# Path to your ixwindow folder +DIR=$$DIR + + +PREV_ICON="/tmp/polybar-icon-prev" + +GAP=" " + + +# Delete previous icons, becase if there will be many +# overlaping icons it may cause a slow down of your window manager +cleanup_icons() { + local icons_id=($(xdo id -n "polybar-xwindow-icon" 2> /dev/null)) + + for icon in "${icons_id[@]}"; + do + xdo kill "$icon" &> /dev/null + done +} + + +reset_prev_icon() { + echo "" > "$PREV_ICON" +} + + + +print_info() { + echo -n "$GAP" + + if [ "$1" = "Empty" ]; then + echo "Empty" + else + local wid="$1" + + # Doesn't always work, so xprop is more realiable here + # WM_CLASS="$(bspc query -T -n "$Node" | jq -r '.client.className')" + local WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')" + + + case "$WM_CLASS" in + 'Brave-browser') + echo "Brave";; + 'TelegramDesktop') + echo "Telegram";; + *) + # https://stackoverflow.com/questions/1538676/uppercasing-first-letter-of-words-using-sed + echo "$WM_CLASS" | sed -e "s/\b\(.\)/\u\1/g";; + esac + fi +} + + +exists_fullscreen_node() { + local fullscreen_nodes="$(bspc query -N -n .fullscreen.\!hidden -d "$1")" + + if [ -n "$fullscreen_nodes" ]; then + echo '1' + else + echo '0' + fi +} + + +display_icon() { + cleanup_icons + icon="$CACHE/$1.jpg" + if [ -f "$icon" ]; then + "$DIR/polybar-xwindow-icon" "$icon" &> /dev/null & + fi +} + + +generate_icon() { + "$DIR/generate-icon" "$CACHE" "$1" +} + +update_prev_icon() { + echo "$1" > "$PREV_ICON" +} + +process_window() { + local desk="$2" + local wid="$1" + local WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')" + + # If there is a fullscreen node, don't show anything, + # since we shouldn't see it + if [ "$(exists_fullscreen_node "$desk")" = "1" ]; then + cleanup_icons + reset_prev_icon + return 0; + fi + + generate_icon "$wid" + + # We use icon-prev thing just so icon won't blink + # when one is switching between the same types of windows + local WM_CLASS_PREV="$(cat "$PREV_ICON")" + + if [ "$WM_CLASS" = "$WM_CLASS_PREV" ]; then + return 0; + else + update_prev_icon "$WM_CLASS" + fi + + + display_icon "$WM_CLASS" + + print_info "$wid" +} + + +is_desktop_empty() { + local desk="$1" + local nodes="$(bspc query -N -n .window.\!hidden -d "$desk")" + + + if [ -n "$nodes" ]; then + echo '0' + else + echo '1' + fi +} + +process_desktop() { + local desk="$1" + local is_empty="$(is_desktop_empty "$desk")" + + if [ "$is_empty" = "1" ]; then + reset_prev_icon + cleanup_icons + + print_info "Empty" + fi + +} + + +reset_prev_icon + + +bspc subscribe node_focus | while read -r Event Monitor Desktop Node +do + # For some reason "$Node" and "$Desktop" are not always working + # properly with sticky windows + Node="$(xdotool getactivewindow)" + Desktop="$(bspc query -D -d focused)" + + process_window "$Node" "$Desktop" + +done & + + +bspc subscribe node_state | while read -r Event Monitor Desktop Node State Active +do + Node="$(xdotool getactivewindow)" + Desktop="$(bspc query -D -d focused)" + + if [ "$State" != "fullscreen" ]; then + continue; + fi + + # So, if you will focus on the other windows of the same app, + # which are not fullscreen, you will see icon + + reset_prev_icon + + if [ "$Active" = "on" ]; then + cleanup_icons + else + process_window "$Node" "$Desktop" + fi + +done & + + +bspc subscribe node_add | while read -r Event Monitor Desktop Ip Node +do + State="$(bspc query -T -n "$Node" | jq -r '.client.state')" + + if [ "$State" = "fullscreen" ]; then + reset_prev_icon + cleanup_icons + fi + +done & + + +bspc subscribe node_flag | while read -r Event Monitor Desktop Node Flag Active +do + if [ "$Flag" = "hidden" ] && [ "$Desktop" = "$(bspc query -D -d .focused)" ]; then + process_desktop "$Desktop" + fi + +done & + + + + +bspc subscribe node_remove | while read -r Event Monitor Desktop Node +do + process_desktop "$Desktop" + +done & + + +bspc subscribe desktop_focus | while read -r Event Monitor Desktop +do + + if [ "$(exists_fullscreen_node "$Desktop")" = "1" ]; then + reset_prev_icon + cleanup_icons + continue; + fi + + process_desktop "$Desktop" + +done + diff --git a/.config/polybar/scripts/ixwindow/polybar-xwindow-icon b/.config/polybar/scripts/ixwindow/polybar-xwindow-icon Binary files differ. diff --git a/.config/polybar/scripts/ixwindow/polybar-xwindow-icon.cpp b/.config/polybar/scripts/ixwindow/polybar-xwindow-icon.cpp @@ -0,0 +1,148 @@ +// compilation: +// g++ polybar-xwindow-icon.cpp -o polybar-xwindow-icon -I/usr/include/opencv4/ -lopencv_core -lopencv_videoio -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lX11 +// +// Code is mostly copied from +// https://stackoverflow.com/questions/54513419/putting-image-into-a-window-in-x11 + +// Some parts are taken from +// https://stackoverflow.com/questions/57078155/draw-border-frame-using-xlib + + + +#include <opencv2/opencv.hpp> // FOR OpenCV +#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat) +#include <opencv2/video/video.hpp> +#include <opencv2/imgproc/imgproc.hpp> +#include <opencv2/highgui/highgui.hpp> + +#include <bits/stdc++.h> +#include <X11/Xlib.h> // Every Xlib program must include this +#include <assert.h> // I include this to test return values the lazy way +#include <unistd.h> // So we got the profile for 10 seconds +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xlib.h> // Every Xlib program must include this +#include <X11/Xatom.h> +#include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/shape.h> +#define NIL (0) // A name for the void pointer + +using namespace cv; +using namespace std; + +int main(int argc, char** argv) +{ + + XGCValues gr_values; + //GC gc; + XColor color, dummy; + + + Display *dpy = XOpenDisplay(NIL); + //assert(dpy); + //int screen = DefaultScreen(dpy); + // Get some colors + + int blackColor = BlackPixel(dpy, DefaultScreen(dpy)); + int whiteColor = WhitePixel(dpy, DefaultScreen(dpy)); + + // Create the window + + Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), $X, $Y, + $SIZE, $SIZE, 0, whiteColor, blackColor); + + // We want to get MapNotify events + + XSelectInput(dpy, w, StructureNotifyMask); + // XSelectInput(dpy, w, ExposureMask); + long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); + + XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False), + XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1); + + XClassHint *polybar_xwindow_icon; + + //my_struct = malloc(sizeof(t_data)); + polybar_xwindow_icon = XAllocClassHint(); + polybar_xwindow_icon->res_name = "polybar-xwindow-icon"; + polybar_xwindow_icon->res_class = "Polybar-xwindow-icon"; + + XSetClassHint(dpy, w, polybar_xwindow_icon); + XFree(polybar_xwindow_icon); + + + XMapWindow(dpy, w); + + // Wait for the MapNotify event + + for(;;) { + XEvent e; + XNextEvent(dpy, &e); + if (e.type == MapNotify) + break; + } + + Window focal = w; + + XWindowAttributes gwa; + XGetWindowAttributes(dpy, w, &gwa); + int wd1 = gwa.width; + int ht1 = gwa.height; + + + + XImage *image = XGetImage(dpy, w, 0, 0 , wd1, ht1, AllPlanes, ZPixmap); + unsigned long rm = image->red_mask; + unsigned long gm = image->green_mask; + unsigned long bm = image->blue_mask; + + Mat img(ht1, wd1, CV_8UC3); // OpenCV Mat object is initilaized + Mat scrap = imread(argv[1]);//(wid, ht, CV_8UC3); + resize(scrap, img, img.size(), cv::INTER_AREA); + + for (int x = 0; x < wd1; x++) + for (int y = 0; y < ht1 ; y++) + { + unsigned long pixel = XGetPixel(image,x,y); + + Vec3b color = img.at<Vec3b>(Point(x,y)); + + + + pixel = 65536 * color[2] + 256 * color[1] + color[0]; + + XPutPixel(image, x, y, pixel); + } + + // namedWindow("QR", CV_WINDOW_NORMAL); + // imshow("QR", img); + + + GC gc = XCreateGC(dpy, w, 0, NIL); + XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1); + + int run = 1; + + while(run) { + XEvent xe; + XNextEvent(dpy, &xe); + switch (xe.type) { + case Expose: + XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1); + XSetForeground(dpy, gc, color.pixel); + XSync(dpy, False); + break; + + default: + break; + } + } + + XDestroyWindow(dpy, w); + XCloseDisplay(dpy); + + + // waitKey(0); + return 0; +} diff --git a/.config/polybar/scripts/redshift.sh b/.config/polybar/scripts/redshift.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +envFile=~/.config/polybar/scripts/env.sh +changeValue=300 + +changeMode() { + sed -i "s/REDSHIFT=$1/REDSHIFT=$2/g" $envFile + REDSHIFT=$2 + echo $REDSHIFT +} + +changeTemp() { + if [ "$2" -gt 1000 ] && [ "$2" -lt 25000 ] + then + sed -i "s/REDSHIFT_TEMP=$1/REDSHIFT_TEMP=$2/g" $envFile + redshift -P -O $((REDSHIFT_TEMP+changeValue)) + fi +} + +case $1 in + toggle) + if [ "$REDSHIFT" = on ]; + then + changeMode "$REDSHIFT" off + redshift -x + else + changeMode "$REDSHIFT" on + redshift -O "$REDSHIFT_TEMP" + fi + ;; + increase) + changeTemp $((REDSHIFT_TEMP)) $((REDSHIFT_TEMP+changeValue)) + ;; + decrease) + changeTemp $((REDSHIFT_TEMP)) $((REDSHIFT_TEMP-changeValue)); + ;; + temperature) + case $REDSHIFT in + on) + printf "%dK" "$REDSHIFT_TEMP" + ;; + off) + printf "off" + ;; + esac + ;; +esac