Advertisement
moreaki

watch.sh

Nov 29th, 2022
981
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 4.99 KB | Source Code | 0 0
  1. #!/usr/bin/env bash
  2.  
  3. # watch a file or command output and scroll within
  4. #
  5. # keys => arrow-up/down, page-up/down, pos1, end
  6. #
  7. # usages:
  8. #           swatch.sh -n <timeout_watch> <file|command>
  9. #           swatch.sh <file|command>
  10. #
  11. # version:          1.2 (macOS compatible)
  12. # dependencies:     awk, tput, clear, read
  13. # published:        https://unix.stackexchange.com/questions/3842/how-can-i-scroll-within-the-output-of-my-watch-command
  14.  
  15. # =============================================
  16. # DEFAULTS
  17. # =============================================
  18. TMPFILE=$(mktemp)
  19. line_show_begin="1"
  20. line_show_begin_last="-1"
  21. console_lines_correction="4"
  22. timeout_watch="2"
  23. timeout_read=".1"
  24. # http://ascii-table.com/ansi-escape-sequences-vt-100.php
  25. ESC_cursor_home='\033[H'
  26.  
  27. define(){ IFS=$'\n' read -r -d '' "${1}" || true; }
  28. define helptext <<-EOF
  29.   Usage: ${0##*/} [-n <timeout>] '[<command>]'
  30.  
  31.          timout : in seconds or fractions of seconds [default: ${timeout_watch}s]
  32.          command: any command wished to be observed - best applied in quotes
  33. EOF
  34.  
  35. __init() {
  36.   trap "fn_console_size_change" SIGWINCH
  37.   trap "fn_quit" INT HUP TERM QUIT EXIT
  38.   fn_console_size_change
  39.   tput civis
  40. }
  41.  
  42. fn_help() {
  43.   printf "%s\n" "${helptext}"
  44.  
  45. }
  46.  
  47. get_options() {
  48.     [[ "$1" == "" ]] && fn_help 1
  49.     while [ -n "$1" ]; do
  50.         case "$1" in
  51.             -h|--help)
  52.                 fn_help 0
  53.             ;;
  54.             -n)
  55.                 [[ "$2" == "" ]] && { echo "Error: option -n required <timeout>" ; exit 1 ; }
  56.                 timeout_watch="$2" && shift
  57.             ;;
  58.             -*) echo "Error: unknown option ยป$1ยซ"; exit 1; ;;
  59.             *)  command=$1;;
  60.         esac
  61.         shift
  62.     done
  63.     [[ "$command" == "" ]] && { echo "Error: command required" ; exit 1 ; }
  64. }
  65.  
  66. fn_print_headline() {
  67.     hdl_txt_right="${HOSTNAME}: $(date "+%Y-%m-%d %H:%M:%S")"
  68.     hdl_txt_left="$command, [${timeout_watch}s, $line_show_begin]"
  69.     hdl_txt_left_length=${#hdl_txt_left}
  70.     printf '%s%*s\n\n' "$hdl_txt_left" "$((console_columns - hdl_txt_left_length))" "$hdl_txt_right"
  71. }
  72.  
  73. fn_print_file() {
  74.     # file length can change during watch execution
  75.     eval "$command" > "$TMPFILE"
  76.     lines_command=$(awk 'END {print NR}' "$TMPFILE")
  77.     line_last=$((lines_command-console_lines))
  78.     (( "$line_last" < "1" )) && { line_last=1; clear; }
  79.     (( "$line_show_begin" > "$line_last" )) && { line_show_begin=$line_last; clear; }
  80.  
  81.     # print position changed
  82.     if (( "$line_show_begin" != "$line_show_begin_last" )); then
  83.         line_show_begin_last=$line_show_begin
  84.         clear
  85.     else
  86.         printf "$ESC_cursor_home"
  87.     fi
  88.  
  89.     # print file section
  90.     fn_print_headline
  91.     eval "$command" > "$TMPFILE"
  92.     awk -v var1="$line_show_begin" -v var2="$console_lines" 'NR>=var1 {if (NR>var1+var2) {exit 0} else {printf "%s\n",$0 } }' "$TMPFILE"
  93. }
  94.  
  95. fn_console_size_change() {
  96.   console_columns=$(tput cols)
  97.   console_lines=$(($(tput lines) - console_lines_correction))
  98.   line_show_begin_last=-1
  99. }
  100.  
  101. fn_quit() {
  102.   tput cnorm
  103.   tput clear
  104.   exit 0
  105. }
  106.  
  107. # =============================================
  108. # MAIN
  109. # =============================================
  110. get_options "$@"
  111. __init
  112.  
  113. while :; do
  114.     fn_print_file
  115.     read -rsn1 -t "$timeout_watch" k # char 1
  116.     case "$k" in
  117.         [[:graph:]]) # Normal input handling
  118.         ;;
  119.         $'\x09') # Routine for selecting current item
  120.         ;;
  121.         $'\x7f') # Routine for back-space
  122.         ;;
  123.         $'\x01') # Routine for ctrl+a
  124.         ;;
  125.         $'\x1b') # ESC
  126.             read -rsn1 k # char 2
  127.             [[ "$k" == ""  ]] && return # Esc-Key
  128.             [[ "$k" == "[" ]] && read -rsn1 -t $timeout_read k # char 3
  129.             [[ "$k" == "O" ]] && read -rsn1 -t $timeout_read k # char 3
  130.             case "$k" in
  131.                 A)  (( "$line_show_begin" > "1" )) && ((line_show_begin--)) ;; # Arrow-Up-Key
  132.                 B)  (( "$line_show_begin" < "$line_last" )) && ((line_show_begin++)) ;; # Arrow-Down-Key
  133.                 H)  line_show_begin=1 ;; # Pos1-Key
  134.                 F)  line_show_begin=$line_last ;; # End-Key
  135.                 5)  # PgUp-Key
  136.                     read -rsn1 -t $timeout_read k # char 4
  137.                     if [[ "$k" == "~" ]] && (( "$line_show_begin" > "$((console_lines/2))" )) ; then
  138.                         line_show_begin=$((line_show_begin-console_lines/2))
  139.                     else
  140.                         line_show_begin=1
  141.                     fi
  142.                 ;;
  143.                 6)  # PgDown-Key
  144.                     read -rsn1 -t $timeout_read k # char 4
  145.                     if [[ "$k" == "~" ]] && (( "$line_show_begin" < "$((line_last-console_lines/2))" )) ; then
  146.                         line_show_begin=$((line_show_begin+console_lines/2))
  147.                     else
  148.                         line_show_begin=$line_last
  149.                     fi
  150.                 ;;
  151.             esac
  152.             read -rsn4 -t $timeout_read    # Try to flush out other sequences ...
  153.         ;;
  154.     esac
  155. done
  156.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement