# How to add a new target to txt2tags

### It's easy!

## Yes, YOU can make it

So you like txt2tags very much but your favorite format is not yet supported? How about adding it yourself?

You don't need to be a Python programmer to do it. You'll just define variables, no algorithm is needed. In fact, if text editors and the command line don't scare you, you don't even need to be a programmer to do it. Just read this document carefully :)

On the following guidelines we'll add the imaginary "foo" target to txt2tags.

# 1. Get the most recent txt2tags source code

IMPORTANT!

Before you start, make sure you have the newest txt2tags code, available at http://txt2tags.googlecode.com/svn/trunk/txt2tags

Open this file on your favorite text editor.

# 2. Add the target identifier and description in TARGET_NAMES

At the beginning of the txt2tags source code, right after the long heading comments, you'll find the declaration of all the available targets:

    TARGET_NAMES = {
      'html' : _('HTML page'),
      'xhtml': _('XHTML page'),
      'sgml' : _('SGML document'),
      'tex'  : _('LaTeX document'),
      'lout' : _('Lout document'),
      'man'  : _('UNIX Manual page'),
      'mgp'  : _('MagicPoint presentation'),
      'wiki' : _('Wikipedia page'),
      'gwiki': _('Google Wiki page'),
      'doku' : _('DokuWiki page'),
      'moin' : _('MoinMoin page'),
      'pm6'  : _('PageMaker document'),
      'txt'  : _('Plain Text'),
      'foo'  : _('FOO Document'),
    }

Add a new item to the dictionary, choosing an identifier and a textual description for your new target.

Notes:

- Copy & paste instead writing from zero to make sure you won't forgot the _(...) format.
- Choose a short name for the identifier (5 letters or less).
- The identifier will also be the filename extension used by txt2tags when saving the result to a file.

You can already run `./txt2tags --targets` and see your new target listed!

# 3. Add the header template in HEADER_TEMPLATE

The headers are the first three lines of a txt2tags document. Some targets as LaTeX have a specific place for them (the Preamble), others don't. Make a decision on how to format the header lines. You have three tokens available:

- %(HEADER1)s - The first source line (Document title)
- %(HEADER2)s - The second source line (Document author)
- %(HEADER3)s - The third source line (Document date)

The title/author/date contents are just suggestions. The user can put whatever he/she wants at those lines. And remember that while the first line (title) is required, the other two are optional. Their lines at this template will be removed if not present.

      'foo': """\
    <title-tag>%(HEADER1)s</title-tag>

    <author-tag>%(HEADER2)s</author-tag>

    <date-tag>%(HEADER3)s<date-tag>
    """,

> Tip: Once again, copy & paste instead writing from zero.

> Tip: To show a literal "%" use "%%".

# 4. Add the target's tags in getTags()

This is the most tricky step. Some targets are easy, some are more exotic.

First, find the definition of the getTags() function.

    def getTags(config):

The keys variable stores all the valid tokens you can use to describe your target's tags.

The alltags dictionary stores the tags for each target. This is where you'll add your new target.

    'foo': {
       'title1'              : '<title-tag-1>\a</title-tag-1>' ,
       'title2'              : '<title-tag-2>\a</title-tag-2>' ,
       'title3'              : '<title-tag-3>\a</title-tag-3>' ,
       ...
    },

IMPORTANT: The easiest is to find an already added target that is similar to yours, copy & paste the code and modify it. Don't start from zero.

Note the `\a` on the tags. It represents the text the user typed inside that mark. So `=My Title=` will be converted to `<title-tag-1>My Title</title-tag-1>`.

You can also put a `\n` character to represent a line break. It's useful if your tag spans in multiple lines. A Tab can be inserted using `\t`.

At this point you can already run a `txt2tags -t foo sample.t2t` command and it will work! The results will be saved to sample.foo. Check it out.

> Tip: Keep editing and running to adjust and improve your target support.

# 5. Add the target's rules in getRules()

This is the final step. Besides the tags already added, now you can also specify some rules to fine-tune your target code.

Search for the function definition:

    def getRules(config):

Then read carefully the allrules comments to learn which options are available.

Once again, copy & paste the entry of an already added target to make your life easier. Put there all the rules you need, always using 1 as the value. You don't need to turn off a rule with zero. Just don't mention it and it will be disabled by default. In other words, just add the rules you want to be ON.

    'foo' : {
      'indentverbblock':1,
      'spacedlistitem':1,
      'parainsidelist':1,
      'keeplistindent':1,
      'barinsidequote':1,
      'autotocwithbars':1,
      'blankendmotherlist':1,
      },

And that's it! Now your target is fully added to the txt2tags program!

Tips:

- If in your target the `urlMark` order is reversed (label comes before the link) use the following rule: `'labelbeforelink':1`. See how this change was made in r450.

- If in your target the nested lists are defined by the number of `*`, for example `**` for sublists and `***` for subsublists, use `listItemLine` instead `listItemOpen`, remove the `keeplistindent` setting and turn on `spacedlistitemopen`. See how this change was made in r181. Example:

      # getTags
      'listItemOpen': '* ',                     * mother list
                                      ====>       * sub list
      # getRules                                    * sub sub list
      'keeplistindent':1,

      --------------------------------------------------------------

      # getTags
      'listItemLine': '*',                      * mother list
                                      ====>     ** sub list
      # getRules                                *** sub sub list
      'spacedlistitemopen':1,

