1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/actions/SectionBreakout.py Sun Feb 20 21:15:05 2011 +0100
1.3 @@ -0,0 +1,191 @@
1.4 +# -*- coding: iso-8859-1 -*-
1.5 +"""
1.6 + MoinMoin - SectionBreakout
1.7 +
1.8 + Break sections out of a page, making new pages for each of the sections and
1.9 + replacing them with Include macros.
1.10 +
1.11 + @copyright: 2011 Paul Boddie <paul@boddie.org.uk>
1.12 + @license: GNU GPL, see COPYING for details.
1.13 +"""
1.14 +
1.15 +Dependencies = ['pages']
1.16 +
1.17 +from MoinMoin.action import ActionBase
1.18 +from MoinMoin.PageEditor import PageEditor
1.19 +from MoinContentSupport import ActionSupport, getHeadingDetails, escape, escattr
1.20 +import re
1.21 +
1.22 +# Action class and supporting functions.
1.23 +
1.24 +class SectionBreakout(ActionBase, ActionSupport):
1.25 +
1.26 + "An action breaking sections out of pages."
1.27 +
1.28 + def get_form_html(self, buttons_html):
1.29 + _ = self._
1.30 + request = self.request
1.31 + page = self.page
1.32 + form = self.get_form()
1.33 +
1.34 + level = int(form.get("level", ["2"])[0])
1.35 +
1.36 + # Acquire heading details from the page.
1.37 +
1.38 + body = page.get_raw_body()
1.39 + heading_details = getHeadingDetails(body, level, level)
1.40 +
1.41 + d = {
1.42 + "buttons_html" : buttons_html,
1.43 + "heading_level_label" : escape(_("Heading level")),
1.44 + "found_headings_label" : escape(_("Headings found in page")),
1.45 + "preview_label" : escape(_("Preview")),
1.46 + "level" : escattr(level),
1.47 + }
1.48 +
1.49 + html = u'''
1.50 + <table>
1.51 + <tr>
1.52 + <td class="label">%(heading_level_label)s</td>
1.53 + <td><input type="text" name="level" value="%(level)s" size="2" /></td>
1.54 + </tr>
1.55 + <tr>
1.56 + <td class="label">%(found_headings_label)s</td>
1.57 + <td>''' % d
1.58 +
1.59 + for heading, level, span in heading_details:
1.60 + html += "%s<br />" % heading
1.61 +
1.62 + html += '''
1.63 + </td>
1.64 + </tr>
1.65 + <tr>
1.66 + <td></td>
1.67 + <td class="buttons"><input type="submit" value="%(preview_label)s" />%(buttons_html)s</td>
1.68 + </tr>
1.69 + </table>
1.70 +''' % d
1.71 +
1.72 + return html
1.73 +
1.74 + def do_action(self):
1.75 +
1.76 + "Create the new event."
1.77 +
1.78 + _ = self._
1.79 + form = self.get_form()
1.80 +
1.81 + # A heading level must be provided.
1.82 +
1.83 + level = form.get("level", [None])[0]
1.84 +
1.85 + if not level:
1.86 + return 0, _("No heading level specified.")
1.87 +
1.88 + return self.break_out_headings(int(level))
1.89 +
1.90 + def render_success(self, msg, msgtype=None):
1.91 +
1.92 + """
1.93 + Render neither 'msg' nor 'msgtype' since redirection should occur
1.94 + instead.
1.95 + NOTE: msgtype is optional because MoinMoin 1.5.x does not support it.
1.96 + """
1.97 +
1.98 + pass
1.99 +
1.100 + def break_out_headings(self, level):
1.101 +
1.102 + """
1.103 + Break out headings at the given 'level' from the current page.
1.104 + """
1.105 +
1.106 + _ = self._
1.107 + request = self.request
1.108 + page = self.page
1.109 + formatter = request.formatter
1.110 +
1.111 + # Acquire all heading details from the page.
1.112 +
1.113 + page_body = page.get_raw_body()
1.114 + regions = []
1.115 + current_region_start = None
1.116 +
1.117 + for heading, found_level, (start, end) in getHeadingDetails(page_body):
1.118 +
1.119 + # Upon finding a suitable heading, begin a new region to be broken
1.120 + # out.
1.121 +
1.122 + if current_region_start is None and found_level >= level:
1.123 + current_region_start = heading, start
1.124 +
1.125 + # Upon finding a higher-level heading, end any open region.
1.126 +
1.127 + elif current_region_start is not None and found_level <= level:
1.128 + regions.append(current_region_start + (start,))
1.129 +
1.130 + # For headings at the requested level, open a new region.
1.131 +
1.132 + if found_level == level:
1.133 + current_region_start = heading, start
1.134 + else:
1.135 + current_region_start = None
1.136 +
1.137 + # End any open region.
1.138 +
1.139 + else:
1.140 + if current_region_start is not None:
1.141 + regions.append(current_region_start + (len(page_body),))
1.142 +
1.143 + # Make new pages for each region, rebuilding the current page body.
1.144 +
1.145 + retained_regions = []
1.146 + retained_region_start = 0
1.147 +
1.148 + for heading, start, end in regions:
1.149 +
1.150 + # Combine the page name and the heading to make a subpage.
1.151 +
1.152 + new_page_name = "%s/%s" % (page.page_name, heading)
1.153 +
1.154 + # Open the page for editing.
1.155 +
1.156 + new_page = PageEditor(request, new_page_name)
1.157 +
1.158 + # Save the new version of the page.
1.159 +
1.160 + new_page.saveText(page_body[start:end], 0)
1.161 +
1.162 + # Retain the preceding region for the current page.
1.163 +
1.164 + retained_regions.append(page_body[retained_region_start:start])
1.165 +
1.166 + # Insert Include macros for the broken out text.
1.167 +
1.168 + retained_regions.append("<<Include(%s,,editlink)>>\n" % new_page_name)
1.169 +
1.170 + # Start a new region to retain.
1.171 +
1.172 + retained_region_start = end
1.173 +
1.174 + # Retain any remaining text.
1.175 +
1.176 + else:
1.177 + retained_regions.append(page_body[retained_region_start:])
1.178 +
1.179 + # Edit the current page.
1.180 +
1.181 + edited_page = PageEditor(request, page.page_name)
1.182 + edited_page.saveText("".join(retained_regions), 0)
1.183 +
1.184 + # NOTE: Perhaps show a message upon failure.
1.185 +
1.186 + request.http_redirect(page.url(request))
1.187 + return 1, None
1.188 +
1.189 +# Action function.
1.190 +
1.191 +def execute(pagename, request):
1.192 + SectionBreakout(pagename, request).render()
1.193 +
1.194 +# vim: tabstop=4 expandtab shiftwidth=4