marquee1 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #!/bin/bash
  2. ########## DEFAULT VALUES ###############################################
  3. # boolean variables are '1' for true or anything else for false.
  4. wait=10 # between outputs, in s
  5. bps=555 # output bytes per s - more is faster - 555 is a good value on my machine - set to 0 to disable; requires pv to be installed.
  6. colored=1 # 0 for no colors or if command output provides colors, 1 for randomized color for each block
  7. stars=0 # sprinkle canvas witgh stars after showing command output
  8. density=3 # how many stars do you want on screen, max., in percent. Not precise.
  9. erase=0 # instead of simplyclearing the screen, erase it from top to bottom
  10. erasetime=2 # how many seconds do you wnat the erase process to last. Not precise.
  11. colors=( 1 2 3 4 5 6 ) # to work with tput. exclude black and white; bold is randomized inside the script
  12. # each line produces a block of output (later split by newline & eval'd)
  13. commands='toilet -t -f smmono12 -W -- "$(date +%R)"
  14. toilet -t -f future -- "$(date +"%A %d %B")"
  15. toilet -t -f future -- "$(uptime -p)"'
  16. ########## USER CUSTOMISATION ################
  17. config="$XDG_CONFIG_HOME/termss/${0##*/}.conf"
  18. [ -r "$config" ] && . "$config"
  19. ##############################################
  20. grep -qw toilet <<<"$commands" && ! which toilet >/dev/null && commands='echo "Please install toilet!"
  21. echo "Or configure other commands in $config"'
  22. #~ dependencies for marquee1 script
  23. for i in shuf od tput; do
  24. which "$i" >/dev/null || exit 1
  25. done
  26. # pv is an optional dependency
  27. which pv >/dev/null || bps=0
  28. # sleep as a builtin
  29. for file in /usr/lib/bash/sleep /usr/lib32/bash/sleep /usr/lib64/bash/sleep; do
  30. [ -r "$file" ] && enable -f "$file" sleep && break
  31. done
  32. # Portable enough?
  33. # let's assume terminal size doesn't change during script execution
  34. term_cols=$(tput cols)
  35. term_lines=$(tput lines)
  36. rand_func() {
  37. # more random than RANDOM? networkworld.com/article/3208389/linux/unix-how-random-is-random.html
  38. num="$(od -vAn -N2 -tu < /dev/urandom )"
  39. #num=$RANDOM
  40. # if $1 is passed, make sure random number is >= that value. if not, minimum is 0.
  41. min=${1-0}
  42. (( num < min )) && num=$((num + min))
  43. echo $num
  44. }
  45. #~ if [[ "$colored" == "1" ]]; then
  46. #~ colmax=${#colchoice[*]}
  47. #~ colchoice=$(( $(rand_func $colmax) % colmax))
  48. #~ lastcolchoice=$colchoice
  49. #~ fi
  50. tput civis # cursor invisible
  51. #~ echo -en "\e]12;10\a" # make cursor green (we need this later)
  52. oldifs="$IFS"
  53. #declare -A length
  54. while :; do
  55. longest_all=0
  56. outputlines=0
  57. count=0
  58. colchoiceprevious=()
  59. # command execution, but no output - to calculate size of complete output
  60. IFS=$'\n'
  61. while read -r -- command ; do
  62. IFS="$oldifs"
  63. # one array field for each command's output
  64. output[count]="$(eval $command)"
  65. longest[count]=0
  66. while read -r -- line ; do
  67. # find longest line
  68. (( ${#line} > longest_all )) && longest_all=${#line}
  69. (( ${#line} > ${longest[count]} )) && longest[count]=${#line}
  70. ((outputlines++))
  71. done <<<"${output[count]}"
  72. IFS=$'\n'
  73. ((count++))
  74. done <<<"$commands"
  75. IFS="$oldifs"
  76. # put cursor on random vertical position, i.e. line
  77. scope=$(( term_lines - outputlines ))
  78. vpos=0
  79. (( scope > 0 )) && vpos="$(( $(rand_func $scope) % scope ))" && tput vpa "$vpos"
  80. # random horizontal pos. offset, used later to put cursor
  81. scope=$(( term_cols - longest_all ))
  82. (( scope > 0 )) && offset_all=$(( $(rand_func $scope) % scope )) || offset_all=0
  83. # define 1 color for each command
  84. if [[ "$colored" == "1" ]]; then
  85. colchoice=( $(shuf -n$count -e ${colors[@]}) ) # once to initialise
  86. until [[ "${colchoice[@]}" != "${colchoiceprevious[@]}" ]]; do
  87. colchoice=( $(shuf -n$count -e ${colors[@]}) )
  88. done
  89. colchoiceprevious=( ${colchoice[@]} )
  90. fi
  91. # write text to random position
  92. for (( i=0 ; i<count ; i++ )) ; do
  93. [[ "$colored" == "1" ]] && tput setaf $(( ${colchoice[i]} + 8 * ( $(rand_func 2)%2 ) )) # randomly makes the color bold or not, by adding 8 to the random value, or not
  94. offset=$(( ( longest_all - ${longest[i]} ) / 2 + offset_all )) # this centers the blocks on top of each other
  95. IFS='' # necessary to include leading whitespace in line
  96. if (( bps > 0 )); then
  97. while read -r -- line ; do
  98. tput hpa $offset # place cursor horizontally
  99. tput cnorm
  100. printf "%s" "$line"
  101. tput civis
  102. printf "\n"
  103. done <<<"${output[i]}" | pv -L $bps -q --
  104. else
  105. while read -r -- line ; do
  106. tput hpa $offset # place cursor horizontally
  107. echo "$line"
  108. done <<<"${output[i]}"
  109. fi
  110. IFS="$oldifs"
  111. #~ if [[ "$colored" == "1" ]]; then
  112. #~ until [[ "$colchoice" != "$lastcolchoice" ]]; do colchoice=$(( $(rand_func $colmax) % colmax)); done
  113. #~ lastcolchoice=$colchoice
  114. #~ fi
  115. done
  116. if [[ "$stars" == 1 ]]; then
  117. # convert density to absolute number of stars desired
  118. density="$(bc <<<"scale=10;$term_cols*$term_lines/100*$density")"
  119. sleep "$(bc <<<"scale=10;$wait/10")"
  120. tput sgr0 # reset
  121. chars='*∙·•·•·•∙·•·•·•+◆●☼'
  122. #strings -e S -s '' /dev/urandom | while read -n1 char; do
  123. starsleep="$(bc <<<"scale=10;($wait-($wait/10))/$density")"
  124. while sleep "$starsleep"; do
  125. # put cursor on random position
  126. Y=$(( $(rand_func $term_lines) % term_lines ))
  127. X=$(( $(rand_func $term_cols) % term_cols ))
  128. if ((X<offset_all || X>=offset_all+longest_all)) || \
  129. ((Y<vpos || Y>=vpos+outputlines)); then
  130. tput cup $Y $X
  131. #~ # put cursor on random vertical position, i.e. line
  132. #~ scope=$term_lines
  133. #~ tput vpa $(( $(rand_func $scope) % scope ))
  134. #~ # random horizontal pos. i.e. column
  135. #~ scope=$term_cols
  136. #~ tput hpa $(( $(rand_func $scope) % scope ))
  137. #tput setaf $(( ${colors[$(( $(rand_func ${#colors[@]})%${#colors[@]} ))]} ))
  138. printf '\e[%s;37m%s' "$((RANDOM%2))" "${chars:$((RANDOM%${#chars})):1}"
  139. fi
  140. done
  141. fi & pid=$!
  142. sleep $wait
  143. [[ "$stars" == 1 ]] && kill $pid >/dev/null 2>&1
  144. if [[ "$erase" == 1 ]] && ((erasetime>0)) && which pv >/dev/null; then
  145. tput -S <<!
  146. cup 0 0
  147. cnorm
  148. !
  149. # cursor visible (normal)
  150. #~ screenchars="$((term_lines * term_cols))"
  151. #~ screenchars="$((screenchars/10))" # 10 spaces, therefore screenchars/10
  152. #~ ((erasetime > 0)) && delay="$(bc <<<"scale=10;$erasetime/$screenchars")" || delay=0.0002
  153. #~ for (( i=0;i<screenchars;i++ )); do
  154. #~ printf ' ' # 10 spaces, therefore screenchars/10
  155. #~ sleep "$delay"
  156. #~ done
  157. screenchars="$((term_lines * term_cols))"
  158. bps_cls="$((screenchars/erasetime))"
  159. for (( i=0;i<screenchars;i++ )); do
  160. printf " "
  161. done | pv -L $bps_cls -q
  162. tput -S <<!
  163. civis
  164. cup 0 0
  165. !
  166. else
  167. clear
  168. fi
  169. done 2>/dev/null