# 6. Send me your work!

Once you're done, send me your work so I can include it on the official txt2tags source and everybody can use your target. You will also be included on the Team page and your karma will increase in 2,715 points :)

The only file you must e-mail me is the full txt2tags code modified with your target.

Have a good programming time!

# A real-world example

See how easy it was to add the DokuWiki target to txt2tags. This file is in the diff format, where red lines are OLD and green lines are NEW:

    --- txt2tags	2007-11-08 15:10:58.000000000 -0200
    +++ txt2tags-doku	2007-11-11 23:09:11.000000000 -0200
    @@ -175,6 +175,7 @@
       'mgp'  : _('MagicPoint presentation'),
       'wiki' : _('Wikipedia page'),
       'gwiki': _('Google Wiki page'),
    +  'doku' : _('DokuWiki page'),
       'moin' : _('MoinMoin page'),
       'pm6'  : _('PageMaker document'),
       'txt'  : _('Plain Text'),
    @@ -438,6 +439,14 @@

     """,

    +  'doku': """\
    +===== %(HEADER1)s =====
    +
    +**//%(HEADER2)s//**
    +
    +//%(HEADER3)s//
    +""",
    +
       'wiki': """\
     '''%(HEADER1)s'''

    @@ -895,6 +905,52 @@
     	   'tableCellSep'        : ' || '          ,
     	},

    +	# http://wiki.splitbrain.org/wiki:syntax
    +	# Hint: <br> is \\ $
    +	# Hint: You can add footnotes ((This is a footnote))
    +	'doku': {
    +	   'title1'              : '===== \a =====',
    +	   'title2'              : '==== \a ===='  ,
    +	   'title3'              : '=== \a ==='    ,
    +	   'title4'              : '== \a =='      ,
    +	   'title5'              : '= \a ='        ,
    +	   # DokuWiki uses '  ' identation to mark verb blocks (see indentverbblock)
    +	   'blockQuoteLine'      : '>'             ,
    +	   'fontMonoOpen'        : "''"            ,
    +	   'fontMonoClose'       : "''"            ,
    +	   'fontBoldOpen'        : "**"            ,
    +	   'fontBoldClose'       : "**"            ,
    +	   'fontItalicOpen'      : "//"            ,
    +	   'fontItalicClose'     : "//"            ,
    +	   'fontUnderlineOpen'   : "__"            ,
    +	   'fontUnderlineClose'  : "__"            ,
    +	   'fontStrikeOpen'      : '<del>'         ,
    +	   'fontStrikeClose'     : '</del>'        ,
    +	   'listItemOpen'        : '  * '          ,
    +	   'numlistItemOpen'     : '  - '          ,
    +	   'bar1'                : '----'          ,
    +	   'url'                 : '[[\a]]'        ,
    +	   'urlMark'             : '[[\a|\a]]'     ,
    +	   'email'               : '[[\a]]'        ,
    +	   'emailMark'           : '[[\a|\a]]'     ,
    +	   'img'                 : '{{\a}}'        ,
    +	   'imgAlignLeft'        : '{{\a }}'       ,
    +	   'imgAlignRight'       : '{{ \a}}'       ,
    +	   'imgAlignCenter'      : '{{ \a }}'      ,
    +	   'tableTitleRowOpen'   : '^ '            ,
    +	   'tableTitleRowClose'  : ' ^'            ,
    +	   'tableTitleCellSep'   : ' ^ '           ,
    +	   'tableRowOpen'        : '| '            ,
    +	   'tableRowClose'       : ' |'            ,
    +	   'tableCellSep'        : ' | '           ,
    +# DokuWiki has no attributes. The content must be aligned!
    +#	   '_tableCellAlignRight' : '<)>'           , # ??
    +#	   '_tableCellAlignCenter': '<:>'           , # ??
    +# DokuWiki colspan is the same as txt2tags' with multiple |||
    +	   # 'comment'             : '## \a'         , # ??
    +	   # TOC is automatic
    +	},
    +
     	# http://en.wikipedia.org/wiki/Help:Editing
     	'wiki': {
     	   'title1'              : '== \a =='        ,
    @@ -1266,8 +1323,23 @@
    	    'autonumberlist':1,
     	    'breaktitleopen':1,
     	    },
    +	  'doku': {
    +	    'indentverbblock':1,           # DokuWiki uses '  ' to mark verb blocks
    +	    'spacedlistitem':1,
    +	    'linkable':1,
    +	    'blankendmotherlist':1,
    +	    'keeplistindent':1,
    +	    'tableable':1,
    +	    'barinsidequote':1,
    +	    'blankendtable':1,
    +	    'tablecellstrip':1,
    +	    'autotocwithbars':1,
    +	    'autonumberlist':1,
    +	    'imgalignable':1,
    +	    'tablecellaligntype':'cell',
    +	    },
     	  'wiki': {
     	    'linkable':1,
     	    'blankendmotherlist':1,

# Another real-world example

Directly from the txt2tags SVN, see how easy the BBCode target was added:

http://code.google.com/p/txt2tags/source/detail?r=410

Click in "expand all" to see the code. The green part is the new code.