There is a bunch of tools like 'script', 'screen', 'ttyrec' which allow record content of shell sessions. By design these tool records everything displayed on pty, including control characters. However, there appears to be no solution to remove the control characters and display the transcript of the recorded session at it was seen by the user. Even replay programs don't seem to work correctly with multi-line commands.
I've spend some time trying to make proper parser for the typescripts, and came to the conclusion it is in fact impossible in general case. The problem is modern terminal emulators (terminator, xterm, rxvt) feature automatic line wrapping and shells (bash, zsh) make use of it. Things work out well for the interactive shell process because it is capable to keep itself in sync with the width of the terminal and adjust cursor positions as needed. Unfortunately 'script' (nor other tools as far as I can see) does not keep track of pty size change events, and this information simply gets lost. As a result a tool rendering the typescript has not enough information and cannot reconstruct appearance of multi-line commands.
Have I missed something? Is there a solution?
I see the following possible solutions, but none of them is easy nor complete:
- Use shell having no sophisticated command line editor (like bourne shell)
- Always run with 'set -x' on (generates a lot of mess with command auto-completion in bash)
- Patch 'script' (and 'screen') tool to record pty size changes (on Linux it can feed timing info to stderr already, would be logical to add pty size change events there)
- Come up with some cunning algorithm to parse messed up typescript. For example, shell sends CR when it needs to go to another line during multi-line command editing. It sends CR+NL when the user submits the command. Unfortunately bash also sends CR when handling some Ctrl-U commands from the user.
- Obtain the text of the command (which is being messed up in typescript) from another source, for example from shell history. But this would require customisation of shell profile scripts, etc.
In the general case, you need to replay in a terminal of the same size.
You can decide to ignore it altogether. As mentioned by sendmoreinfo, you could declare a TERM that doesn't support any of these features. Don't expect
vim
orreadline
to behave in the nice ways you got used to, though.You could store it along with your transcript and recreate the correct size when replaying (eg
xterm -geometry [...] -e [...]
), but resizing will break everything.If you care a lot about this and want the perfect solution, you could implement it yourself!
You could have your
ttyrec
record the terminal size and its changes by handling theSIGWINCH
signal and usingioctl(STDIN_FILENO, TIOCGWINSZ, [...])
.Your
ttyplay
would have to take care of emulating a terminal itself, and representing it within a terminal. That's tricky, but luckily there are a few projects already doing that, so you could reuse a well-established codebase.tmux
comes to mind, for example.