From b5c8f2ee0777e442c68c413050292e8bcaede6bf Mon Sep 17 00:00:00 2001 From: Mark Hansen Date: Sun, 17 May 2020 17:12:52 +1000 Subject: [PATCH] Convert mkattrs.sh to Python/Jinja2 templating --- doc/info/attrs.html | 128 +++++------ doc/infosrc/Makefile | 10 +- doc/infosrc/attrs | 12 +- doc/infosrc/mkattrs.py | 107 +++++++++ doc/infosrc/mkattrs.sh | 344 ---------------------------- doc/infosrc/templates/attrs.html.j2 | 68 ++++++ 6 files changed, 250 insertions(+), 419 deletions(-) create mode 100755 doc/infosrc/mkattrs.py delete mode 100755 doc/infosrc/mkattrs.sh create mode 100644 doc/infosrc/templates/attrs.html.j2 diff --git a/doc/info/attrs.html b/doc/info/attrs.html index 676a4a188..7a9a40756 100644 --- a/doc/info/attrs.html +++ b/doc/info/attrs.html @@ -90,11 +90,11 @@ of the layout programs. GCdouble0.30sfdp, fdp only URL ENGCescString -<none>svg, postscript, map only +<none>svg, postscript, map only _background -Gstring<none> +Gstring<none> area -NCdouble1.0>0patchwork only +NCdouble1.0>0patchwork only arrowhead EarrowType normal @@ -109,14 +109,14 @@ of the layout programs. bgcolor GCcolor
colorList -<none> +<none> center Gbool false charset -Gstring"UTF-8" +Gstring"UTF-8" class -ENCGstring""svg only +ENCGstring""svg only clusterrank GclusterMode localdot only @@ -125,9 +125,9 @@ of the layout programs.
colorList black colorscheme -ENCGstring"" +ENCGstring"" comment -ENGstring"" +ENGstring"" compound Gbool falsedot only @@ -158,16 +158,16 @@ of the layout programs. Gdouble96.0
0.0svg, bitmap output only edgeURL EescString -""svg, map only +""svg, map only edgehref EescString -""svg, map only +""svg, map only edgetarget EescString -<none>svg, map only +<none>svg, map only edgetooltip EescString -""svg, cmap only +""svg, cmap only epsilon Gdouble.0001 * # nodes(mode == KK)
.0001(mode == major)
.01(mode == sgd)neato only esep @@ -185,9 +185,9 @@ of the layout programs. ENGCcolor black fontname -ENGCstring"Times-Roman" +ENGCstring"Times-Roman" fontnames -Gstring""svg only +Gstring""svg only fontpath Gstringsystem-dependent fontsize @@ -196,12 +196,12 @@ of the layout programs. Gbool true gradientangle -NCGint"" +NCGint"" group -Nstring""dot only +Nstring""dot only headURL EescString -""svg, map only +""svg, map only head_lp Epoint write only @@ -210,44 +210,44 @@ of the layout programs. true headhref EescString -""svg, map only +""svg, map only headlabel ElblString -"" +"" headport EportPos center headtarget EescString -<none>svg, map only +<none>svg, map only headtooltip EescString -""svg, cmap only +""svg, cmap only height Ndouble0.50.02 href GCNEescString -""svg, postscript, map only +""svg, postscript, map only id GCNEescString -""svg, postscript, map only +""svg, postscript, map only image -Nstring"" +Nstring"" imagepath -Gstring"" +Gstring"" imagepos -Nstring"mc" +Nstring"mc" imagescale Nbool
stringfalse inputscale -Gdouble<none>fdp, neato only +Gdouble<none>fdp, neato only label ENGClblString -"\N" (nodes)
"" (otherwise) +"\&#92;N" (nodes)
"" (otherwise) labelURL EescString -""svg, map only +""svg, map only label_scheme Gint00sfdp only labelangle @@ -261,40 +261,40 @@ of the layout programs. Ecolor black labelfontname -Estring"Times-Roman" +Estring"Times-Roman" labelfontsize Edouble14.01.0 labelhref EescString -""svg, map only +""svg, map only labeljust -GCstring"c" +GCstring"c" labelloc -NGCstring"t"(clusters)
"b"(root graphs)
"c"(nodes) +NGCstring"t"(clusters)
"b"(root graphs)
"c"(nodes) labeltarget EescString -<none>svg, map only +<none>svg, map only labeltooltip EescString -""svg, cmap only +""svg, cmap only landscape Gbool false layer ENClayerRange -"" +"" layerlistsep -Gstring"," +Gstring"," layers GlayerList -"" +"" layerselect GlayerRange -"" +"" layersep -Gstring" :\t" +Gstring" &#92;t" layout -Gstring"" +Gstring"" len Edouble1.0(neato)
0.3(fdp)fdp, neato only levels @@ -302,21 +302,21 @@ of the layout programs. levelsgap Gdouble0.0neato only lhead -Estring""dot only +Estring""dot only lheight GCdoublewrite only lp EGCpoint write only ltail -Estring""dot only +Estring""dot only lwidth GCdoublewrite only margin NCGdouble
point -<device-dependent> +<device-dependent> maxiter -Gint100 * # nodes(mode == KK)
200(mode == major)
30(mode == sgd)
600(fdp)fdp, neato only +Gint100 * # nodes(mode == KK)
200(mode == major)
30(mode == sgd)
600(fdp)fdp, neato only mclimit Gdouble1.0dot only mindist @@ -348,11 +348,11 @@ of the layout programs.
nslimit1 Gdoubledot only ordering -GNstring""dot only +GNstring""dot only orientation Ndouble0.0360.0 orientation -Gstring"" +Gstring"" outputorder GoutputMode breadthfirst @@ -425,15 +425,15 @@ of the layout programs. Gdouble96.0
0.0svg, bitmap output only root GNstring
bool -<none>(graphs)
false(nodes)circo, twopi only +<none>(graphs)
false(nodes)circo, twopi only rotate Gint0 rotation Gdouble0sfdp only samehead -Estring""dot only +Estring""dot only sametail -Estring""dot only +Estring""dot only samplepoints Nint8(output)
20(overlap and image maps) scale @@ -449,7 +449,7 @@ of the layout programs. Nshape ellipse shapefile -Nstring"" +Nstring"" showboxes ENGint00dot only sides @@ -461,7 +461,7 @@ of the layout programs. Ndouble0.0-100.0 smoothing GsmoothType -"none"sfdp only +"none"sfdp only sortv GCNint00 splines @@ -469,15 +469,15 @@ of the layout programs.
string start GstartType -""fdp, neato only +""fdp, neato only style ENCGstyle -"" +"" stylesheet -Gstring""svg only +Gstring""svg only tailURL EescString -""svg, map only +""svg, map only tail_lp Epoint write only @@ -486,25 +486,25 @@ of the layout programs. true tailhref EescString -""svg, map only +""svg, map only taillabel ElblString -"" +"" tailport EportPos center tailtarget EescString -<none>svg, map only +<none>svg, map only tailtooltip EescString -""svg, cmap only +""svg, cmap only target ENGCescString -
string<none>svg, map only +
string<none>svg, map only tooltip NECescString -""svg, cmap only +""svg, cmap only truecolor Gbool bitmap output only @@ -513,7 +513,7 @@ of the layout programs. write only viewport GviewPort -"" +"" voro_margin Gdouble0.050.0not dot weight @@ -524,7 +524,7 @@ of the layout programs. Gstringxdot only xlabel ENlblString -"" +"" xlp NEpoint write only diff --git a/doc/infosrc/Makefile b/doc/infosrc/Makefile index a04f93564..31b0b8a98 100644 --- a/doc/infosrc/Makefile +++ b/doc/infosrc/Makefile @@ -119,10 +119,10 @@ sdlshapes.ps : sdlshapes.dot sdlshapes.png : sdlshapes.ps ./ps_to_png.sh sdlshapes.ps sdlshapes.png -attrs.html : attrs.1 attrs types mkattrs.sh mktypes.sh - cat attrs.1 > attrs.html - ./mkattrs.sh < attrs >> attrs.html - ./mktypes.sh < types >> attrs.html +attrs.html : attrs.1 attrs types mkattrs.py mktypes.sh + cat attrs.1 > $@ + ./mkattrs.py < attrs >> $@ + ./mktypes.sh < types >> $@ colors.html : colors.1 colors.n ../../lib/common/color_names ../../lib/common/svgcolor_names ../../lib/common/brewer_colors mkcolors.awk brewer.awk svg.awk mkdir -p colortmp @@ -216,7 +216,7 @@ distclean : clean rm -f $(A2GIF) $(AGIF) $(SGIF) $(MPJG) $(MGIF) $(MPNG) $(XGIF) shapes (for s in $$(cat shapelist); do rm -f $$s.gif; done) -EXTRA_DIST = $(XGIF) mklang.y mkarrows.sh mkattrs.sh mkshapes.sh mkstyles.sh mktapers.sh \ +EXTRA_DIST = $(XGIF) mklang.y mkarrows.sh mkattrs.py mkshapes.sh mkstyles.sh mktapers.sh \ mktypes.sh mkarrowtbl.sh mkoutput.py mkshhtml.sh \ ps_to_png.sh arrow_grammar grammar html_grammar \ shapelist attrs.1 colors.1 colors.n \ diff --git a/doc/infosrc/attrs b/doc/infosrc/attrs index 13fd5d9cd..78695d75a 100644 --- a/doc/infosrc/attrs +++ b/doc/infosrc/attrs @@ -91,7 +91,7 @@ Style of arrowhead on the head node of an edge. This will only appear if the dir attribute is "forward" or "both". See the limitation. -:arrowsize (E_arrowsz):E:double:1.0:0.0; +:arrowsize:E:double:1.0:0.0; Multiplicative scale factor for arrowheads. :arrowtail:E:arrowType:normal; Style of arrowhead on the tail node of an edge. @@ -227,7 +227,7 @@ If true, use edge concentrators. This merges multiedges into a single edge and causes partially parallel edges to share part of their paths. The latter feature is not yet available outside of dot. -:constraint (E_constr):E:bool:true; dot +:constraint:E:bool:true; dot If false, the edge is not used in ranking the nodes. For example, in the graph
@@ -338,7 +338,7 @@ for setting the gradient angle.
 Note that a cluster inherits the root graph's attributes if defined.
 Thus, if the root graph has defined a fillcolor, this will override a
 color or bgcolor attribute set for the cluster.
