REXXTAGS.org :: Samples: XML highlighter tag
Home Samples

File: rexxtags.xmlhighlight.tag [download (.tag file, 8 KB)]

Author: José María Blasco<jm@jmblasco.com>

Contributed on: 2002-12-05

Description: This REXX tag allows for a simple form of XML code highlighting. You can surround any XML code between <rexxtags:xmlhighlight> and </rexxtags:xmlhighlight> tags, and the unformatted code will be shown, highlighted, in your page. This is the same REXX tag used in the REXXTAGS tutorial.

Example: Here's the XML code (please substitute "*exxtags" for "rexxtags" in the code),

  1:<*exxtags:xmlhighlight lineno="yes">
  2:  <p style="text-align:justify>The quick brown <b>fox</b> jumps over
  3:   <i>the
  4:lazy</i>
  5:   dog.
  6:  </p>
  7:</*exxtags:xmlhighlight>
  8:


and here's the generated output:

  1:  <p style="text-align:justify>The quick brown <b>fox</b> jumps over
  2:   <i>the
  3:lazy</i>
  4:   dog.
  5:  </p>
  6:


Program code:



  1:/* <rexxtags:xmlhighlight>: a quick and dirty REXX tag to highlight XML code  */
  2:/*                                                                            */
  3:/* Parameters:                                                                */
  4:/*   lineno="[YES|1|NO|0]"       (Optional; default: NO)                      */
  5:/*   file="[filename]"           (Optional; default: "")                      */
  6:/*                                                                            */
  7:/* Version:     1.0                                                           */
  8:/*                                                                            */
  9:/* Author:      (c) Jose Maria Blasco <jm@jmblasco.com>                       */
 10:/*                                                                            */
 11:/* This software is subject to the terms of the Common Public License. You    */
 12:/* must accept the terms of this license to use this software. Refer to       */
 13:/* the license at the following URL for more information:                     */
 14:/* http://oss.software.ibm.com/developerworks/opensource/CPLv1.0.htm          */
 15:/*                                                                            */
 16:/* Description: A quick-and-dirty XML code highlighter which is used          */
 17:/* in the REXXTAGS tutorial (and elsewhere on the REXXTAGS site,              */
 18:/* http://www.rexxtags.org ). I wrote it in 30 minutes to test code           */
 19:/* highlighting, and invested later some more time so that the code is        */
 20:/* readable and has some documentation                                        */
 21:/*                                                                            */
 22:/* Disclaimer: I wrote this program for my own needs (mainly, for the         */
 23:/* REXXTAGS tutorial). It is NOT a complete XML highlighter, nor does it      */
 24:/* handle all syntactical cases. Use at your own risk.                        */
 25:/*                                                                            */
 26:/* Modifications:                                                             */
 27:/*                                                                            */
 28:/* Date       Author      Description                                         */
 29:/* ---------- ----------- --------------------------------------------------- */
 30:/* 2002/12/05 J.M.Blasco  v1.0 Initial release                                */
 31:
 32:Parse arg verb, parms, body /* Standard parse for tags which do body handling */
 33:
 34:Call GetParms               /* We'll need the parameters in many of the calls */
 35:
 36:
 37:/*----------------------------------------------------------------------------*/
 38:/* The tag is TAGDEPENDENT or not _depending_ on whether we are specifying    */
 39:/* a 'file' parameter.                                                        */
 40:/*----------------------------------------------------------------------------*/
 41:
 42:If verb == 'QUERY BODY CONTENT' Then
 43:  If file == '' Then Return 'TAGDEPENDENT'
 44:  Else Return 0
 45:
 46:/*----------------------------------------------------------------------------*/
 47:/* If a 'file' parameter is specified, the tag should not have a body, and    */
 48:/* all processing occurs at the start tag; otherwise, we delay processing     */
 49:/* until the body has been processed (that is, until the 'BODY' call).        */
 50:/*----------------------------------------------------------------------------*/
 51:
 52:If verb == 'START' Then
 53:  If file == '' Then Return ''
 54:  Else Signal StartTag
 55:
 56:If verb == 'BODY' Then Do   /* Standard body processing                       */
 57:  Interpret body
 58:  Signal Body
 59:End
 60:
 61:If verb == 'END' Then Return ''
 62:
 63:Return 0
 64:
 65:/*----------------------------------------------------------------------------*/
 66:/* This routine gets called only when a 'file' parameter has been specified   */
 67:/* and this is the 'START' call. The routine reads the file into a 'body.'    */
 68:/* stems, and then branches to normal body processing.                        */
 69:/*----------------------------------------------------------------------------*/
 70:
 71:StartTag:
 72:  Call on notready name seteof
 73:  eof = 0
 74:  body.0 = 0
 75:  file = Stream(file,'c','query exists')
 76:
 77:  If file == '' Then Signal Body
 78:  l = LineIn(file)
 79:  Do lineno = 1 By 1 While eof == 0
 80:    body.lineno = l
 81:    body.0 = lineno
 82:    l = LineIn(file)
 83:  End
 84:  Signal Body
 85:
 86:/*----------------------------------------------------------------------------*/
 87:/* This is to set an end-of-file indicator for StartTag's main read loop.     */
 88:/*----------------------------------------------------------------------------*/
 89:
 90:SetEof:
 91:  eof = 1
 92:Return
 93:
 94:/*----------------------------------------------------------------------------*/
 95:/* Parse the XML parameters                                                   */
 96:/*----------------------------------------------------------------------------*/
 97:
 98:GetParms:
 99:
