updates to the examples, better html exports now working
FossilOrigin-Name: 67b765255e8896288380bce2b3b1203b070e29b04121de31ad9b5aa6007319e4
This commit is contained in:
parent
4bf3b26d3b
commit
22a344b4e1
9 changed files with 423 additions and 144 deletions
|
@ -6,14 +6,14 @@ Cells in the next generation of the array are calculated based on the value of t
|
|||
|
||||
If, in the following table, a live cell is represented by 1 and a dead cell by 0 then to generate the value of the cell at a particular index in the array of cellular values you use the following table:
|
||||
|
||||
000 -> 0 #
|
||||
001 -> 0 #
|
||||
010 -> 0 # Dies without enough neighbours
|
||||
011 -> 1 # Needs one neighbour to survive
|
||||
100 -> 0 #
|
||||
101 -> 1 # Two neighbours giving birth
|
||||
110 -> 1 # Needs one neighbour to survive
|
||||
111 -> 0 # Starved to death.
|
||||
000 -> 0 #
|
||||
001 -> 0 #
|
||||
010 -> 0 # Dies without enough neighbours
|
||||
011 -> 1 # Needs one neighbour to survive
|
||||
100 -> 0 #
|
||||
101 -> 1 # Two neighbours giving birth
|
||||
110 -> 1 # Needs one neighbour to survive
|
||||
111 -> 0 # Starved to death.
|
||||
|
||||
I had originally written an implementation of this in RETRO 11. For RETRO 12 I took advantage of new language features and some further considerations into the rules for this task.
|
||||
|
||||
|
@ -89,16 +89,11 @@ The `record` word adds the evolved value to a buffer. In this case my `generatio
|
|||
And now to tie it all together. Meet `generation`, the longest bit of code in this sample. It has several bits:
|
||||
|
||||
- setup a new buffer pointing to `Next`
|
||||
|
||||
- this also preserves the old buffer
|
||||
|
||||
- setup a loop for each cell in `This`
|
||||
|
||||
- initial loop index at -1, to ensure proper dummy state for first cell
|
||||
- get length of `This` generation
|
||||
|
||||
- perform a loop for each item in the generation, updating `Next` as it goes
|
||||
|
||||
- copy `Next` to `This` using `update`.
|
||||
|
||||
~~~
|
||||
|
|
|
@ -13,15 +13,13 @@ functional enough to be useful to me.
|
|||
To use:
|
||||
|
||||
- replace all instances of HTTP-DOMAIN with the server URL.
|
||||
(e.g., http://server.tld:port)
|
||||
- setup inetd to run this
|
||||
- visit http://server.tld:port/gopher-url
|
||||
|
||||
e.g., for floodgap:
|
||||
E.g., for floodgap:
|
||||
|
||||
http://server.tld:port/gopher.floodgap.com/1/
|
||||
|
||||
|
||||
~~~
|
||||
{ 'Server 'Port 'Selector 'Response 'Size } [ var ] a:for-each
|
||||
|
||||
|
@ -70,12 +68,19 @@ so I can remove the need for something other than RETRO.
|
|||
[ dup file:read 0; buffer:add ] times unix:pclose
|
||||
buffer:start s:length ] buffer:preserve ;
|
||||
|
||||
:http-prefix? (-f)
|
||||
&Requested 'http:// s:begins-with? ;
|
||||
|
||||
:request (-)
|
||||
&Requested 'http:// s:begins-with? [ &Requested #7 + ] [ &Requested n:inc ] choose
|
||||
http-prefix? [ &Requested #7 + ] [ &Requested n:inc ] choose
|
||||
'gopher:// s:prepend
|
||||
&Buffer FREE net:fetch &Buffer !Response !Size ;
|
||||
~~~
|
||||
|
||||
Parsing the URL to the various internal variables is a matter
|
||||
of splitting the string, saving the pieces, and storing the
|
||||
pointers in the variables.
|
||||
|
||||
~~~
|
||||
:parse-url (s-)
|
||||
$: s:split s:keep !Server
|
||||
|
@ -100,10 +105,17 @@ so I can remove the need for something other than RETRO.
|
|||
:server @Line #2 a:fetch ;
|
||||
:selector @Line #1 a:fetch ;
|
||||
:description @Line #0 a:fetch ;
|
||||
~~~
|
||||
|
||||
The `indicate` word displays a short string of three characters
|
||||
that provide a hint to the user about the content being linked.
|
||||
|
||||
~~~
|
||||
:indicate
|
||||
$0 [ 'TXT_ s:put selector port server '<a_href="HTTP-DOMAIN/%s:%s/0%s">%s</a> s:format s:put ] case
|
||||
$1 [ 'DIR_ s:put selector port server '<a_href="HTTP-DOMAIN/%s:%s/1%s">%s</a> s:format s:put ] case
|
||||
$0 [ 'TXT_ s:put selector port server
|
||||
'<a_href="HTTP-DOMAIN/%s:%s/0%s">%s</a> s:format s:put ] case
|
||||
$1 [ 'DIR_ s:put selector port server
|
||||
'<a_href="HTTP-DOMAIN/%s:%s/1%s">%s</a> s:format s:put ] case
|
||||
$2 [ 'CSO_ s:put s:put ] case
|
||||
$3 [ 'ERR_ s:put s:put ] case
|
||||
$4 [ 'BHX_ s:put s:put ] case
|
||||
|
@ -112,17 +124,33 @@ so I can remove the need for something other than RETRO.
|
|||
$7 [ 'FND_ s:put s:put ] case
|
||||
$8 [ 'TEL_ s:put s:put ] case
|
||||
$9 [ 'BIN_ s:put s:put ] case
|
||||
$h [ 'HTM_ s:put selector #4 + '<a_href="%s">%s</a> s:format s:put ] case
|
||||
$h [ 'HTM_ s:put selector #4 +
|
||||
'<a_href="%s">%s</a> s:format s:put ] case
|
||||
$I [ 'IMG_ s:put s:put ] case
|
||||
$g [ 'GIF_ s:put s:put ] case
|
||||
$i [ '____ s:put s:put ] case
|
||||
drop 'UNK_ s:put description s:put drop ;
|
||||
~~~
|
||||
|
||||
~~~
|
||||
:tt
|
||||
'<tt_style='white-space:_pre'> s:put
|
||||
call
|
||||
'</tt><br> s:put nl ;
|
||||
|
||||
:fields (s-a)
|
||||
ASCII:HT s:tokenize dup !Line ;
|
||||
|
||||
:menu-entry
|
||||
[ @Line #0 a:fetch type indicate ] tt ;
|
||||
|
||||
:plain-text
|
||||
@Line [ '<tt> s:put s:put '</tt> s:put ] a:for-each nl ;
|
||||
|
||||
:tt '<tt_style='white-space:_pre'> s:put call '</tt><br> s:put nl ;
|
||||
:line
|
||||
dup ASCII:HT s:contains-char?
|
||||
[ ASCII:HT s:tokenize !Line @Line a:length #3 gteq? [ [ @Line #0 a:fetch type indicate ] tt ]
|
||||
[ @Line [ '<tt> s:put s:put '</tt> s:put ] a:for-each nl ] choose ] if;
|
||||
[ fields a:length #3 gteq? [ [ menu-entry ]
|
||||
[ plain-text ] choose ] if;
|
||||
[ s:putm ] tt ;
|
||||
|
||||
:css
|
||||
|
@ -131,15 +159,26 @@ so I can remove the need for something other than RETRO.
|
|||
'a_{_color:_orange;_} s:put nl
|
||||
'</style> s:put nl ;
|
||||
|
||||
:process:line
|
||||
&Buffer ASCII:CR s:tokenize
|
||||
[ s:trim line ] a:for-each ;
|
||||
|
||||
:process
|
||||
&Buffer ASCII:HT s:contains-char? [ &Buffer ASCII:CR s:tokenize [ s:trim line ] a:for-each ] if;
|
||||
&Buffer ASCII:HT s:contains-char? [ process:line ] if;
|
||||
'<xmp> s:put &Buffer s:put '</xmp> s:put ;
|
||||
|
||||
:eol ASCII:CR c:put ASCII:LF c:put ;
|
||||
:headers 'HTTP/1.1_200_OK s:put eol 'Content-Type:_text/html s:put eol eol ;
|
||||
:headers 'HTTP/1.1_200_OK s:put eol
|
||||
'Content-Type:_text/html s:put eol eol ;
|
||||
|
||||
:7080 read request headers css process ;
|
||||
|
||||
7080
|
||||
~~~
|
||||
|
||||
If you want to log the requests, this optional bit stores the
|
||||
latest request in a file.
|
||||
|
||||
```
|
||||
&Requested '/home/crc/retro/proxy.log file:spew
|
||||
```
|
||||
|
|
|
@ -2,11 +2,23 @@
|
|||
|
||||
Display the text for the *99 Bottles of Beer* song.
|
||||
|
||||
For this, I'm using `s:evaluate` to construct words which
|
||||
display a string when called. This lets the majority of the
|
||||
code read nicely.
|
||||
|
||||
~~~
|
||||
{ 'bottle 'bottles 'of 'beer 'on 'the 'wall 'no 'more
|
||||
'Take 'one 'down, 'pass 'it 'around }
|
||||
[ dup ':%s_'%s_s:put_sp_; s:format s:evaluate ] a:for-each
|
||||
~~~
|
||||
|
||||
Handling of the exact text related to the number of bottles
|
||||
is done with a simple array of functions that get selected
|
||||
based on the number of bottles left. This is done with a
|
||||
very simple filter, where the number of bottles for the
|
||||
purpose of the text is in a set of 2 or more, 1, or none.
|
||||
|
||||
~~~
|
||||
{ [ no more bottles ]
|
||||
[ #1 n:put sp bottle ]
|
||||
[ dup n:put sp bottles ]
|
||||
|
@ -14,7 +26,12 @@ Display the text for the *99 Bottles of Beer* song.
|
|||
|
||||
:number-bottles
|
||||
dup #2 n:min BOTTLES swap a:fetch call ;
|
||||
~~~
|
||||
|
||||
Thanks to the programatically generated words for the
|
||||
verse text, the main code is nicely readable.
|
||||
|
||||
~~~
|
||||
:display-verse
|
||||
number-bottles of beer on the wall nl
|
||||
number-bottles of beer nl
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
The easiest way to make an alias is by
|
||||
|
||||
:s2 s1 ;
|
||||
:s2 s1 ;
|
||||
|
||||
which adds a layer of `call`.
|
||||
`d:alias` eliminates this overhead.
|
||||
|
|
|
@ -149,22 +149,24 @@ two integers occupying two 32-bit cells.
|
|||
Two different ways are implemented:
|
||||
|
||||
- `w1` uses fixed point encoding.
|
||||
|
||||
Splits a floating point number into the integer and the fraction
|
||||
parts to store them in two cells.
|
||||
This is faster with a narrower dynamic range.
|
||||
|
||||
- `w2` uses sqrt-encoding described in doc/SqrtEncoding.pdf .
|
||||
This is slower with a relatively wider dynamic range,
|
||||
but likely not as wide as the original floating point.
|
||||
|
||||
Since Retro's cells are 32-bit,
|
||||
it is more convenient to handle floating point numbers
|
||||
encoded into single cells than into pairs of cells.
|
||||
For instance, consider using the `a:` words for vectors.
|
||||
Since Retro's cells are 32-bit, it is more convenient to handle
|
||||
floating point numbers encoded into single cells than into pairs
|
||||
of cells. For instance, consider using the `a:` words for vectors.
|
||||
Hence in many cases the words found by doing
|
||||
|
||||
'e: d:words-with
|
||||
|
||||
are suitable.
|
||||
|
||||
However, sometimes a higher precision is desired at a higher cost.
|
||||
|
||||
These are the same as `f:+encode` and `f:-encode` except that they come
|
||||
|
|
|
@ -26,7 +26,7 @@ the discrete moment at which this happens is sometimes called a tick.
|
|||
Each generation is a pure function of the preceding one. The rules
|
||||
continue to be applied repeatedly to create further generations.
|
||||
|
||||
Taken from https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
|
||||
Taken from `https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life`
|
||||
|
||||
# The Code
|
||||
|
||||
|
|
|
@ -1,139 +1,365 @@
|
|||
#!/usr/bin/env retro
|
||||
#! /usr/bin/env retro
|
||||
|
||||
# Export as HTML
|
||||
# RETRO Source to HTML
|
||||
|
||||
This tool processes the code in Unu code blocks, generating HTML
|
||||
output. It assumes that CSS will be used to style the results.
|
||||
The default CSS is included at the end of this file and will be
|
||||
embedded into the generated HTML.
|
||||
RETRO programs are written using a literate format called
|
||||
Unu which allows mixing of code and commentary in a somewhat
|
||||
literate format.
|
||||
|
||||
# Code
|
||||
Code (and optionally tests) is extracted from fenced blocks,
|
||||
and commentary normally uses a subset of Markdown.
|
||||
|
||||
I include my `unu` file processor here as it makes it easy to
|
||||
process the relevant lines from the source file.
|
||||
This tool processes both parts, generating formatted HTML
|
||||
documents that look nice, and also provides syntax highlighting
|
||||
for the test and code blocks.
|
||||
|
||||
Some characters need to be escaped. The `:put-html` words will
|
||||
be used to handle these.
|
||||
## Features
|
||||
|
||||
For Markdown:
|
||||
|
||||
- lists
|
||||
- indented code blocks
|
||||
- paragraphs
|
||||
- headers
|
||||
- fenced code and test blocks
|
||||
- horizontal rules
|
||||
- *inline* _formatting_ elements
|
||||
|
||||
For RETRO:
|
||||
|
||||
- syntax highlighting of most elements
|
||||
- uses introspection to identify primitives
|
||||
|
||||
For both:
|
||||
|
||||
- easily customizable via CSS at the end of this file
|
||||
|
||||
## Limitations
|
||||
|
||||
This only supports a limited subset of full Markdown. I am
|
||||
not adding support for the various linking formats, ordered
|
||||
lists, underlined headers, doubled asterisk, doubled
|
||||
underscores, multiple line/paragraph list entries, or images.
|
||||
|
||||
----
|
||||
|
||||
## The Code
|
||||
|
||||
### Headers and CSS Injection
|
||||
|
||||
HTML is pretty verbose and wants a bunch of boilerplate to
|
||||
work nicely, so I start with some header stuff.
|
||||
|
||||
~~~
|
||||
:c:put-html
|
||||
$< [ '< s:put ] case
|
||||
$> [ '> s:put ] case
|
||||
'<html><head> s:put nl
|
||||
~~~
|
||||
|
||||
Locate and embed the CSS from the end of this file.
|
||||
|
||||
~~~
|
||||
'<style> s:put nl
|
||||
FALSE sys:name
|
||||
[ over [ '##_CSS s:eq? or ] -if; s:put nl ] file:for-each-line
|
||||
drop
|
||||
'</style> s:put nl
|
||||
~~~
|
||||
|
||||
Finish the header boilerplate text and switch to the body.
|
||||
|
||||
~~~
|
||||
'</head><body> s:put nl
|
||||
~~~
|
||||
|
||||
### Support Code
|
||||
|
||||
The first couple of words are a variation of `s:put` that
|
||||
generates HTML codes for specific characters. This ensures
|
||||
that code output displays correctly.
|
||||
|
||||
~~~
|
||||
:c:put<code>
|
||||
$< [ '< s:put ] case
|
||||
$> [ '> s:put ] case
|
||||
$& [ '& s:put ] case
|
||||
ASCII:SPACE [ ' s:put ] case
|
||||
c:put ;
|
||||
:s:put-html [ c:put-html ] s:for-each ;
|
||||
|
||||
:s:put<code> [ c:put<code> ] s:for-each ;
|
||||
~~~
|
||||
|
||||
For regular text, there are a couple of inline formatting things
|
||||
to deal with.
|
||||
|
||||
~~~
|
||||
'Emphasis var
|
||||
'Strong var
|
||||
'Escape var
|
||||
'Code var
|
||||
|
||||
:format
|
||||
@Escape [ &Escape v:on ] if;
|
||||
$` [ @Escape [ &Escape v:off $* c:put ] if;
|
||||
@Code n:zero? [ '<tt_style='display:inline'> &Code v:on ]
|
||||
[ '</tt> &Code v:off ] choose s:put ] case
|
||||
$* [ @Escape @Code or [ &Escape v:off $* c:put ] if;
|
||||
@Strong n:zero? [ '<strong> &Strong v:on ]
|
||||
[ '</strong> &Strong v:off ] choose s:put ] case
|
||||
$_ [ @Escape @Code or [ &Escape v:off $_ c:put ] if;
|
||||
@Emphasis n:zero? [ '<em> &Emphasis v:on ]
|
||||
[ '</em> &Emphasis v:off ] choose s:put ] case
|
||||
c:put ;
|
||||
|
||||
:s:put<formatted> [ format ] s:for-each ;
|
||||
~~~
|
||||
|
||||
### Markdown Elements
|
||||
|
||||
*Code and Test Blocks*
|
||||
|
||||
The biggest element is the code and test blocks.
|
||||
|
||||
These will be generated in an enclosure that looks like:
|
||||
|
||||
<div class='codeblock'><tt>
|
||||
... code ...
|
||||
</tt></div>
|
||||
|
||||
The actual words in the code will be in `<span>` elements.
|
||||
|
||||
The fences need to start and end with `~~~` or three backticks
|
||||
on a line by itself.
|
||||
|
||||
So, identifying and generating an HTML container for a code
|
||||
block is a matter of:
|
||||
|
||||
~~~
|
||||
{{
|
||||
:span '<span_class='text'> s:put s:put-html '</span> s:put ;
|
||||
'Fenced var
|
||||
:toggle-fence @Fenced not !Fenced ;
|
||||
:fenced? (-f) @Fenced ;
|
||||
:handle-line (s-)
|
||||
fenced? [ over call ] [ span '<br> s:put nl ] choose ;
|
||||
'Block var
|
||||
---reveal---
|
||||
:unu (sq-)
|
||||
swap [ dup '~~~ s:eq?
|
||||
[ toggle-fence s:put '<br> s:put nl ]
|
||||
[ handle-line ] choose
|
||||
] file:for-each-line drop ;
|
||||
:in-code-block? (-f) @Block ;
|
||||
:code-block? (s-sf) dup '~~~ s:eq? ;
|
||||
|
||||
:begin '<div_class='codeblock'><tt>~~~</tt> ;
|
||||
:end '<tt>~~~</tt></div> ;
|
||||
:toggle-code (n-)
|
||||
drop @Block n:zero? dup &begin &end choose s:put !Block ;
|
||||
}}
|
||||
~~~
|
||||
|
||||
Formatting is pretty straightforward. I have a `span` word to
|
||||
generate the HTML for the token, and a `format` word to identify
|
||||
the token type and use `span`.
|
||||
And test blocks are basically the same, except for the
|
||||
delimiters.
|
||||
|
||||
~~~
|
||||
:span '<span_class=' s:put s:put ''> s:put s:put-html '</span>_ s:put ;
|
||||
{{
|
||||
'Block var
|
||||
---reveal---
|
||||
:in-test-block? (-f) @Block ;
|
||||
:test-block? (s-sf) dup '``` s:eq? ;
|
||||
|
||||
:format (s-)
|
||||
(ignore_empty_tokens)
|
||||
dup s:length n:zero? [ ' s:put drop ] if;
|
||||
|
||||
(tokens_with_prefixes)
|
||||
dup fetch
|
||||
$: [ 'colon span ] case
|
||||
$( [ 'note span ] case
|
||||
$' [ 'str span ] case
|
||||
$# [ 'num span ] case
|
||||
$. [ 'fnum span ] case
|
||||
$& [ 'ptr span ] case
|
||||
$$ [ 'char span ] case
|
||||
$` [ 'inst span ] case
|
||||
$\ [ 'inst span ] case
|
||||
$| [ 'defer span ] case
|
||||
$@ [ 'fetch span ] case
|
||||
$! [ 'store span ] case
|
||||
|
||||
(immediate_and_primitives)
|
||||
drop dup
|
||||
d:lookup d:class fetch
|
||||
&class:macro [ 'imm span ] case
|
||||
&class:primitive [ 'prim span ] case
|
||||
drop
|
||||
|
||||
(normal_words)
|
||||
s:put-html sp ;
|
||||
:begin '<div_class='codeblock'><tt>```</tt> ;
|
||||
:end '<tt>```</tt></div> ;
|
||||
:toggle-test (n-)
|
||||
drop @Block n:zero? dup &begin &end choose s:put !Block ;
|
||||
}}
|
||||
~~~
|
||||
|
||||
Next is the HTML page generation. This has words to generate
|
||||
the header, embeds the CSS (from the end of this file), and
|
||||
then processes the lines in the source file to generate the
|
||||
body.
|
||||
|
||||
Output is written to stdout.
|
||||
On to generating the actual HTML for the syntax highlighted
|
||||
source. This is driven by the prefix, then by word class via
|
||||
a little quick introspection.
|
||||
|
||||
~~~
|
||||
'CSS var
|
||||
:embed-css
|
||||
'<style> s:put nl
|
||||
sys:name [ dup '/*_CSS_Begins_*/ s:eq? [ &CSS v:on ] if
|
||||
@CSS [ s:put nl ] [ drop ] choose ] file:for-each-line
|
||||
'</style> s:put nl ;
|
||||
{{
|
||||
:span (s-)
|
||||
'<span_class=' s:put s:put ''> s:put s:put<code> '</span>_ s:put ;
|
||||
---reveal---
|
||||
:format-code (s-)
|
||||
(ignore_empty_tokens)
|
||||
dup s:length n:zero? [ ' s:put drop ] if;
|
||||
|
||||
(tokens_with_prefixes)
|
||||
dup fetch
|
||||
$: [ 'colon span ] case
|
||||
$( [ 'note span ] case
|
||||
$' [ 'str span ] case
|
||||
$# [ 'num span ] case
|
||||
$. [ 'fnum span ] case
|
||||
$& [ 'ptr span ] case
|
||||
$$ [ 'char span ] case
|
||||
$` [ 'inst span ] case
|
||||
$\ [ 'inst span ] case
|
||||
$| [ 'defer span ] case
|
||||
$@ [ 'fetch span ] case
|
||||
$! [ 'store span ] case
|
||||
|
||||
(immediate_and_primitives)
|
||||
drop dup
|
||||
d:lookup d:class fetch
|
||||
&class:macro [ 'imm span ] case
|
||||
&class:primitive [ 'prim span ] case
|
||||
drop
|
||||
|
||||
(normal_words)
|
||||
s:put<code> sp ;
|
||||
|
||||
:header
|
||||
'<!DOCTYPE_html> s:put nl
|
||||
'<html> s:put nl
|
||||
'<head> s:put nl embed-css '</head> s:put nl ;
|
||||
:colorize
|
||||
ASCII:SPACE s:tokenize &format-code a:for-each ;
|
||||
|
||||
:body (s-)
|
||||
'<body> s:put nl
|
||||
[ ASCII:SPACE s:tokenize [ format ] a:for-each
|
||||
'<br> s:put nl ] unu
|
||||
'</body> s:put nl ;
|
||||
|
||||
:footer
|
||||
'</html> s:put nl ;
|
||||
|
||||
:generate (s-)
|
||||
header body footer ;
|
||||
:format:code
|
||||
'<tt> s:put colorize '</tt> s:put nl ;
|
||||
}}
|
||||
~~~
|
||||
|
||||
And finally, run it.
|
||||
*Headers*
|
||||
|
||||
After this, I define detection and formatting of headers. The
|
||||
headers should look like:
|
||||
|
||||
# Level 1
|
||||
## Level 2
|
||||
### Level 3
|
||||
|
||||
~~~
|
||||
#0 sys:argv generate
|
||||
:header?
|
||||
dup [ '# s:begins-with? ]
|
||||
[ '## s:begins-with? ]
|
||||
[ '### s:begins-with? ] tri or or ;
|
||||
|
||||
:format:head
|
||||
ASCII:SPACE s:split
|
||||
'# [ '<h1> s:put n:inc s:put '</h1> s:put nl ] s:case
|
||||
'## [ '<h2> s:put n:inc s:put '</h2> s:put nl ] s:case
|
||||
'### [ '<h3> s:put n:inc s:put '</h3> s:put nl ] s:case
|
||||
drop ;
|
||||
~~~
|
||||
|
||||
# CSS
|
||||
*Indented Code Blocks*
|
||||
|
||||
/* CSS Begins */
|
||||
Indented code blocks are lines indented by four spaces.
|
||||
These are *not* syntax highlighted as they are ignored by
|
||||
Unu.
|
||||
|
||||
* { background: #1d1f21; color: #b5bd68; font-family: monospace; }
|
||||
span { white-space: pre }
|
||||
.text { color: #c5c8c6; white-space: pre }
|
||||
.colon { color: #cc6666; }
|
||||
.note { color: #969896; }
|
||||
.str { color: #f0c674; }
|
||||
.num { color: #8abeb7; }
|
||||
.fnum { color: #8abeb7; font-weight: bold; }
|
||||
.ptr { color: #b294bb; font-weight: bold; }
|
||||
.fetch { color: #b294bb; }
|
||||
.store { color: #b294bb; }
|
||||
.char { color: #81a2be; }
|
||||
.inst { color: #de935f; }
|
||||
.defer { color: #888; }
|
||||
.imm { color: #de935f; }
|
||||
.prim { color: #b5bd68; font-weight: bold; }
|
||||
~~~
|
||||
:inline-code? dup '____ s:begins-with? ;
|
||||
:format:inline-code
|
||||
'<tt_class='indentedcode'> s:put
|
||||
#4 + s:put<code>
|
||||
'</tt> s:put nl ;
|
||||
~~~
|
||||
|
||||
*Horizontal Rules*
|
||||
|
||||
Horizonal rules consist of four or more - characters on
|
||||
a line. E.g.,
|
||||
|
||||
----
|
||||
--------
|
||||
|
||||
This also accepts sequences of `-+-+` which were used in
|
||||
some older RETRO source files.
|
||||
|
||||
~~~
|
||||
:rule?
|
||||
dup [ '---- s:begins-with? ] [ '-+-+ s:begins-with? ] bi or ;
|
||||
:format:rule drop '<hr> s:put nl ;
|
||||
~~~
|
||||
|
||||
*Lists*
|
||||
|
||||
Lists start with a `-` or `*`, followed by a space, then
|
||||
the item text. Additionally, this allows for nested lists starting
|
||||
with two spaces before the list marker.
|
||||
|
||||
~~~
|
||||
:list?
|
||||
dup [ '-_ s:begins-with? ] [ '*_ s:begins-with? ] bi or ;
|
||||
:format:list '•_ s:put #2 + s:put<formatted> '<br> s:put nl ;
|
||||
|
||||
:indented-list?
|
||||
dup [ '__-_ s:begins-with? ] [ '__*_ s:begins-with? ] bi or ;
|
||||
:format:indented-list
|
||||
'<span_class='indentedlist'>• s:put
|
||||
#3 + s:put<formatted> '</span><br> s:put nl ;
|
||||
~~~
|
||||
|
||||
*Paragraphs*
|
||||
|
||||
Blank lines denote paragraph breaks.
|
||||
|
||||
~~~
|
||||
:blank? dup s:length n:zero? ;
|
||||
~~~
|
||||
|
||||
*The Formatter*
|
||||
|
||||
This ties together the various words above, generating the
|
||||
output.
|
||||
|
||||
~~~
|
||||
:format
|
||||
s:keep
|
||||
in-code-block? [ format:code ] if;
|
||||
in-test-block? [ format:code ] if;
|
||||
code-block? [ toggle-code ] if;
|
||||
test-block? [ toggle-test ] if;
|
||||
blank? [ drop '<p> s:put nl ] if;
|
||||
header? [ format:head ] if;
|
||||
inline-code? [ format:inline-code ] if;
|
||||
list? [ format:list ] if;
|
||||
indented-list? [ format:indented-list ] if;
|
||||
rule? [ format:rule ] if;
|
||||
s:put<formatted> nl ;
|
||||
|
||||
#0 sys:argv [ &Heap &format v:preserve ] file:for-each-line
|
||||
reset
|
||||
~~~
|
||||
|
||||
This concludes the Markdown (subset) in RETRO utility. All that's
|
||||
left is the CSS.
|
||||
|
||||
## CSS
|
||||
|
||||
* {
|
||||
color: #cccccc;
|
||||
background: #2d2d2d;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
tt, pre {
|
||||
background: #1d1f21; color: #b5bd68; font-family: monospace;
|
||||
white-space: pre;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.indentedcode {
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
.codeblock {
|
||||
background: #1d1f21; color: #b5bd68; font-family: monospace;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
.indentedlist {
|
||||
margin-left: 2em;
|
||||
color: #cccccc;
|
||||
background: #2d2d2d;
|
||||
}
|
||||
|
||||
span { white-space: pre; background: #1d1f21; }
|
||||
.text { color: #c5c8c6; white-space: pre }
|
||||
.colon { color: #cc6666; }
|
||||
.note { color: #969896; }
|
||||
.str { color: #f0c674; }
|
||||
.num { color: #8abeb7; }
|
||||
.fnum { color: #8abeb7; font-weight: bold; }
|
||||
.ptr { color: #b294bb; font-weight: bold; }
|
||||
.fetch { color: #b294bb; }
|
||||
.store { color: #b294bb; }
|
||||
.char { color: #81a2be; }
|
||||
.inst { color: #de935f; }
|
||||
.defer { color: #888; }
|
||||
.imm { color: #de935f; }
|
||||
.prim { color: #b5bd68; font-weight: bold; }
|
||||
|
|
|
@ -14,7 +14,7 @@ provide some access to JSON using RETRO.
|
|||
|
||||
With this, I can begin to parse JSON and do things with it.
|
||||
|
||||
Import a JSON test set (https://api.github.com/repos/stedolan/jq/commits?per_page=5)
|
||||
Import a JSON test set (`https://api.github.com/repos/stedolan/jq/commits?per_page=5`)
|
||||
|
||||
~~~
|
||||
'JSON d:create
|
||||
|
@ -29,12 +29,12 @@ JSON '.[]_|_{message:_.commit.message}_|_flatten jq s:temp
|
|||
|
||||
This leaves output like:
|
||||
|
||||
[
|
||||
"Improve jv_is_integer()"
|
||||
]
|
||||
[
|
||||
"Dockerfile: Change base image to Debian Stable"
|
||||
]
|
||||
[
|
||||
"Improve jv_is_integer()"
|
||||
]
|
||||
[
|
||||
"Dockerfile: Change base image to Debian Stable"
|
||||
]
|
||||
|
||||
I can tokenize this and filter out the [ ] pairs:
|
||||
|
||||
|
|
|
@ -88,6 +88,6 @@ FILE-PATH 'gophermap s:append file:W file:open !FID
|
|||
:glossary source? &drop -if;
|
||||
FILE-PATH over
|
||||
'retro-document_%s_>%s%s.glossary s:format unix:system $. c:put ;
|
||||
~~~
|
||||
|
||||
[ dir? &drop &glossary choose ] unix:for-each-file nl
|
||||
~~~
|
||||
|
|
Loading…
Reference in a new issue