-:fixedsize  (N_fixed):N:bool/string:false;
+:fixedsize:N:bool/string:false;
 If false, the size of a node is determined by smallest width and height
 needed to contain its label and image, if any, with a margin specified by
 the margin attribute. The width
@@ -596,7 +596,7 @@ If a node's shape is record, then the label can
 have a special format
 which describes the record layout.
 

-Note that a node's default label is "\\N", so the node's name or ID becomes +Note that a node's default label is "\N", so the node's name or ID becomes its label. Technically, a node's name can be an HTML string but this will not mean that the node's label will be interpreted as an HTML-like label. This is because the node's actual label is an ordinary string, which will be replaced @@ -623,7 +623,7 @@ Multiplicative scaling factor adjusting the distance that the headlabel(taillabel) is from the head(tail) node. The default distance is 10 points. See labelangle for more details. -:labelfloat (E_label_float):E:bool:false; +:labelfloat:E:bool:false; If true, allows edge labels to be less constrained in position. In particular, it may appear on top of other edges. :labelfontcolor:E:color:black; @@ -754,7 +754,7 @@ the cluster bounding box. By default, this is 8 points.

For nodes, this attribute specifies space left around the node's label. By default, the value is 0.11,0.055. -:maxiter:G:int:100 * # nodes(mode == KK)/200(mode == major)/30(mode == sgd)/600(fdp); neato,fdp +:maxiter:G:int:100 * # nodes(mode == KK)/200(mode == major)/30(mode == sgd)/600(fdp); neato,fdp Sets the number of iterations used. :mclimit:G:double:1.0; dot Multiplicative scale factor used to alter the MinQuit (default = 8) diff --git a/doc/infosrc/mkattrs.py b/doc/infosrc/mkattrs.py new file mode 100755 index 000000000..3d5b545ff --- /dev/null +++ b/doc/infosrc/mkattrs.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# Filter taking a list of attribute descriptions as stdin +# and producing a summary table, followed by a list of +# attribute descriptions. +# Uses `templates/attrs.html.j2` +# See `attrs` file for format documentation. + +from dataclasses import dataclass +import jinja2 +import markupsafe +import re +import sys +from typing import List, Dict + +@dataclass +class Term: + """ One

