Source Code Highlight Filter
============================
The AsciiDoc distribution includes a 'source' filter for highlighting
code syntax.
DocBook Outputs
---------------
AsciiDoc encloses the source code in a DocBook 'programlisting'
element and leaves source code highlighting to the DocBook toolchain
(dblatex has a particularly nice programlisting highlighter). The
DocBook programlisting element is assigned two attributes:
. The 'language' attribute is set to the AsciiDoc 'language'
attribute.
. The 'linenumbering' attribute is set to the AsciiDoc 'src_numbered'
attribute ('numbered' or 'unnumbered').
HTML Outputs
------------
You have the choice of three HTML source code highlighters, your
selection is determined by the 'source-highlighter' attribute (defaults
to 'source-highlight'):
NOTE: Set the 'source-highlighter' attribute from the asciidoc(1)
command-line or in the document header (not in the document body,
because the configuration file conditional macros are processed at
load time).
=== GNU Source Highlight
The default highlighter is the
http://www.gnu.org/software/src-highlite/[GNU source-highlight] which
can highlight 'html4', 'html5' and 'xhtml11' outputs. The GNU
source-highlight must be installed and the 'source-highlight' command
must reside in the shell search 'PATH'.
=== Highlight
You can use
http://www.andre-simon.de/doku/highlight/en/highlight.html[Highlight]
syntax highlighter for 'xhtml11', 'html5' and 'html4' outputs (set the
'source-highlighter' attribute to 'highlighter').
- The 'highlight' command must reside in the shell search 'PATH'.
- To make Highlighter your default highlighter put the following line
your `~/.asciidoc/asciidoc.conf` file:
source-highlighter=highlight
- The AsciiDoc 'encoding' attribute is passed to Highlighter using the
`--encoding` command-line option.
=== Pygments
The http://pygments.org/[Pygments] syntax highlighter can be used for
'xhtml11' and 'html5' outputs (set the 'source-highlighter' attribute
to 'pygments').
- The 'pygmentize' command must reside in the shell search 'PATH'.
- You can customize Pygments CSS styles by editing
`./stylesheets/pygments.css`. The `pygments.css` CSS file was
generated with:
from pygments.formatters import HtmlFormatter
print HtmlFormatter().get_style_defs('.highlight')
- To make Pygments your default highlighter put the following line
your `~/.asciidoc/asciidoc.conf` file:
source-highlighter=pygments
- The AsciiDoc 'encoding' attribute is passed to Pygments using the
`-O` command-line option.
Block attributes
----------------
The following attributes can be included in source code block
attribute lists.
- 'style' and 'language' are mandatory.
- 'style', 'language' and 'src_numbered' are the first three
positional attributes in that order.
- The 'args' attribute allows the inclusion of arbitrary (highlighter
dependent) command options.
//
style::
Set to 'source'.
language::
The source code language name.
+
NOTE: The language names vary between highlighters -- consult the
selected highlighter manual.
src_numbered::
Set to 'numbered' to include line numbers.
src_tab::
Set tab size (GNU source-highlight only).
args::
Include this attribute value in the highlighter command-line (HTML
outputs) or in the `programlisting` element (DocBook).
Testing
-------
Test the filter by converting the test file to HTML with AsciiDoc:
$ asciidoc -v ./filters/source/source-highlight-filter-test.txt
$ firefox ./filters/source/source-highlight-filter-test.html &
Examples
--------
Source code paragraphs
~~~~~~~~~~~~~~~~~~~~~~
The `source` paragraph style will highlight a paragraph of source
code. These three code paragraphs:
---------------------------------------------------------------------
[source,python]
if n < 0: print 'Hello World!'
:language: python
[source]
if n < 0: print 'Hello World!'
[source,ruby,numbered]
[true, false].cycle([0, 1, 2, 3, 4]) do |a, b|
puts "#{a.inspect} => #{b.inspect}"
---------------------------------------------------------------------
Render this highlighted source code:
[source,python]
if n < 0: print 'Hello World!'
:language: python
[source]
if n < 0: print 'Hello World!'
[source,ruby,numbered]
[true, false].cycle([0, 1, 2, 3, 4]) do |a, b|
puts "#{a.inspect} => #{b.inspect}"
Unnumbered source code listing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This source-highlight filtered block:
---------------------------------------------------------------------
[source,python]
---------------------------------------------------------------------
''' A multi-line
comment.'''
def sub_word(mo):
''' Single line comment.'''
word = mo.group('word') # Inline comment
if word in keywords[language]:
return quote + word + quote
else:
return word
---------------------------------------------------------------------
---------------------------------------------------------------------
Renders this highlighted source code:
[source,python]
---------------------------------------------------------------------
''' A multi-line
comment.'''
def sub_word(mo):
''' Single line comment.'''
word = mo.group('word') # Inline comment
if word in keywords[language]:
return quote + word + quote
else:
return word
---------------------------------------------------------------------
Numbered source code listing with callouts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This source-highlight filtered block:
---------------------------------------------------------------------
[source,ruby,numbered]
---------------------------------------------------------------------
#
# Useful Ruby base class extensions.
#
class Array
# Execute a block passing it corresponding items in
# +self+ and +other_array+.
# If self has less items than other_array it is repeated.
def cycle(other_array) # :yields: item, other_item
other_array.each_with_index do |item, index|
yield(self[index % self.length], item)
end
end
end
if $0 == __FILE__ # \<1>
# Array#cycle test
# true => 0
# false => 1
# true => 2
# false => 3
# true => 4
puts 'Array#cycle test' # \<2>
[true, false].cycle([0, 1, 2, 3, 4]) do |a, b|
puts "#{a.inspect} => #{b.inspect}"
end
end
---------------------------------------------------------------------
\<1> First callout.
\<2> Second callout.
---------------------------------------------------------------------
Renders this highlighted source code:
[source,ruby,numbered]
---------------------------------------------------------------------
#
# Useful Ruby base class extensions.
#
class Array
# Execute a block passing it corresponding items in
# +self+ and +other_array+.
# If self has less items than other_array it is repeated.
def cycle(other_array) # :yields: item, other_item
other_array.each_with_index do |item, index|
yield(self[index % self.length], item)
end
end
end
if $0 == __FILE__ # <1>
# Array#cycle test
# true => 0
# false => 1
# true => 2
# false => 3
# true => 4
puts 'Array#cycle test' # <2>
[true, false].cycle([0, 1, 2, 3, 4]) do |a, b|
puts "#{a.inspect} => #{b.inspect}"
end
end
---------------------------------------------------------------------
<1> First callout.
<2> Second callout.
[TIP]
=====
- If the source 'language' attribute has been set (using an
'AttributeEntry' or from the command-line) you don't have to specify
it in each source code block.
- You should place callout markers inside source code comments to
ensure they are not misinterpreted and mangled by the highlighter.
=====