work in progress in progress.
made to work with org-mode files
after cloning this repo
git submodule init # pulls ext--json-rpc-request
git submodule update
set up and run the transclusion server somewhere
start emacs and load xcl-transclude.el
open this file, M-x xcl-transclude-mode
, cursor over a transclusion
directive, and C-c E
(functions and key chords are subject to change)
assuming you have the nix package manager, clone this repository and
run nix-shell
.
from the nix-shell
, running emacs
should give you a
development-ready emacs instance
the transclusion engine is a nodejs webserver; see transclusion server for install + setup; launch it from another terminal
node build/webserver.js
with org macros this seems to be a better option.
see https://github.com/fniessen/org-macros/blob/master/org-macros.setup
To test this, run the org-mode export process (e.g. C-c C-e
then
h H
or t A
), then find the text from LICENSE
exported as well.
TODO: figure out how to make this org-compatible. Right now it is
trivially easy to cause export-time conflicts due to eval
using org’s native macro facility in normal org export
partial transclusion
{{{transclude(LICENSE::60,500)}}}
the whole thing
{{{transclude(LICENSE)}}}
primary consideration is edit-time user friendliness;
for accuracy, fuzzy text anchors should be used
non-resolution should lead to an empty resource, i.e. an empty string at render time
There is 1 goal of the transclusion target notation: to establish a range. However, conventional address methods do not distinguish between point and range resources. For transclusion, we need to ensure that we operate, code-wise, in range space. Hence, when given a point resource, we must convert it into a range resource.
In addition to the straightforward range methods covered in sections below, some examples of org internal links:
- textual link (see documentation) like
[[My Target]]
can resolve, in this order, to:- a text label
<<My Target>>
aka dedicated target. This defines a point resource. - an element,
#+NAME: My Target
. This needs to be interpreted as the range encompassing that element. - a headline,
* My Target
. This is the range encompassing the section.
- a text label
CUSTOM_ID
a la[[#my-custom-id]]
, resolves exactly to an entry withCUSTOM_ID: my-custom-id
. This needs to be interpreted as the range encompassing the section bearing that id.
the textual link method logic may involve back-tracking, so it may be sensible to simply disallow providing a single textual link for transclusion.
{{{transclude(file:tiny.org)}}}
{{{transclude(file:tiny.org::5)}}}
{{{transclude(file:tiny.org::2-3)}}}
{{{transclude(file:tiny.org::-2)}}}
{{{transclude(file:tiny.org::7-)}}}
{{{transclude(file:tiny.org::0,100)}}}
{{{transclude(file:tiny.org::,100)}}}
{{{transclude(file:tiny.org::50,)}}}
convert to line first
{{{transclude(file:moozorgjs.org::1%-3%)}}}
{{{transclude(file:tiny.org::*decoy 1)}}}
{{{transclude(file:tiny.org::in 2101…for great justice)}}}
these should all resolve to
{{{transclude(file:t*ny.org::*huh)}}}
{{{transclude(grep:gg+you::*huh)}}}
{{{transclude(grep:gg you::*huh)}}}
{{{transclude(grep:gg%20you::*huh)}}}
a better term than constriction / constrictor probably exists
the $constrictor
should fallback to resolution logic of the
colon-based content address when no constriction method is found
address like:
- file:$RESOLVER#$constrictor
- https://$RESOLVER#constrictor
http://example.com/#dummy target#ignore again#This domain...
where $constrictor …
not yet a user friendly way to create anchors in edit phase
$RESOLVER#handling todo
resolve to Handling TODO
via first + best sequential match
$RESOLVER#in 2101…for great justice
- [X] js poc
- [ ] emacs poc
possibly just L
$RESOLVER#line/support+scheduled
resolve to the line,
“Support attributes like SCHEDULED:
.”
- [X] js poc
- [ ] emacs poc
possibly just P
$RESOLVER#para/org.js parser converter
intro paragraph
- [X] js poc
- [ ] emacs poc
need org context
$RESOLVER#section/web browser
Web Browser
hardest – need broader semantic analysis
$RESOLVER#unit/require org
require(“org”)
the src block with “require” within
this only makes sense in read-only transclusion
the pipe is an obvious choice of “filter” designation, but since it
conflicts with org-mode table syntax, the post-processor parsing
should also recognize unicode BROKEN BAR
¦
as an alternative
- file:$RESOLVER#$constrictor|post-processor
- file:$RESOLVER#$constrictor¦post-processor
this currently makes sense for something transcluded into an org doc where only the text is wanted, but the transclusion target’s (host document) location has significant whitespace, such as in an org table. Linebreaks in the source document cause the table to break.
when the transclusion target is defined by an org headline section, one may want to keep the text only. The address may look like
file:somefile.org::*infamous muse of famous mouse¦no-headline
text in the real
text in the fake
(org picks the first occurrence)
- transcluding-org-elements.org? # opens dired
- transcluding-org-elements.org?s=1 # opens dired
this relies on running the webserver from xcl/src/xcl/node_webserver.cljs
see xcl/README.org for details
{{{transclude(LICENSE::2,10)}}}
{{{transclude(file:transcluding-org-elements.org)}}}
{{{transclude(file:./transcluding-org-elements.org::2-10)}}}
{{{transclude(file:./transcluding-org-elements.org::20)}}}
{{{transclude(xcl:./public/tracemonkey.pdf?p=3&s=Monkey observes that…so TraceMonkey attempts)}}}
{{{transclude(calibre:quick start?s=The real advantage…on your computer.)}}}
{{{transclude(zotero:just-in-time?s=Monkey observes…TraceMonkey attempts)}}}
{{{transclude(xcl:./public/alice.epub?p=2&s=Would you tell me, please…walk long enough)}}}
{{{transclude(zotero:faulty reward functions?s=We assumed…measure the performance)}}}
http://stackoverflow.com/questions/15328515/iso-transclusion-in-emacs-org-mode
http://stackoverflow.com/a/15352203
(defun org-dblock-write:transclusion (params)
(progn
(with-temp-buffer
(insert-file-contents (plist-get params :filename))
(let ((range-start (or (plist-get params :min) (line-number-at-pos (point-min))))
(range-end (or (plist-get params :max) (line-number-at-pos (point-max)))))
(copy-region-as-kill (line-beginning-position range-start)
(line-end-position range-end))))
(yank)))
Then to include a line range from a given file, you can create a dynamic block like so:
C-c C-x C-u
(org-dblock-update
) will on the BEGIN/END
block
updates that block; org-update-all-dblocks
does all in the
buffer.
This is an unsatisfactory solution because it is actually just
unidirectional quasi-dynamic inclusion; quasi, because the
update step has no knowledge of the target until the update is
invoked. It is possible to add action hooks to run updates
automatically, but that is no different from export-time inclusion,
which by nature assumes a unidirectional flow of information. Org
already has a number of ways to achieve this, such as a sh
src
block that runs cat
.
Transclusion is different in practice: it is the actual content, appearing at the location of transclusion.