filters.rst 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. ===================
  2. Source Code Filters
  3. ===================
  4. .. contents::
  5. A `Source Code Filter` transforms the input character stream to an in-memory
  6. output stream before parsing. A filter can be used to provide templating
  7. systems or preprocessors.
  8. To use a filter for a source file the ``#?`` notation is used::
  9. #? stdtmpl(subsChar = '$', metaChar = '#')
  10. #proc generateXML(name, age: string): string =
  11. # result = ""
  12. <xml>
  13. <name>$name</name>
  14. <age>$age</age>
  15. </xml>
  16. As the example shows, passing arguments to a filter can be done
  17. just like an ordinary procedure call with named or positional arguments. The
  18. available parameters depend on the invoked filter. Before version 0.12.0 of
  19. the language ``#!`` was used instead of ``#?``.
  20. **Hint:** With ``--hint[codeBegin]:on```or ``--verbosity:2``
  21. (or higher) Nim lists the processed code after each filter
  22. application.
  23. Pipe operator
  24. =============
  25. Filters can be combined with the ``|`` pipe operator::
  26. #? strip(startswith="<") | stdtmpl
  27. #proc generateXML(name, age: string): string =
  28. # result = ""
  29. <xml>
  30. <name>$name</name>
  31. <age>$age</age>
  32. </xml>
  33. Available filters
  34. =================
  35. Replace filter
  36. --------------
  37. The replace filter replaces substrings in each line.
  38. Parameters and their defaults:
  39. ``sub: string = ""``
  40. the substring that is searched for
  41. ``by: string = ""``
  42. the string the substring is replaced with
  43. Strip filter
  44. ------------
  45. The strip filter simply removes leading and trailing whitespace from
  46. each line.
  47. Parameters and their defaults:
  48. ``startswith: string = ""``
  49. strip only the lines that start with *startswith* (ignoring leading
  50. whitespace). If empty every line is stripped.
  51. ``leading: bool = true``
  52. strip leading whitespace
  53. ``trailing: bool = true``
  54. strip trailing whitespace
  55. StdTmpl filter
  56. --------------
  57. The stdtmpl filter provides a simple templating engine for Nim. The
  58. filter uses a line based parser: Lines prefixed with a *meta character*
  59. (default: ``#``) contain Nim code, other lines are verbatim. Because
  60. indentation-based parsing is not suited for a templating engine, control flow
  61. statements need ``end X`` delimiters.
  62. Parameters and their defaults:
  63. ``metaChar: char = '#'``
  64. prefix for a line that contains Nim code
  65. ``subsChar: char = '$'``
  66. prefix for a Nim expression within a template line
  67. ``conc: string = " & "``
  68. the operation for concatenation
  69. ``emit: string = "result.add"``
  70. the operation to emit a string literal
  71. ``toString: string = "$"``
  72. the operation that is applied to each expression
  73. Example::
  74. #? stdtmpl | standard
  75. #proc generateHTMLPage(title, currentTab, content: string,
  76. # tabs: openArray[string]): string =
  77. # result = ""
  78. <head><title>$title</title></head>
  79. <body>
  80. <div id="menu">
  81. <ul>
  82. #for tab in items(tabs):
  83. #if currentTab == tab:
  84. <li><a id="selected"
  85. #else:
  86. <li><a
  87. #end if
  88. href="${tab}.html">$tab</a></li>
  89. #end for
  90. </ul>
  91. </div>
  92. <div id="content">
  93. $content
  94. A dollar: $$.
  95. </div>
  96. </body>
  97. The filter transforms this into:
  98. .. code-block:: nim
  99. proc generateHTMLPage(title, currentTab, content: string,
  100. tabs: openArray[string]): string =
  101. result = ""
  102. result.add("<head><title>" & $(title) & "</title></head>\n" &
  103. "<body>\n" &
  104. " <div id=\"menu\">\n" &
  105. " <ul>\n")
  106. for tab in items(tabs):
  107. if currentTab == tab:
  108. result.add(" <li><a id=\"selected\" \n")
  109. else:
  110. result.add(" <li><a\n")
  111. #end
  112. result.add(" href=\"" & $(tab) & ".html\">" & $(tab) & "</a></li>\n")
  113. #end
  114. result.add(" </ul>\n" &
  115. " </div>\n" &
  116. " <div id=\"content\">\n" &
  117. " " & $(content) & "\n" &
  118. " A dollar: $.\n" &
  119. " </div>\n" &
  120. "</body>\n")
  121. Each line that does not start with the meta character (ignoring leading
  122. whitespace) is converted to a string literal that is added to ``result``.
  123. The substitution character introduces a Nim expression *e* within the
  124. string literal. *e* is converted to a string with the *toString* operation
  125. which defaults to ``$``. For strong type checking, set ``toString`` to the
  126. empty string. *e* must match this PEG pattern::
  127. e <- [a-zA-Z\128-\255][a-zA-Z0-9\128-\255_.]* / '{' x '}'
  128. x <- '{' x+ '}' / [^}]*
  129. To produce a single substitution character it has to be doubled: ``$$``
  130. produces ``$``.
  131. The template engine is quite flexible. It is easy to produce a procedure that
  132. writes the template code directly to a file::
  133. #? stdtmpl(emit="f.write") | standard
  134. #proc writeHTMLPage(f: File, title, currentTab, content: string,
  135. # tabs: openArray[string]) =
  136. <head><title>$title</title></head>
  137. <body>
  138. <div id="menu">
  139. <ul>
  140. #for tab in items(tabs):
  141. #if currentTab == tab:
  142. <li><a id="selected"
  143. #else:
  144. <li><a
  145. #end if
  146. href="${tab}.html" title = "$title - $tab">$tab</a></li>
  147. #end for
  148. </ul>
  149. </div>
  150. <div id="content">
  151. $content
  152. A dollar: $$.
  153. </div>
  154. </body>