From a8ae7bf2e82c6ead3aaea725b971281cf2a19d6d Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Sun, 3 Jul 2016 21:53:34 +0200 Subject: add README.md --- README.md | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lrep | 6 +++ 2 files changed, 163 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b4c10e --- /dev/null +++ b/README.md @@ -0,0 +1,157 @@ +# 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/ diff --git a/lrep b/lrep index 399d858..dafc644 100755 --- a/lrep +++ b/lrep @@ -2,6 +2,12 @@ # lrep [-z] [-t SECS] [FILES...] - literate read-eval-print # -*- ruby -*- +# +# 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/ + require 'pty' require 'io/console' require 'optparse' -- cgit 1.4.1