* README.org (Introduction): Add forward slashes to hyperlink.
* README.org: Mention website manual.
* .build.yml: Fix issue in website tarball.
This repository contains guile-blocks
, an Org Mode inspired
implementation of source blocks in Guile Scheme.
This file provides an overview of Guile Blocks. It does not attempt to detail every piece of functionality. For a more thorough review, consult the manual. The manual is hosted at https://guile-blocks.info.
This project can be built as a Guix package. To do so, run
guix build -f guix.scm
Alternatively, to build in the worktree, run
guix shell -CDf guix.scm # optional, set up dependencies ./bootstrap ./configure make make check # optional, run tests
The dependencies for this project are listed in the guix.scm
file.
This repository is available as a Guix channel. A channels.scm
file
is in the repository root.
Blocks can be created using the make-block*
function.
(define ruby-hello-world (make-block* #:code "print 42" #:language ruby))
A define-block
macro is provided as a shorthand.
(define-block ruby-hello-world #:code "print 42" #:language ruby)
Blocks are immutable. Functions which take and return a block are returning new blocks. Blocks can not be modified after they are created.
Blocks are run using the run-block
function.
(run-block ruby-hello-world)
run-block
returns a new block, identical to the previous block but
with the #:results
field set. If the #:results
field is already
set to a truthy value, the evaluator is not run and the same block is
returned.
It is possible to run a block at the same time it is created by
passing #:run? #t
to make-block*
or define-block
.
(block-result (make-block* #:code "print(10 + 9)" #:language ruby #:run? #t)) ;=> "19"
Multiple blocks can be combined into one new block using the
combine-blocks
function.
combine-blocks*
is a wrapper around combine-blocks
that
automatically inserts its arguments into a list.
(define-block ruby-set-variables #:code "x = 400" #:language ruby) (define-block ruby-print-x ;; Language may be omitted or the same. #:code "print x") (block-result (run-block (combine-blocks* ruby-set-variables ruby-print-x))) ;=> "400"
Combining blocks takes the #:code
field of each block and appends
them together. The #:separator
field of the parent is placed in
between the two blocks, by default "\n".
Combining blocks also updates the #:subblocks
field, which is
discussed later.
Blocks can be run as a pipeline. The results of the parent block is
inserted into the child's #:code
field, using the #:chain
string
as a marker for what to replace.
Pipelines are not limited to two elements.
run-blocks*
is a wrapper around run-blocks
that automatically
inserts its arguments into a list.
(define-block ruby-print-python-code #:code "puts \"print(74, end='')\"" #:language ruby) (define-block python-print #:code "%ruby%" #:chain "%ruby%" ;text to replace in #:code #:language python) (define-block ruby-add-1 #:code "print %python% + 1" #:chain "%python%" ;this can be anything #:language ruby) (block-result (run-blocks* ruby-print-python-code python-print ruby-add-1)) ;=> "75"
If the child's #:code
field is not set, the #:result
field is
inserted directly into the #:code
field.
(define-block guile-print-guile-code #:code ''(+ 1 1) ;result => '(+ 1 1) #:language guile-direct) (define-block guile-eval #:language guile-direct) (block-result (run-blocks* guile-print-guile-code guile-eval)) ;=> 2
It is possible to run a nested list of blocks directly, without
needing to call combine-blocks
first.
(run-blocks `((,a ,b) ,c ,d)) ;; is equivalent to (run-blocks `(,(combine-blocks* a b) ,c ,d))
Directly running nested blocks is only supported one level deep.
(run-blocks `((,a ,b (,c ,d)) ,d)) ;invalid (run-blocks `((,a ,b ,(combine-blocks* c d)) ,d)) ;valid
Explicit calls to combine-blocks
would be required.
When combining and pipelining blocks, a special field called
#:subblocks
is updated. This field indicates how the final block was
built.
When combining blocks, the subblocks are set as a list. For example,
(block-subblocks (combine-blocks* a b)) ;=> `(,a ,b)
Combining more blocks will append to the list.
(block-subblocks (combine-blocks* (combine-blocks* a b) c)) ;=> `(,a ,b ,c)
When running a pipeline, the subblocks of each pipeline element are inserted into a list. Elements without subblocks are inserted directly.
(block-subblocks (run-blocks* (combine-blocks* a b) c d)) ;=> `((,a ,b) ,c ,d)
A side effect of this is it is impossible to tell by looking at the
#:subblocks
field alone whether a block created by running a
pipeline or by combining blocks. A block created by running a pipeline
of blocks that were not previously combined would look identical to a
block created by combining blocks.
The elements of the #:subblocks
field are the original blocks.
When running a pipeline, the blocks are not executed directly.
Instead, the #:code
field is updated by replacing #:chain
, and
that new block is the one that executes. However, that is not
reflected in the subblocks. The subblocks #:code
field will not be
replaced.