Suggest a new tip!


1. Top 4 user mistakes

  1. Forget to close lists with two blank lines (or with an empty item)
    BAD                           GOOD
    - My cool list                - My cool list
    - Should end here             - Ends here
    = No, not a title =
                                  = Title =
  2. Forget to "glue" the marks with their contents, leaving unwanted spaces
    BAD                           GOOD
    ** not bold**                 **bold**
    __not underline __            __underline__
    // no way it is italic //     //italic//
    [invalid link ]               [label link]
    [ invalid_image.png ]         [image.png]
  3. Forget to add the required spaces around table cells
    BAD                           GOOD
    |no|it's|not|a|table|         | this | is | a | table |
  4. Forget to add leading spaces to identify nested lists
    BAD                           GOOD
    : definition list             : definition list 
    - turned to bullet list?        - bullet inside
    + and now it is numbered?         + numbered inside bullet
    - what a mess!                  - back to bullet

2. Quick document tree

Writing a long document and suddenly get lost? Needs to edit that 50 page monster you don't touch for months? There is a quick way to get an overview of the contents:

$ txt2tags --toc-only -t txt userguide.t2t
  Part I - Introducing Txt2tags
    The First Questions You May Have
    Supported Formatting Structures
    Supported Targets
    Status of Supported Structures by Target
    The Three User Interfaces: Gui, Web and Command Line
  Part II - OK, I want it. Now what?
    Download & Install Python
    Download txt2tags

The --toc-only option dumps the Table of Contents of the document, using the same target as the document's. So we force it to be clear text with -t txt. Another option that can be used is --enum-title to get nice numbers:

$ txt2tags --toc-only -t txt --enum-title userguide.t2t 
  1. Part I - Introducing Txt2tags
    1.1. The First Questions You May Have
    1.2. Supported Formatting Structures
    1.3. Supported Targets
    1.4. Status of Supported Structures by Target
    1.5. The Three User Interfaces: Gui, Web and Command Line
  2. Part II - OK, I want it. Now what?
    2.1. Download & Install Python
    2.2. Download txt2tags

If the document tree is deep, you can limit the dump to any level with the --toc-level option:

$ txt2tags --toc-only -t txt --enum-title --toc-level 1 userguide.t2t 
  1. Part I - Introducing Txt2tags
  2. Part II - OK, I want it. Now what?
  3. Part III - Writing and Converting Your First Document
  4. Part IV - Mastering Txt2tags Concepts
  5. Part V - Mastering Marks
  6. Part VI - Mastering Macros
  7. Part VII - Mastering Settings
  8. Part VIII - Black Magic
  9. Part IX - Txt2tags HISTORY

3. Make strike text

Upgrade your txt2tags to version 2.5 or newer, which has strike text support with the -- mark. For example, --STRIKE-- becomes STRIKE.

In older versions, some nice filters will do the trick:

%%% Support for --strike-- text in txt2tags older than 2.5
%!postproc(html):  '--([^ ].*?)--'  <s>\1</s>
%!style(tex): ulem
%!postproc(tex):  --(.*?)--  \sout{\1}

If you want to use this filter for all your files, put it on the txt2tags RC File.

4. Make case insensitive filters

PreProc and PostProc filters are case sensitive by default. This means that when matching, the text "txt2tags" is different from "TXT2TAGS". If you want to make a filter that treats lower and uppercase letters as the same (ignore case), just put a "(?i)" at the beginning. Example:

%preproc: '(?i)latex'   'LaTeX'   

This way, "latex", "LATEX", "LAtex" and all its variants will be changed to "LaTeX".

5. Make centred aligned paragraphs

In txt2tags you can't center paragraphs, but you can center a table. So...

    | This is a centered paragraph.

This line results in:

This is a centered paragraph.

Note: There are spaces before the pipe | to make the table centred. There are no trailing pipe at the end of the line, so this table has no border, making it invisible.

Note: Yes, this is ugly and piggy. Avoid to use it.

Note: In (X)HTML targets, it's best to enclose the paragraph inside a DIV and make a CSS rule to center it.

If your document will use many links (URLs), the text can quickly become too noisy and polluted. The cleaner approach is to store all the links at the config area, making a link bank:

%!preproc: URLT2T
%!preproc: URLGOOGLE
%!preproc: URLBLOG

Then you can write your text with cleaner links:

This site is powered by [txt2tags URLT2T]. For more information
please [read my Blog URLBLOG] or [search Google URLGOOGLE].

Compare this to the inline links (ugly) version:

This site is powered by [txt2tags].
For more information please
[read my Blog]
or [search Google].

Plus: If there are links that you use all the time in your documents (your website or blog, for example), you can make a global link bank on an urls.t2t file, or on your txt2tags RC File, then all your documents can use them. The other advantage is that it makes easy when the link changes, you just have to edit one single place.

An evolution from the previous tip, you can put links automatically for any word(s) you want.

%!preproc: '(?i)(txt2tags)'   '[\1]'
%!preproc: '(Google)'         '[\1]'
%!preproc: '(Yahoo! Groups)'  '[\1]'

Then in your text you won't bother inserting links manually, txt2tags will do it for you:

I do use Txt2tags, Google and Yahoo! Groups everyday.

Converting this text to XHTML:

I do use <a href="">Txt2tags</a>,
<a href="">Google</a> and
<a href="">Yahoo! Groups</a> everyday.

Handy, huh? Note that the "(?i)" part on the first filter make it case insensitive, working for "txt2tags", "TXT2TAGS" and any other variant.

8. Force link (URL) recognition

When trying (and failing) to make some funky links like:

[Main page index.php?page=main]

[Product details product?id=1234567]

Just "protect" the link address with the raw mark and it will be converted correctly:

[Main page ""index.php?page=main""]

[Product details ""product?id=1234567""]

Note: This is often needed for local (relative) links only. Full URLs like are recognized by default.

9. Use spaces and Unicode characters in image filename

We need to be restrictive to avoid false positives when matching texts. These are the currently allowed characters for an image filename:


If your image filename contains spaces, accented letters or Unicode characters, just protect the filename (except the extension!) with the raw mark:


10. Change the default format for the %%date macro

When used without arguments, the %%date macro expands to the current date in the ISO format: YYYYMMDD. But with a nice filter, you can change this default format:

%!preproc:  %%date  %%date(%d-%m-%Y %H:%M)

If you want to use this filter for all your files, put it on the txt2tags RC File.

11. Make code snippets colored (syntax highlight)

Txt2tags doesn't colorize programming code inside verbatim blocks. That would be plain bloat, and we're KISS.

But you can make that using any other colorizer program and save the results to a file. Then you just include this file on the txt2tags conversion using the Tagged Include feature.

