1 """
2 MoinMoin macro to specify columns
3 Columns.py
4 ark 06/14/04 0.1
5
6 ***********
7 by Antti Kuntsi <antti@kuntsi.com>
8
9 As far as the author is concerned, this code is released to the public
10 domain, but some restrictions in the MoinMoin COPYING file may apply. Ask a
11 lawyer.
12 ***********
13 This code has not been tested exhaustively. Use at your own risk.
14 ***********
15
16 This macro generates containers, that can be used with CSS to create
17 columns.
18
19 Usage:
20 [[Columns(mode,name,keywordargs)]]
21
22 mode start, next or end.
23
24 name Name of the div id. <div id="name">
25
26 keywordargs Zero or more key="value" arguments for the HTML div
27 tag.
28
29 Examples:
30
31 [[Columns(start, leftcolumn)]]
32 This text is in the left column.
33 [[Columns(next, rightcolumn)]]
34 This text is in the right column.
35 [[Columns(end)]]
36
37 requires class definitions in CSS for the used column names, eg
38
39 #leftcolumn {
40 position: relative;
41 background: transparent;
42 float: left;
43 width: 45%;
44 border-right: 1px solid gray;
45 padding-left: 5%;
46 padding-right: 1%;
47 margin: 0px;
48 }
49
50 #rightcolumn {
51 position: relative;
52 background: transparent;
53 float: right;
54 width: 42%;
55 padding-right: 1%;
56 margin: 0px;
57 }
58
59
60 Demo. Try pasting the above examples into a MoinMoin sandbox page and the
61 current CSS.
62
63
64 """
65
66
67 import string
68 from MoinMoin import wikiutil, config
69
70
71 DEFAULT_KEYWORD_ARGS = {}
72
73 def execute(macro, args):
74 '''handle the Columns Macro. return the generated display HTML'''
75
76 if args==None:
77 args = ''
78 parseargs = _parse_arguments(args, ',', '"')
79
80 if len(parseargs)<1:
81 return '<p><strong class="error">Columns macro must have at least one argument!</strong></p>'
82 if parseargs[0] not in ("start", "next", "end"):
83 return '<p><strong class="error">Unknown mode "<i>%s</i>"!</strong></p>'%(parseargs[0])
84 mode = parseargs[0]
85
86 if mode != "end":
87 classname = parseargs[1].strip()
88 else:
89 classname=""
90 kwargs = _parse_keyword_arguments(parseargs[2:], DEFAULT_KEYWORD_ARGS)
91
92 kwstring = ''
93 for key in kwargs.keys():
94 kwstring = '%s %s="%s"'%(kwstring, key, kwargs[key])
95
96 divtag=""
97 if mode in ("end", "next"):
98 divtag += '</div>'
99 if mode == "end":
100 divtag += '<br clear="both">'
101 if mode in ("start", "next"):
102 divtag += '<div id="%s"%s>'%(classname, kwstring)
103
104 result=[macro.formatter.paragraph(0),
105 macro.formatter.rawHTML(divtag),
106 macro.formatter.paragraph(1)
107 ]
108
109 return "".join(result)
110
111
112 def _parse_arguments(argstring, delimchar=',', quotechar='"'):
113 '''parse argstring into separate arguments originally separated by delimchar.
114 occurrences of delimchar found within quotechars are ignored.
115 This parser is not particularly elegant. Improvements are welcome.
116 jjk 03/28/01'''
117
118 delim2 = chr(0)
119 inquote = 0
120 for i1 in range(len(argstring)):
121 cchar = argstring[i1]
122 if cchar==quotechar:
123 inquote = not inquote
124 elif (not inquote) and cchar==delimchar:
125 argstring = argstring[:i1] + delim2 + argstring[i1+1:]
126
127 args = string.split(argstring, delim2)
128 for i1 in range(len(args)):
129 arg = args[i1]
130 if arg[:1]==quotechar and arg[-1:]==quotechar:
131 args[i1] = arg[1:-1]
132 return args
133
134
135 def _parse_keyword_arguments(raw_kw_args=[], default={}):
136 '''given a list of 'key=value' and/or 'key="value"',
137 answer a dictionary of {key:value}
138 jjk 03/28/01'''
139 kwargs = {}
140 kwargs.update(default)
141 for keyvalstr in raw_kw_args:
142 keyval = string.split(keyvalstr, '=')
143 if len(keyval)==0:
144 continue
145 elif len(keyval)==1:
146 key = keyval[0]
147 value = ''
148 elif len(keyval)==2:
149 key = keyval[0]
150 value = keyval[1]
151 elif len(keyval)>2:
152 key = keyval[0]
153 value = string.join(keyval[1:],'=')
154 if value[:1]=='"':
155 value = value[1:]
156 if value[-1:]=='"':
157 value = value[:-1]
158 kwargs[string.lower(key)] = value
159 return kwargs
160
161
162 def _is_URL(aString):
163 '''answer true if aString is a URL.
164 The method used here is pretty dumb. Improvements are welcome.
165 jjk 03/28/01'''
166 return string.find(aString, '://')>0