Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 258 lines (189 sloc) 8.066 kb

WikiCreole Parser

This is a WikiCreole parser in EmacsLisp.

Rationale

We have Emacs Muse and we have OrgMode as wiki/blog makers but neither is close to the Creole syntax which is actually the syntax used on the EmacsWiki.

WikiCreole is closest to the OddMuse syntax used there. It also happens to be my favorite Wiki syntax.

The combination of this and Elnode should make a complete EmacsLisp EmacsWiki a possibility. Also a blog engine and all sorts of other simple content based things.

I even like the idea of using WikiCreole as a kind of base language for every HTML template I write, rather than HTML.

Compliance

This is early stages so it's not fully compliant with WikiCreole yet. Here is the WikiCreole test document and we don't handle some big things and all of what I'd call the exceptions:

  • not ending headings with an appropriate =
  • having whitespace before list items
  • no escapes
  • org-mode tables only

Tests

We do have a somewhat comprehensive ERT suite for the code we do have.

Extensions

We support a couple of extra extensions over Creole right now.

Syntax Coloring

We automatically fontify PRE sections with extra markup:

##! emacs-lisp
(defun creole-block-parse (text)
  "Parses TEXT as a creole block.

A creole block is a paragraph or list item that can include
links, italic, bold, line break or inline preformatted markup.

Returns a copy of TEXT with the WikiCreole replaced with
appropriate HTML."
  (replace-regexp-in-string
   "\\*\\*\\(\\(.\\|\n\\)*\\)\\*\\*"
   "<strong>\\1</strong>"
   (replace-regexp-in-string
    "//\\(\\(.\\|\n\\)*\\)//"
    "<em>\\1</em>"
    (replace-regexp-in-string
     "{{{\\(\\(.\\|\n\\)*\\)}}}"
     "<code>\\1</code>"
     (replace-regexp-in-string
      "\\\\"
      "<br/>"
      (creole-link-parse text))))))

Org-Mode tables

Instead of Creole tables, we actually use org-mode tables. Org-mode tables are very similar:

Date Amount Description
------------+--------+---------------------
2011-11-15 100.15 Expensive lunch out
2011-11-18 7.30 Dry cleaning
2011-11-21 22.50 Takeaway curry
------------+--------+---------------------
129.95
  1. +TBLFM: @5$2=vsum(@I..@II)

When a table is exported to HTML it is recalculated, so you can use formulas quite happily. Formula lines are not exported to HTML.

Lisp callouts

You can call to EmacsLisp like this:

<<(
 (mapconcat
   (lambda (s)
     (format "* %s" s))
   '("rationale" "compliance" "tests")
   "\n")
)>>

And this is what that would output:

<<( (mapconcat (lambda (s) (format "* %s" s)) '("rationale" "compliance" "tests") "\n") )>>

It's my intention to build a few Lisp functions specifically for use inside the Lisp extension element. The first of these is:

creole-directory-list directory-name &optional make-links

WikiCreole format a table of files in directory-name.

make-links causes the files to be WikiCreole links.

HTML

You can embed HTML directly into this Creole implementation, using a plugin, like this:

<<html <P>This is HTML which is just embedded <EM>directly</EM> into the output.<BR/> You obviously have to be really <u>careful</u> you don't break the output.</P> html>>

OddMuse Links

If you set the variable: creole-oddmuse-on to t you can use OddMuse links, which look like this:

[http://target text about target]

CamelCaps Links

If you let bind creole-link-resolver-fn to a function that resolves links then creole will use that resolver to also convert CamelCaps to links:

MyLink

will be passed to the resolver, the result of the resolver will be used to generate the link so that, if the resolver returns: http://myserver/MyLink the link will be:

<a href="http://myserver/MyLink">MyLink</a>

This is intended to support real Wiki engines, like the EmacsWiki engine.

Extended embed

You can use the image syntax to embed things other than images. Use an embed handler function, which are called like:

(function match-data-object scheme path)

where the match-data-object has the following sub-matches:

1 the url part 2 the query part with the leading \"?\" 3 the query part without the \"?\" 4 the description part with the leading \"|\" 5 the description part without the leading \"|\"

Two examples embed handlers are:

creole-youtube-handler and creole-include-handler. The former provides embed HTML code and the latter will include a whole other creole file as HTML.

API

The code is designed to be reused in differing circumstances, it is split into:

  • a tokenizer creole-tokenizer which produces a list of tokens representing the input document
    • Inline markup inside a paragraph is NOT converted.
  • a parser creole-structure which takes a tokenizer list and returns a parsed representation
    • note it's only creole lists that need this parsing step
    • creole-html adds the parsed structure to the creole source buffer as a local variable
  • an HTML exporter creole-html which outputs HTML from a WikiCreole source buffer
    • it always outputs to the same buffer right now, obviously changes coming here
    • it also has an interactive output option
    • it can also take a structure transformation function, see below
  • a user tool creole-wiki which can take lots of customization options

Structure Transformation

The creole-structure function produces a list based syntax tree of a creole document. The resulting structure can be transformed into something else.

The creole-html function supports a parameter :structure-transform-fn which can be a function, or a list of functions, which are passed the structure and can return a transformed version. The transformed version is then rendered to HTML.

This is intended to be used for implementing things like tables of contents (these are required by EmacsWiki).

About EmacsWiki

Here is a Wiki engine that is designed, eventually, to do the job that OddMuse does for the EmacsWiki. It will use this creole implementation via Elnode to implement the Wiki.

I hope this will produce a more hackable wiki for the Emacs community. We're a very hacky community, we like to change things, so having our wiki implemented in Elisp seems like a good step forward.

Using Creole for other doc

I like writing creole so much that I really don't want to get into writing texinfo again. Especially for writing manuals for all the Elisp I do. I wonder if creole could be converted to texinfo? In many ways texinfo is much richer, so we'd have to find ways of capturing certain semantics. For example, texinfo has the @function and @example tags whereas creole just has one syntax for which is used for code or pre-formatted sections depending on whether it's used inline or not.

I wonder if we couldn't achieve the correct conversion by doing something smart though. Creole could lookup single word code/pre markup to see if it's a declared function or variable (via some program specific lookup function, easy for EmacsLisp, maybe harder for Java).

To achieve this we could just have more hooks in the conversion.

To do

There are things that people could help with on creole. Here's a list of my next priorities:

  • make the block parsing routines more abstract
    • creole-block-parse
    • creole-image-parse
    • creole-link-parse
    • all are fixed to HTML output, they need to be abstracted to allow other transformations
Something went wrong with that request. Please try again.