%!include(html): '''' 

If you use the Vim editor, just run this command to get you code colorized in HTML (check the path for 2html.vim on your system):

vi -c "so /usr/share/vim/vim7/syntax/2html.vim|wqa"

You can enter the © and ® symbols directly on the source file without fuss. Just find out how to insert them in your text editor. Copy & paste also works fine (copy from here!).

Note: In Vim, type Ctrl-K Co and Ctrl-K Rg in Insert mode. The :dig command lists other symbols.

Depending on the target, you may have to specify a new file encoding so that these symbols appear correctly. If you run into problems, try adding this line to your configuration:

%!encoding: iso-8859-1

The ™ symbol is a little trickier because it's part of the new UTF-8 encoding. First you need to save your source file as an UTF-8 text file. Check your text editor's preferences. Then just tell txt2tags about the new encoding:

%!encoding: utf-8

Bonus Tip: If you plan to type symbols or accented characters in your texts, a good practice is always use the UTF-8 encoding in your files. You don't need to understand exactly what it is, just keep in mind that is has all the symbols you may need someday :)

Another solution is to use the target's specific characters entities that represent those symbols. Then you can insert those symbols as "(C)", "(R)" and "(TM)" on the source file and let the filters do the dirty job. But remember that each target must have its own set of filters. An example for HTML:

% Filters to use (C), (R) and (TM) as copyright symbols
%!postproc(html):  \(C\)   &copy;
%!postproc(html):  \(R\)   &reg;
%!postproc(html):  \(TM\)  &#8482;

13. Config overview (or Solving configuration problems)

In txt2tags you can define configuration in three tiers:

Things can get real wild if you make lots of configs in all those places. Even wilder if you're using the %!includeconf command to get more configuration to your document.

In doubt or trouble, use the --dump-config option to see all the configuration that is being read. First it lists all the config found on the RC file:

$ txt2tags --dump-conf userguide.t2t
RAW config for RC file
  (all)    target........: html

Then there is the config found on the document's Config Area. Note that the first column shows the target where the config will be applied. If it is "(all)", this config is valid for all targets.

RAW config for source document
  (all)    target........: html
  (all)    options.......: --toc --toc-level 2 --css-sugar
  (all)    options.......: --css-sugar --no-toc --style userguide.css
  (all)    postproc......: ('<H3>Aurelio, .*', '')
  (all)    preproc.......: ('IMGPATH', '.')
  (html)   preproc.......: ('^%nopdf', '')
  (html)   preproc.......: ('^ *--------*', '')
  (html)   preproc.......: ('^ *========*', '')

Next are the command line options:

RAW config for command line
  (all)    dump-config...: ON
  (all)    infile........: userguide.t2t
  (all)    realcmdline...: ['--dump-conf', 'userguide.t2t']

And after all this listing, here is the result: the parsed config. It's the real configuration that will be applied to the document after all the configs were read and processed.

Full PARSED config
           css-sugar.....: ON
           dump-config...: ON
           infile........: userguide.t2t
           realcmdline...: --dump-conf, userguide.t2t
           sourcefile....: userguide.t2t
           style.........: userguide.css
           target........: html
           toc-level.....: 2

Active filters
           preproc.......: IMGPATH  ->  .
           preproc.......: MARKPROP  ->  **Properties:**
           preproc.......: MARKCONT  ->  **Contains:**
           preproc.......: ^%nopdf  ->  
           preproc.......: ^ *--------*  ->  
           preproc.......: ^ *========*  ->  
           postproc......: <H3>Aurelio, .*  ->  

Target Specific

14. Table COLUMN align targets: SGML, LaTeX and Man Page

Some targets let you align each table cell independently, as HTML. Other are more strict, just letting you align the table column, then all its cells share the same positioning. This is the case for SGML, LaTeX and Man.

On this targets, the column alignment is defined by the align of the first table row cells (usually it's a title row). So keep that in mind when writing your text.

  |     Name     |   Age   |
  | John Smith   |      55 |
  | Mary Katana  |      23 |

In this example, both columns will be centered on the aforementioned targets, regardless the left and right align defined on the second and third rows.

15. (X)HTML: What exactly the --css-sugar option does

It "insert CSS-friendly tags for HTML and XHTML targets" ;)

Ok, ok, more details:

So this option clears the formatting attributes and create new DIVs to make it easier to use CSS rules. Then you can see the page as a three piece component: header, toc, body and apply different rules for each.

Note: Using --style doesn't imply --css-sugar. You have to declare both.

16. (X)HTML: Insert a manual line break <BR>

Txt2tags doesn't have a mark for the manual line break. In the cases you want to use it, maybe a bullet list, a table or a verbatim text would fit better.

But if the line break is the solution you want, just make your own new mark for it. Let's say "@@" will be the line break mark.

%!postproc( html): @@ <BR>
%!postproc(xhtml): @@ <br />

Then in your text, use @@ when you want a line break. Example:

First line @@ Second Line @@ Third line

17. (X)HTML: Use semantic tags (STRONG, EM, INS, DEL) instead visual tags (B, I, U, S)

By default txt2tags uses the good old visual tags (<B>, <I>, <U>, <S>) for bold, italic, underline and strike text.

Some people prefer to use their semantic equivalents (<strong>, <em>, <ins>, <del>) instead. If this is your case, just set up these filters:

% Use semantic tags (strong, em, ins, del) instead visual (B, I, U, S)
%!postproc(html):  '(?i)(</?)b>'  '\1strong>'
%!postproc(html):  '(?i)(</?)i>'  '\1em>'
%!postproc(html):  '(?i)(</?)u>'  '\1ins>'
%!postproc(html):  '(?i)(</?)s>'  '\1del>'

If you want to use this filter for all your files, put it on the txt2tags RC File.

18. (X)HTML: Make subscript/superscript text

Txt2tags doesn't have a mark for subscript or superscript text. But you can make your own. Let's define the following two new marks for them:

Using the same idea from the previous tip, we make two filters:

% The ^ need to be escaped by \
%!postproc(html):  \^\^(.*?)\^\^  <sup>\1</sup>
%!postproc(html):  ,,(.*?),,      <sub>\1</sub>

Using this filters, ^^upper^^ and ,,lower,, becomes <sup>upper</sup> and <sub>lower</sub>.

Again, you can instead use the modern CSS powered version:

%!postproc(html):  \^\^(.*?)\^\^  <span class="textsup">\1</span>
%!postproc(html):  ,,(.*?),,      <span class="textsub">\1</span>

% On the CSS:
% .textsup { vertical-align: super }
% .textsub { vertical-align: sub   }

If you want to use this filters for all your files, put it on the txt2tags RC File.

19. (X)HTML: Use a remote image

In txt2tags you have a mark for local images, but not for remote ones. The trick here is to fool the program making it think your remote image is local.

There are two ways of achieving this. The first uses a filter:

%!postproc(html):  RemoteImage.jpg

Hi, check out my picture: [RemoteImage.jpg].

So txt2tags will make the image tag <IMG SRC="RemoteImage.jpg"> and the filter will change it to <IMG SRC="http://www.example...">.

The other trick is cleaner to type, but relies on a txt2tags behavior that may not work on future versions. Just protect the image address with the raw mark, from the beginning to the last character before the dot:

Hi, check out my picture: ["""".jpg].


20. (X)HTML: Insert text for images ALT attribute

Txt2tags already puts an empty ALT="" attribute on all images, so all you have to do is to fill it. PostProc comes for the rescue.

%!postproc(xhtml): '(?i)(city.jpg.*?alt=")'   '\1this is my city' 
%!postproc(xhtml): '(?i)(beach.jpg.*?alt=")'  '\1a really nice beach' 

Hello, this is a photo of my city: [city.jpg]
And this the beach near here: [beach.jpg]

This will be converted to:

Hello, this is a photo of my city:
<img align="right" src="city.jpg" border="0" alt="this is my city"/>
And this the beach near here:
<img align="right" src="beach.jpg" border="0" alt="a really nice beach"/>

The PostProc rule is a regular expression that matches from the image filename until its ALT attribute contents start. Don't worry if you don't understand these symbols. Just copy & paste these lines to you text and change "city.jpg" by your image filename and "this is my city" to the image's text. The rest remains untouched.

21. (X)HTML: Insert custom tags (DIV, SPAN)

From txt2tags version 2.6 and newer, there's a new tagged mark to directly insert target code.

You can do it in blocks:

<div id="mycooldiv">
	This paragraph will live inside mycooldiv DIV.

	But note that txt2tags marks are not interpreted here.

In specific lines:

''' <div id="mycooldiv">

