diff options
-rwxr-xr-x | twopane.bash | 92 |
1 files changed, 72 insertions, 20 deletions
diff --git a/twopane.bash b/twopane.bash index 8417022..2aacab2 100755 --- a/twopane.bash +++ b/twopane.bash | |||
@@ -7,9 +7,14 @@ PROGNAME=${0##*/} | |||
7 | 7 | ||
8 | BOT_SIZE=8 | 8 | BOT_SIZE=8 |
9 | BOT_TITLE=input | 9 | BOT_TITLE=input |
10 | BOT_CMD=start | 10 | BOT_CMD=sendstream |
11 | TOP_CMD='PS1="$TOP_TITLE\$ " bash --noprofile --norc -i' | 11 | if [ $# = 0 ] |
12 | TOP_TITLE=output | 12 | then |
13 | TOP_CMD="$SHELL -i" | ||
14 | else | ||
15 | TOP_CMD=$* | ||
16 | fi | ||
17 | TOP_TITLE=$TOP_CMD | ||
13 | 18 | ||
14 | TWOPANE=$(mktemp -d) | 19 | TWOPANE=$(mktemp -d) |
15 | export TWOPANE TOP_CMD BOT_CMD TOP_TITLE BOT_TITLE BOT_SIZE | 20 | export TWOPANE TOP_CMD BOT_CMD TOP_TITLE BOT_TITLE BOT_SIZE |
@@ -26,8 +31,13 @@ save_screenrc() | |||
26 | } | 31 | } |
27 | 32 | ||
28 | save_screenrc <<'.' | 33 | save_screenrc <<'.' |
34 | # Disable keybindings. | ||
29 | unbindall | 35 | unbindall |
30 | escape \0\0 | 36 | escape \0\0 |
37 | # Disable messages. This is needed for screen -X/-Q to work reasonably. | ||
38 | msgwait 0 | ||
39 | msgminwait 0 | ||
40 | |||
31 | caption string '%t' | 41 | caption string '%t' |
32 | layout new | 42 | layout new |
33 | split | 43 | split |
@@ -38,34 +48,35 @@ screen -ln -t "$BOT_TITLE" 0 bash --noprofile --rcfile "$TWOPANE"/bashrc -i | |||
38 | source "$TWOPANE"/screenrc.startpane | 48 | source "$TWOPANE"/screenrc.startpane |
39 | . | 49 | . |
40 | 50 | ||
41 | save_screenrc 'startpane' <<'.' | 51 | save_screenrc 'startpane' <<. |
42 | focus top | 52 | focus top |
43 | screen -ln -t "$TOP_TITLE" 1 sh -c "$TOP_CMD" | 53 | screen -ln -t "\$TOP_TITLE" 1 $TOP_CMD |
44 | exec .!. socat -u UNIX-RECV:"$TWOPANE"/socket STDOUT | 54 | exec .!. sh -c 'socat -u UNIX-RECV:"\$TWOPANE"/socket STDOUT & socat -u STDIN,rawer UNIX-SEND:"\$TWOPANE"/socket' |
45 | title 'output' | 55 | title 'output' |
46 | focus bottom | 56 | focus bottom |
47 | layout save 0 | 57 | layout save 0 |
48 | . | 58 | . |
49 | 59 | ||
50 | save_screenrc 'restart' <<. | 60 | save_screenrc 'restart' <<. |
51 | layout new | 61 | focus top |
52 | split | 62 | screen -ln -t "\$TOP_TITLE" 1 $TOP_CMD |
63 | exec .!. sh -c 'socat -u UNIX-RECV:"\$TWOPANE"/socket STDOUT & socat -u STDIN,rawer UNIX-SEND:"\$TWOPANE"/socket' | ||
64 | title 'output' | ||
53 | focus bottom | 65 | focus bottom |
54 | resize $BOT_SIZE | ||
55 | select 0 | ||
56 | title 'input' | ||
57 | |||
58 | source "$TWOPANE"/screenrc.startpane | ||
59 | . | 66 | . |
60 | 67 | ||
61 | restart() | 68 | restart() |
62 | { | 69 | { |
70 | while screen -p1 -Q info | ||
71 | do | ||
72 | screen -p1 -X kill | ||
73 | done | ||
63 | screen -X source "$TWOPANE"/screenrc.restart | 74 | screen -X source "$TWOPANE"/screenrc.restart |
64 | } | 75 | } |
65 | sendp() | 76 | sendp() |
66 | { | 77 | { |
67 | trap "kill -SIGUSR1 $1" EXIT | 78 | trap "kill -SIGUSR1 ${1:-$$}" EXIT |
68 | socat -u STDIN UNIX-SENDTO:"$TWOPANE"/socket || restart | 79 | socat -u STDIN UNIX-SENDTO:"$TWOPANE"/socket 2>&20 || restart |
69 | } | 80 | } |
70 | sendc() | 81 | sendc() |
71 | { | 82 | { |
@@ -98,14 +109,47 @@ raw() | |||
98 | stty "${stty_opts[@]}" | 109 | stty "${stty_opts[@]}" |
99 | } | 110 | } |
100 | 111 | ||
112 | :() | ||
113 | { | ||
114 | if [ "$#" -gt 0 ] | ||
115 | then | ||
116 | printf '%s: %s\r\n' "$0" "$*" >&2 | ||
117 | fi | ||
118 | } | ||
119 | |||
101 | start() | 120 | start() |
102 | { | 121 | { |
103 | trap ': SIGPIPE ${SOCAT[@]@A}' SIGPIPE | 122 | socat_stty_opts=( |
104 | trap ': SIGCHLD ${SOCAT[@]@A}' SIGCHLD | 123 | echo=1 |
105 | trap ': SIGUSR1 ${SOCAT[@]@A}; SOCAT=()' SIGUSR1 | 124 | echoctl=1 |
125 | intr=0 | ||
126 | quit=0 | ||
127 | eof=0 | ||
128 | start=0 | ||
129 | stop=0 | ||
130 | susp=0 | ||
131 | lnext=0 | ||
132 | ) | ||
133 | stty=$(printf %s, "${socat_stty_opts[@]}") | ||
134 | while ! socat -u \ | ||
135 | STDIN,rawer,"${stty}" \ | ||
136 | UNIX-SENDTO:"$TWOPANE"/socket | ||
137 | do | ||
138 | restart | ||
139 | done | ||
140 | } | ||
141 | |||
142 | sendstream() | ||
143 | { | ||
144 | #trap ': SIGPIPE ;' SIGPIPE | ||
145 | #trap ': SIGCHLD ;' SIGCHLD | ||
146 | trap '' SIGPIPE SIGCHLD | ||
147 | trap 'SOCAT=(); RETRY=$REPLY;' SIGUSR1 | ||
106 | raw | 148 | raw |
107 | while read -r -N1 || [ $? -gt 128 ] | 149 | while [ "$RETRY" ] || read -t 0.1 -r -N1 || [ $? -gt 128 ] |
108 | do | 150 | do |
151 | REPLY=$RETRY$REPLY | ||
152 | RETRY= | ||
109 | if [ "$REPLY" ] | 153 | if [ "$REPLY" ] |
110 | then | 154 | then |
111 | sendc "$REPLY" | 155 | sendc "$REPLY" |
@@ -120,7 +164,15 @@ set -o pipefail | |||
120 | shopt -s lastpipe | 164 | shopt -s lastpipe |
121 | trap "screen -X quit" EXIT | 165 | trap "screen -X quit" EXIT |
122 | $(declare -f) | 166 | $(declare -f) |
123 | export PS1="$BOT_TITLE\$ " | 167 | export PS1="\$BOT_TITLE\$ " |
168 | |||
169 | if [ "\$SHOW_SOCAT_ERRORS" ] | ||
170 | then | ||
171 | exec 20>&2 | ||
172 | else | ||
173 | exec 20>/dev/null | ||
174 | fi | ||
175 | |||
124 | \$BOT_CMD | 176 | \$BOT_CMD |
125 | . | 177 | . |
126 | 178 | ||