item. """ + name: str + # Anchor () for definition + d_anchor: str = "" + # Anchor () for table at the top + a_anchor: str = "" + +@dataclass +class Attribute: + terms: List[Term] + # use string : this is a string formed of G,N,C,E + uses: str + kinds: List[str] + flags: List[str] + html_description: str + defaults: List[str] + minimums: List[str] + +attrs : List[Attribute] = [] + +for line in sys.stdin: + # Skip comment lines. + if line.startswith('#'): + continue + + if line.startswith(':'): + # This is a header line. Grab out the values. + # :name:uses:kind[:dflt[:minv]]; [notes] + headers, _, flags = line.rpartition(';') + parts = headers.split(':') + + attr = Attribute( + terms=[Term(name=name) for name in parts[1].split('/')], + uses=parts[2], + kinds=parts[3].split('/'), + flags=[flag for flag in flags.strip().split(',') if flag], + # Set an empty string html description, ready to append to. + html_description='', + # Remaining fields are optional. + # First, check for default value: this has format :dflt1[/dflt2]* + defaults=parts[4].split('/') if len(parts) >= 5 else [], + # Check for minimum value: this has format /min1[/min2]* + minimums=parts[5].split('/') if len(parts) >= 6 else [], + ) + attrs.append(attr) + + else: + # This is an HTML line, possibly a continuation of a previous HTML line. + attr.html_description += ' ' + line + + +attrs.sort(key=lambda attr: ''.join(term.name for term in attr.terms)) + +for attr in attrs: + attr.html_description = markupsafe.Markup(attr.html_description) + +# The specification allows items with the same attribute name. +# This creates unique anchor keys, which are n copies of 'a' and 'd'. +a_anchors_used = set() +d_anchors_used = set() +for attr in attrs: + for term in attr.terms: + a_key = 'a' + d_key = 'd' + a_anchor = a_key + ':' + term.name + d_anchor = d_key + ':' + term.name + while a_anchor in a_anchors_used: + a_key += 'a' + a_anchor = a_key + ':' + term.name + while d_anchor in d_anchors_used: + d_key += 'd' + d_anchor = d_key + ':' + term.name + a_anchors_used.add(a_anchor) + d_anchors_used.add(d_anchor) + term.a_anchor = a_anchor + term.d_anchor = d_anchor + + +env = jinja2.Environment( + # Load template files from ./templates/ + loader=jinja2.FileSystemLoader('templates'), + # Auto-HTML-escape any html or xml files. + autoescape=jinja2.select_autoescape(['html', 'xml', 'html.j2', 'xml.j2']), + # Whitespace control + trim_blocks=True, + lstrip_blocks=True, + # Raise exception on any attempt to access undefined variables. + undefined=jinja2.StrictUndefined, +) +template = env.get_template('attrs.html.j2') +print(template.render(attrs=attrs)) diff --git a/doc/infosrc/mkattrs.sh b/doc/infosrc/mkattrs.sh deleted file mode 100755 index 39df45d93..000000000 --- a/doc/infosrc/mkattrs.sh +++ /dev/null @@ -1,344 +0,0 @@ -#! /bin/ksh -typeset -A uses kinds dflts minvs flags descs namecnt -typeset -i J L -name= -use= -kind= -dflt= -minv= -flag= - -# Filter taking a list of attribute descriptions as stdin -# and producing a summary table, followed by a list of -# attribute descriptions. - -set -f # Turn of globbing - -# Map special HTML characters into their HTML representation. -# This can be escaped using '\'. -protect () -{ - s= - L=${#1} - for (( J=0 ; J' ) - s=${s}'>' - ;; -# '&' ) -# s=${s}'&' -# ;; - '\' ) - if (( J == L-1 )) - then - s=${s}'\' - else - (( J++ )) - c=${1:J:1} - s=${s}$c - fi - ;; - * ) - s=${s}$c - ;; - esac - done - print -r -n -- $s -} - -# The specification allows items with the same attribute name. -# If there is more than one, the later ones are indexed by -# :, where each gets a distinct positive n. -# This function takes the index name, extracts the real name -# and stores it in realname, and creates the anchor keys, -# which are n copies of 'a' and 'd'. -function setRealnameNKeys -{ - if [[ $1 == *:* ]] - then - realname=${1%:*} - J=${1##*:} - else - realname=$1 - J=0 - fi - AKEY=a - DKEY=d - while (( J > 0 )) - do - AKEY=${AKEY}a - DKEY=${DKEY}d - (( J-- )) - done -} - -# Header has the format name:uses:kind[:dflt[:min]]; notes -function parseHdr -{ -# get flags to the right of ';' - flag="${1##*;}" - flag="${1##*;*( )}" - if [[ -n $flag ]] - then - flag=${flag//,/ } # change optional commas to spaces - fi - -# strip off flags to the right of ';' - opts="${1%;*}" - -# get name: this has the format name1[/name2]* notes - name=${opts%%:*} - rest=${opts#*:} - name=${name%% *} # strip off notes - -# there may be duplicate names with separate entries. -# Keep count of name uses, and modify name with :i. - J=${namecnt[$name]} - namecnt[$name]=$(( J+1 )) - if (( J > 0 )) - then - name=${name}:$J - fi - -# get use string : this is a string formed of G,N,C,E - use=${rest%%:*} - rest=${rest#${use}:} - -# get kind string: this has format kind1[/kind2]* - kind=${rest%%:*} - rest=${rest#${kind}} - -# Remaining fields are optional. -# First, check for default value: this has format :dflt1[/dflt2]* - if [[ -z "$rest" ]] - then - dflt= - minv= - return - fi - rest=${rest#:} -# If rest contains a ':' not preceded by a space, we take this to -# mean that a minval field is present, and split rest at that ':'. -# Everything preceding the ':' becomes the dflt. -# If there is no such colon (that is, there is no colon, or all -# colons are preceded by a space, we assume there is no minval, and -# use all of rest as dflt. -# This allows dflt to contain a ':' as long as it is preceded by a space. - if [[ $rest == *[![:space:]]:* ]] - then - dflt=${rest%:*} - rest=${rest#"${dflt}"} - else - dflt=${rest} - rest= - fi - -# Check for minimum value: this has format :min1[/min2]* - if [[ -z "$rest" ]] - then - minv= - return - fi - minv=${rest#:} -} - -OLDIFS="$IFS" -IFS= -while read line -do - c=${line:0:1} - if [[ $c == '#' ]] - then continue - elif [[ $c == ':' ]] - then - if [[ -n "$name" ]] - then - descs[$name]=$txt - txt="" - fi - line=${line#:} - parseHdr $line - uses[$name]="$use" - kinds[$name]="$kind" - dflts[$name]="$dflt" - minvs[$name]="$minv" - flags[$name]="$flag" - else - txt="$txt ${line}\n" - fi -done -IFS="$OLDIFS" - -if [[ -n "$name" ]] -then - descs[$name]=$txt - txt="" -fi - -#print ${!descs[@]} -#print ${uses[@]} -#print ${kinds[@]} -#print ${dflts[@]} -#print ${minvs[@]} -#print ${flags[@]} -#print ${descs[@]} -#exit - -print "" -print "" - -set -s ${!descs[@]} -for i -do - print -n " " - print -n "" - - printf "" "${uses[$i]}" - - print -n "" - - print -n "" - IFS="$OLDIFS" - - print -n "" - - print -n "" - print " " -done - -print "
NameUsed ByTypeDefaultMinimumNotes
" - setRealnameNKeys $i - first=yes - for n in ${realname//\// } - do - if [[ -n $first ]] - then - first= - else - print -n "
" - fi - printf "%s\n" $AKEY $n $DKEY $n $n - done - print -n "
%s"; - first=yes - kind=${kinds[$i]} - for n in ${kind//\// } - do - if [[ -n $first ]] - then - first= - else - print -n "
" - fi - case $n in - double ) - print -n "double" - ;; - int ) - print -n "int" - ;; - string ) - print -n "string" - ;; - bool ) - printf "bool\n" - ;; - * ) - printf "%s\n" $n $n - ;; - esac - done - print -n "
"; - first=yes - dflt=${dflts[$i]} - OLDIFS="$IFS" - IFS='/' - for n in ${dflt} - do - if [[ -n $first ]] - then - first= - else - print -n "
" - fi - n=$(protect $n) - print -r -n -- $n - done - print -n "
"; - first=yes - minv=${minvs[$i]} - OLDIFS="$IFS" - IFS='/' - for n in ${minv} - do - if [[ -n $first ]] - then - first= - else - print -n "
" - fi - n=$(protect $n) - print -n -- $n - done - IFS="$OLDIFS" - print -n "
" - flag=${flags[$i]} - case $flag in - "" ) - ;; - "notdot" ) - print -n "not dot" - ;; - * ) - set -A farray $flag - L=${#farray[@]} - for (( J = L-1 ; J >= 0 ; J-- )) - do - n=${farray[$J]} - if [[ $n == "ps" ]] - then - n=postscript - elif [[ $n == "bitmap" ]] - then - n="bitmap output" - fi - print -n $n - if (( J > 0 )) - then - print -n ', ' - fi - done - print -n " only" - ;; - esac - print -n "
" - -print "
" - -#set -s ${!descs[@]} -print "

Attribute Descriptions

\n
" -for i -do - setRealnameNKeys $i - - first=yes - for n in ${realname//\// } - do - if [[ -n $first ]] - then - first= - else - print -n "," - fi - printf "
%s\n" $DKEY $n $AKEY $n $n - done - print "
${descs[$i]}" -done -print "
\n
" - -exit 0 diff --git a/doc/infosrc/templates/attrs.html.j2 b/doc/infosrc/templates/attrs.html.j2 new file mode 100644 index 000000000..25dc26152 --- /dev/null +++ b/doc/infosrc/templates/attrs.html.j2 @@ -0,0 +1,68 @@ + + +{% for attr in attrs %} + +{% endfor %} +
NameUsed ByTypeDefaultMinimumNotes
+ {%- for term in attr.terms -%} + {%- if not loop.first -%} +
+ {%- endif -%} + {{ term.name }} + {% endfor -%} +
{{ attr.uses }} + {%- for kind in attr.kinds -%} + {%- if not loop.first -%} +
+ {%- endif -%} + {%- if kind in ['double', 'int', 'string'] -%} + {{ kind }} + {%- elif kind == 'bool' -%} + bool + {% else -%} + {{kind}} + {% endif -%} + {%- endfor -%} +
+ {%- for default in attr.defaults -%} + {%- if not loop.first -%} +
+ {%- endif -%} + {{ default }} + {%- endfor -%} +
+ {%- for minimum in attr.minimums -%} + {%- if not loop.first -%} +
+ {%- endif -%} + {{- minimum -}} + {%- endfor -%} +
+ {%- if attr.flags == [] -%} + {%- elif attr.flags == ['notdot'] -%} + not dot + {%- else -%} + {%- for flag in attr.flags | reverse -%} + {%- if flag == 'ps' -%} + postscript + {%- elif flag == 'bitmap' -%} + bitmap output + {%- else -%} + {{ flag }} + {%- endif -%} + {%- if not loop.last %}, {% endif -%} + {%- endfor %} only + {%- endif -%} +
+
+

Attribute Descriptions

+
+{% for attr in attrs %} + {% for term in attr.terms %} + {% if not loop.first %},{% endif %} +
{{ term.name }} + {% endfor %} +
{{ attr.html_description }} +{% endfor %} +
+
-- 2.50.1