This paragraph will live inside mycooldiv DIV.

Txt2tags marks are interpreted here.

''' </div>

Or even inline, inside a paragraph:

My name is ''<span class="name">''John''</span>''.

If you're using and older version of txt2tags, follow these tips:

You can combine the Raw Line mark and a PostProc filter to insert any arbitrary (X)HTML tag you need.

First, decide which symbols you'll use to represent the < and > characters. A popular choice is {{ and }}. Then write your tags inside Raw Lines and it will work. Example:

%!postproc(html):  {{(.*?)}}  <\1>

""" {{div id="mycooldiv"}}
This paragraph will live inside mycooldiv DIV.

""" {{/div}}

This will generate the following HTML code:

<div id="mycooldiv">
This paragraph will live inside mycooldiv DIV.

Note: The blank line after the paragraph is to make sure it will be closed before the DIV. If omitted, you'll end with tag overlap: <div><p></div></p>.

22. (X)HTML: Use entities like &eacute; for accented characters

All modern browsers know how to handle accented characters, you don't need to use HTML entities like &eacute; or &atilde; to represent them. Just type the accented letters normally.

The only thing you need to do, is to specify the correct encoding of your source file. You can use the txt2tags --encoding option or %!encoding directive. Examples:

% My source file is encoded in UTF-8
%!encoding: UTF-8

% My source file is encoded in latin-1 (ISO-8859-1)
%!encoding: iso-8859-1

If you really need the entities, for some exotic reason or system limitation, you can convert the accented chars using filters. If you use just a few accented chars, create one filter for each letter (lower and uppercase):

% Convert accented chars to HTML entities: é -> &eacute;
%!postproc(html):  á   &aacute;
%!postproc(html):  â   &acirc;
%!postproc(html):  à   &agrave;
%!postproc(html):  ã   &atilde;
%!postproc(html):  ä   &auml;
%!postproc(html):  Á   &Aacute;
% ...

If you want a general solution for all accented vowels plus C-cedilla and N-tilde, use this set of filters:

% Convert accented vowels (plus Ç and Ñ) to HTML entities
%!postproc(html):  ([ÁÉÍÓÚáéíóú])   &\1acute;
%!postproc(html):  ([ÀÈÌÒÙàèìòù])   &\1grave;
%!postproc(html):  ([ÄËÏÖÜäëïöü])   &\1uml;
%!postproc(html):  ([ÂÊÎÔÛâêîôû])   &\1circ;
%!postproc(html):  ([ÃÕãõ])         &\1tilde;
%!postproc(html):  &[ÁÀÃÄÂ](\w+;)   &A\1
%!postproc(html):  &[áàãäâ](\w+;)   &a\1
%!postproc(html):  &[ÉÈËÊ](\w+;)    &E\1
%!postproc(html):  &[éèëê](\w+;)    &e\1
%!postproc(html):  &[ÍÌÏÎ](\w+;)    &I\1
%!postproc(html):  &[íìïî](\w+;)    &i\1
%!postproc(html):  &[ÓÒÖÔÕ](\w+;)   &O\1
%!postproc(html):  &[óòöôõ](\w+;)   &o\1
%!postproc(html):  &[ÚÙÜÛ](\w+;)    &U\1
%!postproc(html):  &[úùüû](\w+;)    &u\1
%!postproc(html):  Ñ                &Ntilde;
%!postproc(html):  ñ                &ntilde;
%!postproc(html):  Ç                &Ccedil;
%!postproc(html):  ç                &ccedil;

If you want to use this filters for all your files, put it on the txt2tags RC File.

23. (X)HTML: Split the page in multiple files

All you have to do is to normally convert your file to (X)HTML with txt2tags, then use the excellent HTMLDOC tool to split it. Example:

htmldoc -t htmlsep -o output-folder file.html

You can get full instructions on how to install and use HTMLDOC with txt2tags on this Blog post.

24. (X)HTML: Convert HTML pages to the txt2tags markup

If you're migrating your site to txt2tags, there's a handy Vim script to convert all your HTML files to the simple t2t markup.

Repeat this process to all your HTML files.

Tip inside the tip: You can comment line 85 if you want the script to preserve unknown tags. They are deleted by default. Just add a double quote at the line start:

" mmmmm, dangerous! it removes all remaining HTML tags
" %s,<[^>]*>,,ge

Note: The Vim editor is installed by default on Linux and Mac OS X. Windows users must download and install it to use this script.

25. Man: Change section number

By default txt2tags generates man pages for section 1 (user commands). But your man page can use any of these sections:

Nr. Topic
1 Commands available to users
2 Unix and C system calls
3 C library routines for C programs
4 Special file names
5 File formats and conventions for files used by Unix
6 Games
7 Word processing packages
8 System administration commands and procedures

To change the man section number, use this PostProc filter:

%!postproc(man): "^(\.TH.*) 1 "  "\1 5 "

Change the number "5" to the desired section number. Attention to the white spaces. Cut & paste this line to make sure it is correct.

If you want to use this filter for all your files, put it on the txt2tags RC File.

26. Man: Make the OPTIONS part of the man page

Man pages use a standard format to show a program's options. You can make your man page looks exactly as the system's pages using definition lists. Pay attention to the bold marks and leading spacing on each definition term. Example:


:      **--dump-config**
print all the config found and exit

:  **-h**, **--help**
print help information and exit

:  **-V**, **--version**
print program version and exit

27. MagicPoint: Make a pause on the slide

You can use the strong bar (=========) to make a pause on the current slide in MagicPoint. It's useful to show just the first part of the slide, then you explain it, then you press the space bar and the rest of the slide appears.

You can use as many pauses as needed, like one for each list item. Example:

= My nice slide =

- Item one
- Item two
- Item three
- Item four

28. LaTeX: Load extra packages (\usepackage)

You can load any LaTeX package into your document, just use the Style directive. Example:

%!style(tex): amssymb

% The --style command line option is another alternative

This will create the \usepackage{amssymb} line on your document Preamble. Multiple packages can be loaded in one single call:

%!style(tex): amssymb,booktabs,array,paralist

% Will turn into \usepackage{amssymb,booktabs,array,paralist}

Starting in txt2tags version 2.3.1, you can also define multiple style calls, making it easy insert configuration for each package using PostProc filters. Example:

%!style(tex): amssymb
%!style(tex): booktabs
%!style(tex): array
%!style(tex): paralist

% This will create four \usepackage lines

If you want to use this configuration for all your files, put it on the txt2tags RC File.

29. LaTeX: Remove the current date

In txt2tags, the third header line is often used for the document date. If you leave it blank, no date tag will be generated. But in LaTeX, when no date tag is found, it automatically shows the current date on the document cover. Some expect this behavior, some don't.

To force the document to have no date, you must leave an empty date tag on the LaTeX code: \date{}. You can make it easily setting a PostProc filter:

%!postproc(tex): \\date{-}  \date{}

And in you source files, just type an hyphen on the third line, for example:

My doc
John Doe

The filter will remove the hyphen, leaving the tag empty and then LaTeX won't print any date.

Extra tip: If your TeX processor complains about the missing Author tag, you can do a similar workaround setting up another filter:

%!postproc(tex): \\author{-}  \author{}

If you want to use this configuration for all your files, put it on the txt2tags RC File.

30. LaTeX: Set the language config (babel, inputenc)

For the text encoding (character set) just use the Encoding directive. Then include the babel package in your document and create a PostProc filter to insert the language for it. It's a three line wonder:

% Brazilian Portuguese configuration
%!encoding: iso-8859-1
%!style(tex): babel
%!postproc(tex): {babel} [brazil]{babel}

This will add two extra lines to the LaTeX Preamble:

\usepackage[latin1]{inputenc}  % char encoding
\usepackage[brazil]{babel}  % user defined package

Note that the IANA standard encoding names are automatically translated to the LaTeX equivalents (iso-8859-1 to latin1 on this example).

31. LaTeX: Use a personal style file (.sty)

Create your own LaTeX user style file (say myrules.sty) with all the packages and configuration you usually put inside the document Preamble.

Then just use the Style directive pointing to your file. Remember to include the relative path for the file, if it isn't on the same folder as your txt2tags source file. The file must have the .sty extension. You can use as many files as your heart wishes. Example:

%!style(tex): ../../common.sty
%!style(tex): ../../pdfthings.sty
%!style(tex): projectrules.sty

Note: The support for multiple style files was added into txt2tags version 2.3.1.

If you want to use this configuration for all your files, put it on the txt2tags RC File.

32. LaTeX: Use symbols and Greek letters (µ « ® Ø)

In LaTeX you normally just use $\mu$ to represent the µ Greek letter. You can type the letter on the txt2tags sources and make a postproc to convert it to the LaTeX entity.

%!postproc(tex): "µ"  "$\mu$"

You can create similar filters for all the Greek letters do you normally use, as well for any other special encoded letter or symbol.

If you want to use this filter for all your files, put it on the txt2tags RC File.

Text Editors

33. Vim: Convert the current file

:!txt2tags %

The ! executes an external command and % expands to the current filename. Make sure you have set the %!target configuration on the file, so you don't have to type the -t option on the command line.

Note that Vim's command-line mode ":" has history, so you just have to type it once. For the next conversions just do:


If you want to preserve this history even when quitting Vim, put this line in your ~/.vimrc:

set viminfo='10,\"30,:40,%,n~/.viminfo

34. Vim: Handy mappings to convert files

By Frank Mueller

With this lines in your ~/.vimrc, you will have handy shortcuts to convert the current file to LaTeX, HTML and text:

map 2l :w<CR>:!txt2tags -t tex % ; xelatex %<.tex ; open %<.pdf<CR>
map 2h :w<CR>:!txt2tags -t html % ; open %<.html<CR>
map 2t :w<CR>:!txt2tags -t txt % <CR>