about summary refs log tree commit diff
path: root/README.md
blob: 1b4c10ea629aca891fa08ae50e2138b4175a5950 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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/