100:  Parse var parms 'lineno="'lineno'"'
101:  If Translate(lineno) == "YES" Then lineno = 1
102:  If lineno \= 1 Then lineno = 0
103:  printlinenos = lineno
104:
105:  Parse var parms 'file="'file'"'
106:
107:Return
108:
109:/*----------------------------------------------------------------------------*/
110:/* Body processing routine. Does all the highlighting.                        */
111:/*----------------------------------------------------------------------------*/
112:
113:Body:
114:
115:  state = 0              /* State variable. 0: Normal text; 1: Inside XML tag */
116:  r = ''                 /* This will hold the accumulated result             */
117:
118:  diff = 0               /* Allow for the first line to be blank, and in..    */
119:  lineno = 1             /* ..this case, ignore it.                           */
120:  if body.1 = '' then do
121:    lineno = 2
122:    diff = 1
123:  End
124:
125:  /* Main loop                                                                */
126:
127:  Do lineno = lineno to body.0
128:
129:    l = body.lineno      /* If the last line is blank, ignore it              */
130:    If l = '' & lineno = body.0 Then Leave
131:
132:    l = change(l,'&','&amp;')                /* Don't mess with '&'           */
133:    l = change(l,'  ','&nbsp; ')             /* Don't allow blank sequences.. */
134:    l = change(l,'  ','&nbsp; ')             /* to collapse.                  */
135:
136:    l1 = ''              /* 'll' contains the already processed part of 'l'   */
137:    Do Forever
138:      If state = 0 & Pos('<',l) > 0 Then Do   /* State change: Normal --> XML */
139:        p = Pos('<',l)
140:        state = 1
141: l1 = l1||Left(l,p-1)'<font color="#0000ff"><b>&lt;'
142: l = Substr(l,p+1)
143: End
144:      Else If state = 1 & Pos('>',l) > 0 Then Do   /* XML --> Normal text     */
145:        p = Pos('>',l)
146:        state = 0
147: l1 = l1||Left(l,p-1)'&gt;</b></font>'
148: l = Substr(l,p+1)
149: End
150:      Else Leave /* Leave when no more '<' or '>' in line                     */
151:    End
152:    l = l1||l
153:    If printlinenos Then l = '<font color="#999999"><font size="1">'Change(Right(lineno-diff,3),' ','&nbsp;')'</font>:</font>'l
154:    If lineno = 1 Then r = '<br />'l
155:    Else r = r'00'x||'<br />'l
156:  End
157:Return '<font face="Courier New,Courier,Arial">'r'</font>'
158:
159:/* The following internal function is from Mike Cowlishaw  */
160:/* (posted in comp.lang.rexx)                              */
161:/* Internal function:  CHANGE(string,old,new)              */
162:/*                                                         */
163:/* (Like XEDIT  "C/old/new/1 *")                           */
164:/*                                                         */
165:/* Changes all occurrences of "old" in "string" to "new".  */
166:/* If "old"=='', then "new" is prefixed to "string".   MFC */
167:Change: procedure expose changed
168:  parse arg string, old, new
169:  if old=='' then do; changed=1; return new||string; end
170:  out=''; changed=0
171:  do while pos(old,string)\=0
172:    parse var string prefix (old) string
173:    out=out||prefix||new
174:    changed=changed+1
175:    end
176:  return out||string
177:

/samples/rexxtags.xmlhighlight.html
Last update: 13/12/02 at 16:07
 Comments
Valid XHTML 1.0! Valid CSS!