Attachment 'Include.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - Include macro
   4 
   5     This macro includes the formatted content of the given page(s). See
   6 
   7         http://purl.net/wiki/moinmaster/HelpOnMacros/Include
   8 
   9     for detailed docs.
  10 
  11     @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
  12                 2000-2001 Richard Jones <richard@bizarsoftware.com.au>
  13     @license: GNU GPL, see COPYING for details.
  14 """
  15 
  16 #Dependencies = ["pages"] # included page
  17 Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks
  18 
  19 generates_headings = True
  20 
  21 import re, StringIO
  22 from MoinMoin import wikiutil
  23 from MoinMoin.Page import Page
  24 
  25 
  26 _sysmsg = '<p><strong class="%s">%s</strong></p>'
  27 
  28 ## keep in sync with TableOfContents macro!
  29 _arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
  30 _arg_level = r',\s*(?P<level>\d*)'
  31 _arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
  32 _arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
  33 _arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
  34 _arg_items = r'(,\s*items=(?P<items>\d+))?'
  35 _arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
  36 _arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
  37 _arg_editlink = r'(,\s*(?P<editlink>editlink))?'
  38 _args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
  39     _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
  40     _arg_skipitems, _arg_titlesonly, _arg_editlink)
  41 
  42 _title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
  43 
  44 def extract_titles(body, title_re):
  45     titles = []
  46     for title, _ in title_re.findall(body):
  47         h = title.strip()
  48         level = 1
  49         while h[level:level+1] == '=':
  50             level += 1
  51         title_text = h[level:-level].strip()
  52         titles.append((title_text, level))
  53     return titles
  54 
  55 def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M)):
  56     request = macro.request
  57     _ = request.getText
  58 
  59     # return immediately if getting links for the current page
  60     if request.mode_getpagelinks:
  61         return ''
  62 
  63     # parse and check arguments
  64     args = text and args_re.match(text)
  65     if not args:
  66         return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text, ))
  67 
  68     # prepare including page
  69     result = []
  70     print_mode = request.action in ("print", "format")
  71     this_page = macro.formatter.page
  72     if not hasattr(this_page, '_macroInclude_pagelist'):
  73         this_page._macroInclude_pagelist = {}
  74 
  75     # get list of pages to include
  76     inc_name = wikiutil.AbsPageName(this_page.page_name, args.group('name'))
  77     pagelist = [inc_name]
  78     if inc_name.startswith("^"):
  79         try:
  80             inc_match = re.compile(inc_name)
  81         except re.error:
  82             pass # treat as plain page name
  83         else:
  84             # Get user filtered readable page list
  85             pagelist = request.rootpage.getPageList(filter=inc_match.match)
  86 
  87     # sort and limit page list
  88     pagelist.sort()
  89     sort_dir = args.group('sort')
  90     if sort_dir == 'descending':
  91         pagelist.reverse()
  92     max_items = args.group('items')
  93     if max_items:
  94         pagelist = pagelist[:int(max_items)]
  95 
  96     skipitems = 0
  97     if args.group("skipitems"):
  98         skipitems = int(args.group("skipitems"))
  99     titlesonly = args.group('titlesonly')
 100     editlink = args.group('editlink')
 101 
 102     # iterate over pages
 103     for inc_name in pagelist:
 104         if not request.user.may.read(inc_name):
 105             continue
 106         if inc_name in this_page._macroInclude_pagelist:
 107             result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name, ))
 108             continue
 109         if skipitems:
 110             skipitems -= 1
 111             continue
 112         fmt = macro.formatter.__class__(request, is_included=True)
 113         fmt._base_depth = macro.formatter._base_depth
 114         inc_page = Page(request, inc_name, formatter=fmt)
 115         if not inc_page.exists():
 116             continue
 117         inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
 118 
 119         # check for "from" and "to" arguments (allowing partial includes)
 120         body = inc_page.get_raw_body() + '\n'
 121         from_pos = 0
 122         to_pos = -1
 123         from_re = args.group('from')
 124         if from_re:
 125             try:
 126                 from_match = re.compile(from_re, re.M).search(body)
 127             except re.error:
 128                 ##result.append("*** fe=%s ***" % e)
 129                 from_match = re.compile(re.escape(from_re), re.M).search(body)
 130             if from_match:
 131                 from_pos = from_match.end()
 132             # else:
 133             #    result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
 134         to_re = args.group('to')
 135         if to_re:
 136             try:
 137                 to_match = re.compile(to_re, re.M).search(body, from_pos)
 138             except re.error:
 139                 to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
 140             if to_match:
 141                 to_pos = to_match.start()
 142             # else:
 143             #    result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
 144 
 145         if titlesonly:
 146             levelstack = []
 147             for title, level in extract_titles(body[from_pos:to_pos], title_re):
 148                 if levelstack:
 149                     if level > levelstack[-1]:
 150                         result.append(macro.formatter.bullet_list(1))
 151                         levelstack.append(level)
 152                     else:
 153                         while levelstack and level < levelstack[-1]:
 154                             result.append(macro.formatter.bullet_list(0))
 155                             levelstack.pop()
 156                         if not levelstack or level != levelstack[-1]:
 157                             result.append(macro.formatter.bullet_list(1))
 158                             levelstack.append(level)
 159                 else:
 160                     result.append(macro.formatter.bullet_list(1))
 161                     levelstack.append(level)
 162                 result.append(macro.formatter.listitem(1))
 163                 result.append(inc_page.link_to(request, title))
 164                 result.append(macro.formatter.listitem(0))
 165             while levelstack:
 166                 result.append(macro.formatter.bullet_list(0))
 167                 levelstack.pop()
 168             continue
 169 
 170         if from_pos != 0 or to_pos != -1:
 171             inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
 172         elif from_re or to_re:
 173             inc_page.set_raw_body("", modified=True)
 174         else:
 175             inc_page.set_raw_body(body[:], modified=True)
 176         ##result.append("*** f=%s t=%s ***" % (from_re, to_re))
 177         ##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
 178  
 179         if not hasattr(request, "_Include_backto"):
 180             request._Include_backto = this_page.page_name
 181 
 182         # do headings
 183         level = None
 184         if args.group('heading') and args.group('hquote'):
 185             heading = args.group('htext') or inc_page.split_title()
 186             level = 1
 187             if args.group('level'):
 188                 level = int(args.group('level'))
 189             if print_mode:
 190                 result.append(macro.formatter.heading(1, level) +
 191                               macro.formatter.text(heading) +
 192                               macro.formatter.heading(0, level))
 193             else:
 194                 url = inc_page.url(request)
 195                 result.extend([
 196                     macro.formatter.heading(1, level, id=heading),
 197                     macro.formatter.url(1, url, css="include-heading-link"),
 198                     macro.formatter.text(heading),
 199                     macro.formatter.url(0),
 200                     macro.formatter.heading(0, level),
 201                 ])
 202 
 203         # set or increment include marker
 204         this_page._macroInclude_pagelist[inc_name] = \
 205             this_page._macroInclude_pagelist.get(inc_name, 0) + 1
 206 
 207         # output the included page
 208         strfile = StringIO.StringIO()
 209         request.redirect(strfile)
 210         try:
 211             inc_page.send_page(content_only=True,
 212                                omit_footnotes=True,
 213                                count_hit=False)
 214             result.append(strfile.getvalue())
 215         finally:
 216             request.redirect()
 217 
 218         # decrement or remove include marker
 219         if this_page._macroInclude_pagelist[inc_name] > 1:
 220             this_page._macroInclude_pagelist[inc_name] = \
 221                 this_page._macroInclude_pagelist[inc_name] - 1
 222         else:
 223             del this_page._macroInclude_pagelist[inc_name]
 224 
 225         # if no heading and not in print mode, then output a helper link
 226         if editlink and not (level or print_mode):
 227             if from_pos != 0 or to_pos != -1 or not (from_re or to_re):
 228                 result.extend([
 229                     macro.formatter.div(1, css_class="include-link"),
 230                     inc_page.link_to(request, '[%s]' % (inc_name, ), css_class="include-page-link"),
 231                     inc_page.link_to(request, '[%s]' % (_('edit'), ), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}),
 232                     macro.formatter.div(0),
 233                 ])
 234 
 235         # XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
 236 
 237     # return include text
 238     return ''.join(result)
 239 
 240 # vim:ts=4:sw=4:et

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2009-06-21 15:23:28, 9.2 KB) [[attachment:Include.py]]
  • [get | view] (2009-06-22 15:28:39, 9.2 KB) [[attachment:IncludeModified.py]]
  • [get | view] (2009-06-22 15:28:14, 8.9 KB) [[attachment:IncludeOriginal.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.