Heya again, as discussed in IRC I corrected some subtleties and bugs in all the shell scripts. The attached patch is updated compared to the version posted in IRC, it fixes an additional bug in herbstcommander.sh and panel.sh, where tags are not split correctly (by any whitespace instead of tabs only). I quickly tested every script after the update and looked over the source again, and things worked like expected. Florian
From b0f03959a6a7e864194fd7249925e5c8379c4552 Mon Sep 17 00:00:00 2001 From: Florian Bruhin <git _at_ the _minus_ compiler _dot_ org> Date: Tue, 18 Jun 2013 15:20:33 +0200 Subject: [PATCH] Cleanup, simplifications and bugfixes in scripts Everywhere: - Replace all-caps variable names by lower-case ones, because upper-case variable names should be reserved for environment variables. http://stackoverflow.com/a/673940/2085149 - Replace multiple sed calls to the same file with one sed-call with multiple -e arguments. - Use consistent spacing for pipes - Quote variables which could potentially have whitespace in them (monitor names, tag names, file paths) http://mywiki.wooledge.org/Quotes#line-28 In release.sh: - Use "read -a" to read version into an array. This does not depend on tr and saves an external binary call. http://mywiki.wooledge.org/BashGuide/Arrays#line-81 - Fix typo in comment In dumpbeautify.sh: - Remove unneeded semicolons in awk script - Print color clear character directly from awk, saving a sed call - Print an additional clear after output is finished - Use & for the backreference for sed (faster, easier to read) In exec_on_tag.sh: - Use "hc attr" to get current tag In floatmon.sh: - Replace grep | cut | sed by single sed call - Check if xwininfo exists In herbstcommander.sh: - Split tags up correctly (only by tab, not any whitespace) In q3terminal.sh: - Bugfix: hc add "$tag", not scratchpad hardcoded - Don't use $ for variables inside ((..)) (consistency) - Add whitespace in calculations (easier to read) In panel.sh: - Change geometry comment to reflect real monitor_rect output - Replace 'if [ -e "$(which foo)" ]' by simple 'if which foo'. which has an exit status saying if it has found anything or not, so there is no need to check it's output. - Use "foo()" instead of "function foo()" Consistency, and "function foo()" is not portable, not even across all bash versions. http://mywiki.wooledge.org/BashPitfalls#function_foo.28.29 - Use \" instead of quote-mixing to get literal " inside "..." (easier to read) - Use simple sed call instead of cut | grep - Remove superfluous check if ${cmd[1]} is empty, as $monitor will never be empty. - Split tags up correctly (only by tab, not any whitespace) --- release.sh | 34 ++++++++++++++-------------- scripts/dmenu.sh | 4 ++-- scripts/dumpbeautify.sh | 56 +++++++++++++++++++++++----------------------- scripts/exec_on_tag.sh | 16 +++++-------- scripts/floatmon.sh | 38 ++++++++++++++++++++----------- scripts/herbstcommander.sh | 2 +- scripts/lasttag.sh | 8 +++---- scripts/layout.sh | 12 +++++----- scripts/loadstate.sh | 4 ++-- scripts/q3terminal.sh | 27 +++++++++++----------- scripts/savestate.sh | 4 ++-- share/panel.sh | 26 ++++++++++----------- share/restartpanels.sh | 10 ++++----- 13 files changed, 123 insertions(+), 118 deletions(-) diff --git a/release.sh b/release.sh index 31ea228..9316314 100755 --- a/release.sh +++ b/release.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="$1" +version="$1" if [ -z "$1" ] || [ "$1" = -h ] ; then echo "$0 VERSIONMAJOR.VERSIONMINOR.VERSIONPATCH" @@ -13,47 +13,47 @@ if git status --porcelain | grep '^ M' ; then exit 1 fi -VERSIONARGS=( $(tr . ' ' <<< "$VERSION") ) +IFS=. read -a versionargs <<< "$version" echo "==> Release commit" echo ":: Patching version.mk" -sed -i "s/^VERSION_MAJOR.*$/VERSION_MAJOR = ${VERSIONARGS[0]}/" version.mk -sed -i "s/^VERSION_MINOR.*$/VERSION_MINOR = ${VERSIONARGS[1]}/" version.mk -sed -i "s/^VERSION_PATCH.*$/VERSION_PATCH = ${VERSIONARGS[2]}/" version.mk +sed -i -e "s/^VERSION_MAJOR.*$/VERSION_MAJOR = ${versionargs[0]}/" \ + -e "s/^VERSION_MINOR.*$/VERSION_MINOR = ${versionargs[1]}/" \ + -e "s/^VERSION_PATCH.*$/VERSION_PATCH = ${versionargs[2]}/" version.mk echo ":: Patching NEWS" date=$(date +%Y-%m-%d) -newheader="Release $VERSION on $date" -newunderline="$(echo $newheader|sed 's/./-/g')" +newheader="Release $version on $date" +newunderline="$(echo $newheader | sed 's/./-/g')" headerexp="^Next Release: [^ ]*$" -# this requires news sed -sed -i -e "/$headerexp/,+1s/^[-]*$/$newunderline/" NEWS -sed -i -e "s/$headerexp/$newheader/" NEWS +# this requires new sed +sed -i -e "/$headerexp/,+1s/^[-]*$/$newunderline/" \ + -e "s/$headerexp/$newheader/" NEWS echo ":: Commiting changes" git add NEWS version.mk -git commit -m "Release $VERSION" +git commit -m "Release $version" echo ":: Tagging commit" -git tag -s v$VERSION -m "Release $VERSION" +git tag -s "v$version" -m "Release $version" echo "==> Tarball" echo ":: Tarball creation" make tar -tarball=herbstluftwm-$VERSION.tar.gz -md5sum=$(md5sum $tarball| head -c 13 ) +tarball="herbstluftwm-$version.tar.gz" +md5sum=$(md5sum "$tarball" | head -c 13 ) echo ":: Patching www/index.txt" line=$(printf "| %-7s | $date | $md5sum...%15s| link:tarballs/%s[tar.gz]" \ - $VERSION ' ' "$tarball" ) + $version ' ' "$tarball" ) linerexp="// do not remove this: next version line will be added here" sed -i "s#^$linerexp\$#$line\n$linerexp#" www/index.txt echo ":: Commiting changes" git add www/index.txt -git commit -m "www: Add $VERSION tarball" +git commit -m "www: Add $version tarball" echo echo "Still to do:" echo "1. Add the following line to the MD5SUMS file on the mirror:" -md5sum $tarball +md5sum "$tarball" echo "2. Make www files and install them on the remote" echo "3. Push the changes to all public remotes (including --tags)" diff --git a/scripts/dmenu.sh b/scripts/dmenu.sh index 24bd556..064e909 100755 --- a/scripts/dmenu.sh +++ b/scripts/dmenu.sh @@ -8,8 +8,8 @@ dmenu_cmd() { } simple_command() { - arg=$($hc complete 1 "$@"|dmenu_cmd -p "$@:") \ - && exec $hc "$@" "$arg" + arg=$("$hc" complete 1 "$@" | dmenu_cmd -p "$@:") \ + && exec "$hc" "$@" "$arg" } simple_command "$1" diff --git a/scripts/dumpbeautify.sh b/scripts/dumpbeautify.sh index 3301306..423d167 100755 --- a/scripts/dumpbeautify.sh +++ b/scripts/dumpbeautify.sh @@ -7,54 +7,54 @@ awkcode=' BEGIN { indent=2 - ORS=""; - x=0; - open=0; + ORS="" + x=0 + open=0 first=1 - i=0; - color[i++]="\033[1;31m"; - color[i++]="\033[1;32m"; - color[i++]="\033[1;33m"; - color[i++]="\033[1;34m"; - color[i++]="\033[1;35m"; - color[i++]="\033[1;36m"; - color[i++]="\033[1;37m"; - color[i++]="\033[0;31m"; - color[i++]="\033[0;32m"; - color[i++]="\033[0;33m"; - color[i++]="\033[0;34m"; - color[i++]="\033[0;35m"; - color[i++]="\033[0;36m"; - color[i++]="\033[0;37m"; + i=0 + color[i++]="\033[1;31m" + color[i++]="\033[1;32m" + color[i++]="\033[1;33m" + color[i++]="\033[1;34m" + color[i++]="\033[1;35m" + color[i++]="\033[1;36m" + color[i++]="\033[1;37m" + color[i++]="\033[0;31m" + color[i++]="\033[0;32m" + color[i++]="\033[0;33m" + color[i++]="\033[0;34m" + color[i++]="\033[0;35m" + color[i++]="\033[0;36m" + color[i++]="\033[0;37m" } $1 ~ "^[(]" { if (first == 0) { - printf "\n"; - printf "%"(indent*x)"s" , "" ; + printf "\n" + printf "%"(indent*x)"s" , "" } else { - first=0; + first=0 } color_bracket[x]=open print color[(color_bracket[x]) % length(color)] - print ; + gsub("[(]", "&" clear) + print x++ - open++; + open++ } $1 ~ "[)]" { - x-- ; + x-- print color[(color_bracket[x]) % length(color)] print } END { - printf "\n" + printf clear "\n" } ' clear=$(tput sgr0) || clear=$(echo -e '\e[0m') -sed 's/\([()]\)/\n\1/g' | # insert newlines before ( - awk "$awkcode" | - sed 's#(#('"$clear"'#g' +sed 's/[()]/\n&/g' | # insert newlines before ( + awk -v "clear=$clear" "$awkcode" diff --git a/scripts/exec_on_tag.sh b/scripts/exec_on_tag.sh index 5c552db..a0d7f6a 100755 --- a/scripts/exec_on_tag.sh +++ b/scripts/exec_on_tag.sh @@ -1,7 +1,7 @@ #!/bin/bash -TAG="$1" -EXPIRE="120" # expiry time in seconds +tag="$1" +expire="120" # expiry time in seconds shift if [ -z "$1" ] ;then @@ -16,18 +16,12 @@ hc() { herbstclient "$@" } -curtag() { - hc tag_status \ - | grep -oE "$(echo -ne '\t')#[^$(echo -ne '\t')]*" \ - | tail -c +3 -} - -TAG=${TAG:-$(curtag)} +tag=${tag:-$(hc attr tags.focus.name)} # ensure tag exists -hc add "$TAG" +hc add "$tag" # move next window from this process to this tag -hc rule maxage="$EXPIRE" pid="$$" tag="$TAG" once +hc rule maxage="$expire" pid="$$" tag="$tag" once exec "$@" diff --git a/scripts/floatmon.sh b/scripts/floatmon.sh index 9f1f053..50267f8 100755 --- a/scripts/floatmon.sh +++ b/scripts/floatmon.sh @@ -7,21 +7,33 @@ Floatkey=${Floatkey:-Shift-f} hc() { herbstclient "$@" ; } -size=$(xwininfo -root | - grep -E '^ (Width|Height):' | - cut -d' ' -f4 | - sed 'N;s/\n/x/') +if which xwininfo &> /dev/null; then + size=$(xwininfo -root | + sed -n -e '/^ Width: / { + s/.*: //; + h + } + /^ Height: / { + s/.*: //g; + H; + x; + s/\n/x/p + }') +else + echo "This script requires the xwininfo binary." + exit 1 +fi -hc chain , add $tag , floating $tag on -hc or , add_monitor "$size"+0+0 $tag $monitor \ - , move_monitor $monitor "$size"+0+0 -hc raise_monitor $monitor -hc lock_tag $monitor +hc chain , add "$tag" , floating "$tag" on +hc or , add_monitor "$size"+0+0 "$tag" "$monitor" \ + , move_monitor "$monitor" "$size"+0+0 +hc raise_monitor "$monitor" +hc lock_tag "$monitor" cmd=( or case: and # if not on floating monitor - . compare monitors.focus.name != $monitor + . compare monitors.focus.name != "$monitor" # and if a client is focused . get_attr clients.focus.winid # then remember the last monitor of the client @@ -30,12 +42,12 @@ or case: and . substitute M monitors.focus.index set_attr clients.focus.my_lastmon M # and then move the client to the floating tag - . shift_to_monitor $monitor - . focus_monitor $monitor + . shift_to_monitor "$monitor" + . focus_monitor "$monitor" . true case: and # if on the floating monitor - . compare monitors.focus.name = $monitor + . compare monitors.focus.name = "$monitor" # and if a client is focused . get_attr clients.focus.winid # then send it back to the original monitor diff --git a/scripts/herbstcommander.sh b/scripts/herbstcommander.sh index 244d286..2b42578 100755 --- a/scripts/herbstcommander.sh +++ b/scripts/herbstcommander.sh @@ -43,7 +43,7 @@ while :; do else case "${cmd[*]}" in raise|jumpto|bring) - tags=( $($herbstclient_cmd tag_status) ) + IFS=$'\t' read -a tags <<< "$($herbstclient_cmd tag_status)" i=1 completion=$( wmctrl -l | while read line; do diff --git a/scripts/lasttag.sh b/scripts/lasttag.sh index c329227..43388e6 100755 --- a/scripts/lasttag.sh +++ b/scripts/lasttag.sh @@ -8,14 +8,14 @@ herbstclient --idle '(tag_changed|goto_last_tag|reload)' \ | while read line ; do - ARGS=( $line ) + args=( $line ) case ${ARGS[0]} in tag_changed) - LASTTAG="$TAG" - TAG=${ARGS[1]} + lasttag="$tag" + tag=${args[1]} ;; goto_last_tag) - ! [ -z "$LASTTAG" ] && herbstclient use "$LASTTAG" + [ "$lasttag" ] && herbstclient use "$lasttag" ;; reload) exit diff --git a/scripts/layout.sh b/scripts/layout.sh index c631a84..68d8ed5 100755 --- a/scripts/layout.sh +++ b/scripts/layout.sh @@ -3,14 +3,14 @@ # print layout of all tags, and colorizes all window ids # it's useful to get a overview over the list of all windows -hc=${herbstclient_command:-herbstclient} +hc="${herbstclient_command:-herbstclient}" -$hc complete 1 use | +"$hc" complete 1 use | while read tag ; do echo -n "$tag " - indent=$(echo -n "$tag "|sed 's/./ /g') + indent=$(echo -n "$tag " | sed 's/./ /g') # prepend indent, except in first line - $hc layout "$tag" \ - | sed "2,\$ s/^/$indent/" \ - | sed "s/\(0x[0-9a-f]\{1,\}\)/$(tput setaf 3)\1$(tput sgr0)/g" + "$hc" layout "$tag" \ + | sed -e "2,\$ s/^/$indent/" \ + -e "s/0x[0-9a-f]\+/$(tput setaf 3)&$(tput sgr0)/g" done diff --git a/scripts/loadstate.sh b/scripts/loadstate.sh index 1c5e0a0..75ccbe9 100755 --- a/scripts/loadstate.sh +++ b/scripts/loadstate.sh @@ -13,6 +13,6 @@ hc=${herbstclient_command:-herbstclient} while read line ; do tag="${line%%: *}" tree="${line#*: }" - $hc add "$tag" - $hc load "$tag" "$tree" + "$hc" add "$tag" + "$hc" load "$tag" "$tree" done diff --git a/scripts/q3terminal.sh b/scripts/q3terminal.sh index 9d74580..498a5c2 100755 --- a/scripts/q3terminal.sh +++ b/scripts/q3terminal.sh @@ -20,20 +20,20 @@ hc() { } mrect=( $(hc monitor_rect -p "" ) ) -termwidth=$(((${mrect[2]}*8)/10)) +termwidth=$(( (${mrect[2]} * 8) / 10 )) termheight=400 rect=( $termwidth $termheight - $((${mrect[0]}+(${mrect[2]}-termwidth)/2)) - $((${mrect[1]}-termheight)) + $(( ${mrect[0]} + (${mrect[2]} - termwidth) / 2 )) + $(( ${mrect[1]} - termheight )) ) y_line=${mrect[1]} -hc add scratchpad +hc add "$tag" monitor=q3terminal @@ -45,9 +45,9 @@ if ! hc add_monitor $(printf "%dx%d%+d%+d" "${rect[@]}") \ else # remember which monitor was focused previously hc chain \ - , new_attr string monitors.by-name.$monitor.my_prev_focus \ + , new_attr string monitors.by-name."$monitor".my_prev_focus \ , substitute M monitors.focus.index \ - set_attr monitors.by-name.$monitor.my_prev_focus M + set_attr monitors.by-name."$monitor".my_prev_focus M fi update_geom() { @@ -61,19 +61,18 @@ interval=0.01 animate() { progress=( "$@" ) for i in "${progress[@]}" ; do - rect[3]=$((${y_line}-(i*termheight)/$steps)) + rect[3]=$((y_line - (i * termheight) / steps)) update_geom sleep "$interval" done } show() { - hc lock - hc raise_monitor $monitor - hc focus_monitor $monitor + hc raise_monitor "$monitor" + hc focus_monitor "$monitor" hc unlock - hc lock_tag $monitor + hc lock_tag "$monitor" animate $(seq $steps -1 0) } @@ -91,10 +90,10 @@ hide() { animate $(seq 0 +1 $steps) # if q3terminal still is focused, then focus the previously focused monitor # (that mon which was focused when starting q3terminal) - hc substitute M monitors.by-name.$monitor.my_prev_focus \ - and + compare monitors.focus.name = $monitor \ + hc substitute M monitors.by-name."$monitor".my_prev_focus \ + and + compare monitors.focus.name = "$monitor" \ + focus_monitor M - hc remove_monitor $monitor + hc remove_monitor "$monitor" } [ $exists = true ] && hide || show diff --git a/scripts/savestate.sh b/scripts/savestate.sh index b717f46..d5ab007 100755 --- a/scripts/savestate.sh +++ b/scripts/savestate.sh @@ -10,8 +10,8 @@ hc=${herbstclient_command:-herbstclient} # and sometime later: # loadstate.sh < mystate -$hc complete 1 use | +"$hc" complete 1 use | while read tag ; do echo -n "$tag: " - $hc dump "$tag" + "$hc" dump "$tag" done diff --git a/share/panel.sh b/share/panel.sh index 6bb01b1..cdad890 100755 --- a/share/panel.sh +++ b/share/panel.sh @@ -10,7 +10,7 @@ if [ -z "$geometry" ] ;then echo "Invalid monitor $monitor" exit 1 fi -# geometry has the format: WxH+X+Y +# geometry has the format W H X Y x=${geometry[0]} y=${geometry[1]} panel_width=${geometry[2]} @@ -23,9 +23,9 @@ selfg='#101010' #### # Try to find textwidth binary. # In e.g. Ubuntu, this is named dzen2-textwidth. -if [ -e "$(which textwidth 2> /dev/null)" ] ; then +if which textwidth &> /dev/null ; then textwidth="textwidth"; -elif [ -e "$(which dzen2-textwidth 2> /dev/null)" ] ; then +elif which dzen2-textwidth &> /dev/null ; then textwidth="dzen2-textwidth"; else echo "This script requires the textwidth tool of the dzen2 project." @@ -41,8 +41,8 @@ else dzen2_svn="" fi -function uniq_linebuffered() { - awk -W interactive '$0 != l { print ; l=$0 ; fflush(); }' "$@" +uniq_linebuffered() { + awk -W interactive '$0 != l { print ; l=$0 ; fflush(); }' "$@" 2>/dev/null } herbstclient pad $monitor $panel_height @@ -52,12 +52,12 @@ herbstclient pad $monitor $panel_height while true ; do date +'date ^fg(#efefef)%H:%M^fg(#909090), %Y-%m-^fg(#efefef)%d' sleep 1 || break - done > >(uniq_linebuffered) & + done > >(uniq_linebuffered) & childpid=$! herbstclient --idle kill $childpid } 2> /dev/null | { - TAGS=( $(herbstclient tag_status $monitor) ) + IFS=$'\t' read -a tags <<< "$(herbstclient tag_status $monitor)" visible=true date="" windowtitle="" @@ -65,7 +65,7 @@ herbstclient pad $monitor $panel_height bordercolor="#26221C" separator="^bg()^fg($selbg)|" # draw tags - for i in "${TAGS[@]}" ; do + for i in "${tags[@]}" ; do case ${i:0:1} in '#') echo -n "^bg($selbg)^fg($selfg)" @@ -84,7 +84,7 @@ herbstclient pad $monitor $panel_height ;; esac if [ ! -z "$dzen2_svn" ] ; then - echo -n "^ca(1,herbstclient focus_monitor $monitor && "'herbstclient use "'${i:1}'") '"${i:1} ^ca()" + echo -n "^ca(1,herbstclient focus_monitor $monitor && herbstclient use \"${i:1}\") ${i:1} ^ca()" else echo -n " ${i:1} " fi @@ -93,7 +93,7 @@ herbstclient pad $monitor $panel_height echo -n "^bg()^fg() ${windowtitle//^/^^}" # small adjustments right="$separator^bg() $date $separator" - right_text_only=$(echo -n "$right"|sed 's.\^[^(]*([^)]*)..g') + right_text_only=$(echo -n "$right" | sed 's.\^[^(]*([^)]*)..g') # get width of right aligned text.. and add some space.. width=$($textwidth "$font" "$right_text_only ") echo -n "^pa($(($panel_width - $width)))$right" @@ -105,7 +105,7 @@ herbstclient pad $monitor $panel_height case "${cmd[0]}" in tag*) #echo "resetting tags" >&2 - TAGS=( $(herbstclient tag_status $monitor) ) + IFS=$'\t' read -a tags <<< "$(herbstclient tag_status $monitor)" ;; date) #echo "resetting date" >&2 @@ -115,8 +115,8 @@ herbstclient pad $monitor $panel_height exit ;; togglehidepanel) - currentmonidx=$(herbstclient list_monitors |grep ' \[FOCUS\]$'|cut -d: -f1) - if [ -n "${cmd[1]}" ] && [ "${cmd[1]}" -ne "$monitor" ] ; then + currentmonidx=$(herbstclient list_monitors | sed -n '/\[FOCUS\]$/s/:.*//p') + if [ "${cmd[1]}" -ne "$monitor" ] ; then continue fi if [ "${cmd[1]}" = "current" ] && [ "$currentmonidx" -ne "$monitor" ] ; then diff --git a/share/restartpanels.sh b/share/restartpanels.sh index 320a3fe..9d9110c 100755 --- a/share/restartpanels.sh +++ b/share/restartpanels.sh @@ -2,15 +2,15 @@ installdir=/ -XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} +XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" defaultpanel="$XDG_CONFIG_HOME/herbstluftwm/panel.sh" -[ -x "$defaultpanel" ] || defaultpanel=$installdir/etc/xdg/herbstluftwm/panel.sh +[ -x "$defaultpanel" ] || defaultpanel="$installdir/etc/xdg/herbstluftwm/panel.sh" -panelcmd=${1:-$defaultpanel} +panelcmd="${1:-$defaultpanel}" herbstclient emit_hook quit_panel -for i in $(herbstclient list_monitors|cut -d':' -f1) ; do - $panelcmd $i & +for i in $(herbstclient list_monitors | cut -d':' -f1) ; do + "$panelcmd" $i & done -- 1.8.3.1
Attachment:
pgpJbmChni6HZ.pgp
Description: PGP signature
Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev