157 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/sh
 | |
| 
 | |
| # Run hledger-ui in the background without needing an interactive
 | |
| # terminal, passing through any arguments, and dump its first screen*
 | |
| # as cleaned up plain text. This allows scripts to run hledger-ui and
 | |
| # capture its output.
 | |
| # * Or, all output from inputs hard-coded below.
 | |
| #
 | |
| # Here's some sample output for "test/hledgeruicapture -f examples/sample.journal"
 | |
| # showing the initial output (accounts screen) then the outputs from four inputs: 
 | |
| # RIGHT (draws register screen)
 | |
| # UP    (moves selection up one row; only the heading and old/new rows are redrawn)
 | |
| # LEFT  (draws accounts screen again)
 | |
| # 1     (redraws accounts screen with depth limit 1).
 | |
| # Note,
 | |
| # - only lines which have been redrawn are shown (and perhaps redrawing parts of lines is also possible)
 | |
| # - all inputs above cause the top line to be redrawn, which helps distinguish the outputs
 | |
| # - the top line's border chars are converted to ---
 | |
| # - empty lines and the bottom line (help & border) are omitted
 | |
| #
 | |
| # --- sample.journal account balances (1/8)
 | |
| #  assets:bank:checking    0
 | |
| #  assets:bank:saving     $1
 | |
| #  assets:cash           $-2
 | |
| #  expenses:food          $1
 | |
| #  expenses:supplies      $1
 | |
| #  income:gifts          $-1
 | |
| #  income:salary         $-1
 | |
| #  liabilities:debts      $1
 | |
| # --- assets:bank:checking transactions (4/4)
 | |
| #  2008-01-01   income                           in:salary                          $1   $1
 | |
| #  2008-06-01   gift                             in:gifts                           $1   $2
 | |
| #  2008-06-02   save                             as:ba:saving                      $-1   $1
 | |
| #  2008-12-31 * pay off                          li:debts                          $-1    0
 | |
| # --- assets:bank:checking transactions (3/4)
 | |
| #  2008-06-02   save                             as:ba:saving                      $-1   $1
 | |
| #  2008-12-31 * pay off                          li:debts                          $-1    0
 | |
| # --- sample.journal account balances (1/8)
 | |
| #  assets:bank:checking    0
 | |
| #  assets:bank:saving     $1
 | |
| #  assets:cash           $-2
 | |
| #  expenses:food          $1
 | |
| #  expenses:supplies      $1
 | |
| #  income:gifts          $-1
 | |
| #  income:salary         $-1
 | |
| #  liabilities:debts      $1
 | |
| # --- sample.journal account balances to depth 1 (1/4)
 | |
| #  assets       $-1
 | |
| #  expenses      $2
 | |
| #  income       $-2
 | |
| #  liabilities   $1
 | |
| #
 | |
| #
 | |
| # Todo:
 | |
| # - allow a sequence of inputs to be provided. Eg, first line of stdin
 | |
| #   is hledger-ui arguments, and each following line is an input.
 | |
| #
 | |
| #
 | |
| # Requirements:
 | |
| # - empty (http://empty.sourceforge.net) is used as a (complicated,
 | |
| #   delicate) way of running hledger-ui from a non-interactive script.
 | |
| #   It is included in tools/empty/ and should be installed in PATH. It
 | |
| #   seemed simpler than using expect (but maybe isn't).
 | |
| 
 | |
| # For debugging:
 | |
| # watch -n0.2 "pgrep -fl '(empty|hledger-ui)' | grep -v watch"
 | |
| # https://www.linuxjournal.com/article/2156
 | |
| 
 | |
| # Convert a stream of hledger-ui ANSI output captured by empty
 | |
| # to a plain text sequence of outputs, suitable for tests.
 | |
| # Based on https://unix.stackexchange.com/a/4529/286158, Term::ANSIColor
 | |
| # First regex: 
 | |
| # 1. convert "move to first column" escape sequences to newlines
 | |
| # 2. strip remaining escape sequences
 | |
| # 3. (replace empty's <<< delimiters with newlines - not any more, where have they gone ?)
 | |
| # 4. add a final newline
 | |
| # Second regex (because I couldn't fix newline matching in the first):
 | |
| # 1. replace screen-width dash borders with short hyphen delimiters
 | |
