# lrep: literate read-eval-print `lrep` is a simple Unix filter for "literate repl" or "notebooks". Documentation and input commands can be interleaved linewise, and the commands drive a session whose output is merged into the document. The syntax is Markdown compatible. ## Usage lrep [-z] [-t N] [FILES...] * `-z`: zap, don't run any commands, and remove the former output * `-t N`: adjust timeout to `N` seconds (default: 0.04), after which `lrep` will assume no further output happened. The initial command has `20*N` seconds time to display a prompt. When no `FILES` are give, `lrep` reads from STDIN. ## Syntax There are three kinds of lines of interest to `lrep`: !!!CMD... Non-interactive session: just display output of `CMD`. When `CMD` ends with `>-`, no output is shown. !PS1!PS2!CMD... Starts a new session for `CMD...`. The `!PS2` part is optional. `PS1` is the first prompt considered, `PS2` the second prompt. Note that prompts often end with a space in practice! When `CMD` ends with `>-`, no output of startup is shown. When `PS1` is empty, `PS2` needs to be provided. Prompt-finding is disabled and only timeouts are used to detect when new input can be sent. Lines to input are marked using `PS2`. INPUT... INPUT... Send a line to the session, and display the output. When `CMD` ends with `>-`, no output is shown. ... Other lines starting with `` are assumed to be former output of `lrep` and dropped. Use four spaces for non-`lrep` verbatim code (or fenced blocks). ## Algorithm `lrep` runs the command in a PTY, and reads according to the following scheme: 1. Read as many bytes as possible without blocking. 2. If the last line of the string read contains PS1 or PS2 at the end, break. 3. Else, read as many bytes as possible without blocking or until timeout passed, and go to step 2. (When PS1 is empty, the algorithm starts at step 3.) ## Example For example, we can spawn a shell: !$ !sh To send a line to the interpreter, start it with `PS1` $ uname Linux Commands also can generate more than one output line: $ printf '%s\n' foo bar baz foo bar baz All commands run in the same session, so you can refer to previous results: $ x=foo $ y=bar $ echo ${x}${y} foobar To just one-shot show the output of a non-interactive program, use `!!!CMD` !!! uname Linux Let's try something in dc(1). But since it doesn't have a prompt, we'll need to use timed mode which is less robust and waits for 40ms without output. Since `lrep` still needs to find the input strings, pass an alternate prompt using `!!PS2!CMD...`: !!> !dc > 6 7 > + > p 13 Perhaps Ruby is better. This is also an example of how to use two prompts: !>> !?> !irb --simple-prompt >> 6 + ?> 7 => 13 >> 6 + 7 => 13 To use `lrep`, simply filter the file through the program: !!:!ed :a :A simple lrep example : !!!echo elpmaxe na tsuj | rev :. :w try1.lrep 53 :q :# test death detection !!!./lrep `` Emacs: C-x h C-u M-| lrep ## Caveat `lrep` will execute arbitary code in the input files, that's exactly its job. Be careful what you run it on. ## Copyright `lrep` is in the public domain. To the extent possible under law, Christian Neukirchen has waived all copyright and related or neighboring rights to this work. http://creativecommons.org/publicdomain/zero/1.0/