about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-07-03 21:53:34 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-07-03 21:53:34 +0200
commita8ae7bf2e82c6ead3aaea725b971281cf2a19d6d (patch)
tree394b9a963e130b2ab42f85a5787e637724995c3a
parent77d7e8335578231351a25580bb4497f84e0bc219 (diff)
downloadlrep-a8ae7bf2e82c6ead3aaea725b971281cf2a19d6d.tar.gz
lrep-a8ae7bf2e82c6ead3aaea725b971281cf2a19d6d.tar.xz
lrep-a8ae7bf2e82c6ead3aaea725b971281cf2a19d6d.zip
add README.md HEAD master
-rw-r--r--README.md157
-rwxr-xr-xlrep6
2 files changed, 163 insertions, 0 deletions
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`:
+
+    <TAB>!!!CMD...
+
+Non-interactive session: just display output of `CMD`.
+When `CMD` ends with `>-`, no output is shown.
+
+    <TAB>!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`.
+
+    <TAB><PS1>INPUT...
+    <TAB><PS2>INPUT...
+
+Send a line to the session, and display the output.
+When `CMD` ends with `>-`, no output is shown.
+
+    <TAB>...
+
+Other lines starting with `<TAB>` 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 `<TAB>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
+`<TAB>!!!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 `<TAB>!!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 <try1.lrep
+	A simple lrep example
+		!!!echo elpmaxe na tsuj | rev
+		just an example
+
+Note that is exactly how this file was created.
+
+## Editor integration
+
+Vi:
+
+    map \e :!%./lrep<CR>``
+
+Emacs:
+
+    C-x h C-u M-| lrep <RET>
+
+## 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 <chneukirchen@gmail.com>
+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 <chneukirchen@gmail.com>
+# 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'