| # 2. strip trailing spaces on each line
 | |
| # 3. hide empty lines
 | |
| # 4. hide each screen's bottom help line
 | |
| hledgerui2txt()
 | |
| {
 | |
|     perl -pe 's/\e\[\d+;1H/\n/g; s/\e\[?.*?[\@-~]//g; s/$/\n/;' | \
 | |
|     perl -ne 's/(─)+/---/; s/(─)+//; s/ +$//; print unless /^$/ or /q:quit/'
 | |
| }
 | |
| 
 | |
| # Be sure not to leave empty and/or hledger-ui running if this script is killed.
 | |
| # (Doesn't prevent occasional "Fatal open FIFO ... No such file or directory" errors.)
 | |
| cleanup() {
 | |
|     (echo; echo "hledgeruicapture: interrupted, cleaning up") >&2
 | |
|     if [[ -e p$$ ]]; then PID=$(cat p$$); kill $PID; rm -f c$$; fi
 | |
| }
 | |
| trap cleanup INT QUIT TERM
 | |
| 
 | |
| # Start hledger-ui (and empty's monitor process) in the background,
 | |
| # specifying input/output FIFOs (with process-specific names in case
 | |
| # of concurrent testing). We don't use empty's default FIFOs because
 | |
| # finding their paths in a script is a hassle.
 | |
| empty -f -i i$$ -o o$$ -p p$$ hledger-ui "$@"
 | |
| 
 | |
| # Wait for the first screen's final line (containing "q:quit"), then
 | |
| # send 'q' causing hledger-ui to exit.
 | |
| # Doesn't work if the line has already been displayed when this runs.
 | |
| #empty -w -t 1 -i o$$ -o i$$ q:quit q
 | |
| 
 | |
| # Wait long enough to ensure the first screen has rendered
 | |
| # (assuming no crazy large data is being displayed).
 | |
| sleep 0.1
 | |
| 
 | |
| # # Testing: send some other stuff
 | |
| # U=$'\e[A'
 | |
| # D=$'\e[B'
 | |
| # R=$'\e[C'
 | |
| # L=$'\e[D'
 | |
| # empty -s -o i$$ $R; sleep 0.1
 | |
| # empty -s -o i$$ $U; sleep 0.1
 | |
| # empty -s -o i$$ $L; sleep 0.1
 | |
| # empty -s -o i$$ 1; sleep 0.1
 | |
| # empty -s -o i$$ 2; sleep 0.1
 | |
| # empty -s -o i$$ 3; sleep 0.1
 | |
| # empty -s -o i$$ 1; sleep 0.1
 | |
| 
 | |
| # capture the output FIFO's content in a file, before hledger-ui quits ?
 | |
| # hangs until ctrl-c, why ?
 | |
| #cat o$$ #> c$$
 | |
| 
 | |
| # Send 'q' on the input FIFO, causing hledger-ui to exit.
 | |
| empty -s -o i$$ q
 | |
| # But wait until after the pipe has been read, below ? Doesn't help.
 | |
| # (sleep 1; empty -s -o i$$ q) &
 | |
| 
 | |
| # drain the output FIFO one last time, allowing empty monitor to exit ? no
 | |
| #cat o$$
 | |
| 
 | |
| # kill empty's monitor process deliberately ? no
 | |
| #empty -k `cat p$$`
 | |
| 
 | |
| 
 | |
| # Read all from the output FIFO, causing empty's monitor to exit and
 | |
| # clean up the FIFOs. And convert it to plain text.
 | |
| 
 | |
| # can never get empty -r to work right
 | |
| ##empty -r -b 10000 -t 10 -i o$$ | hledgerui2txt
 | |
| 
 | |
| # cat works..
 | |
| # but only when running interactively. When non-interactive
 | |
| # (eg echo | ./uitest), the FIFO returns nothing. Could be "If all
 | |
| # file descriptors referring to the write end of a pipe have been
 | |
| # closed, then an attempt to read(2) from the pipe will see
 | |
| # end-of-file (read(2) will return 0)"
 | |
| cat o$$ | hledgerui2txt
 | |
| 
 | |
| # convert the captured output, and clean up
 | |
| # cat c$$ | hledgerui2txt
 | |
| # rm c$$
 |