# Add a dropdown select list for NewPage macro to support multiple template selection.
# Pass categories to NewPage macro, and categories append at the end of new page.

diff -r 6419f0986299 MoinMoin/PageEditor.py
--- a/MoinMoin/PageEditor.py	Fri Nov 21 23:12:33 2008 +0800
+++ b/MoinMoin/PageEditor.py	Sat Nov 22 15:07:55 2008 +0800
@@ -20,6 +20,7 @@
 
 
 from MoinMoin import caching, config, wikiutil, error
+from MoinMoin import wikiutil2
 from MoinMoin.Page import Page
 from MoinMoin.widget import html
 from MoinMoin.widget.dialog import Status
@@ -426,6 +427,9 @@
         lang = self.pi.get('language', request.cfg.language_default)
 
         request.write("<p>")
+        category = form.get('category',[None])[0] or kw.get('category', None)
+        if category:
+            raw_body = wikiutil2.append_category(request, raw_body, category)
         request.write(
             u'''\
 <textarea id="editor-textarea" name="savetext" lang="%(lang)s" dir="%(dir)s" rows="%(rows)d" cols="80"
diff -r 6419f0986299 MoinMoin/action/edit.py
--- a/MoinMoin/action/edit.py	Fri Nov 21 23:12:33 2008 +0800
+++ b/MoinMoin/action/edit.py	Sat Nov 22 15:07:55 2008 +0800
@@ -8,7 +8,7 @@
                 2006 MoinMoin:ThomasWaldmann
     @license: GNU GPL, see COPYING for details.
 """
-from MoinMoin import wikiutil
+from MoinMoin import wikiutil, wikiutil2
 from MoinMoin.Page import Page
 
 def execute(pagename, request):
@@ -122,30 +122,7 @@
     # markup.
 
     if category and category != _('<No addition>'): # opera 8.5 needs this
-        # strip trailing whitespace
-        savetext = savetext.rstrip()
-
-        # Add category separator if last non-empty line contains
-        # non-categories.
-        lines = [line for line in savetext.splitlines() if line]
-        if lines:
-
-            import re
-            p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
-            p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
-            categories = map( lambda x: p_strip.search(x).groups()[0],
-                              p_split.findall(lines[-1]))
-
-            if categories:
-                confirmed = wikiutil.filterCategoryPages(request, categories)
-                if len(confirmed) < len(categories):
-                    # This was not a categories line, add separator
-                    savetext += u'\n----\n'
-
-        # Add new category
-        if savetext and savetext[-1] != u'\n':
-            savetext += ' '
-        savetext += category + u'\n' # Should end with newline!
+        savetext = wikiutil2.append_category(request, savetext, category)
 
     # Preview, spellcheck or spellcheck add new words
     if ('button_preview' in request.form or
diff -r 6419f0986299 MoinMoin/action/newpage.py
--- a/MoinMoin/action/newpage.py	Fri Nov 21 23:12:33 2008 +0800
+++ b/MoinMoin/action/newpage.py	Sat Nov 22 15:07:55 2008 +0800
@@ -22,7 +22,51 @@
         self.pagename = self.request.form.get('pagename', [None])[0]
         self.nametemplate = self.request.form.get('nametemplate', ['%s'])[0]
         self.nametemplate = self.nametemplate.replace('\x00', '')
+        self.parent = self.request.form.get('parent', [''])[0]
+        self.template = self.request.form.get('template', [''])[0]
+        self.category = self.request.form.get('category', [None])[0]
+        if ',' in self.template:
+            arg_kw = self.parse_combined_template(self.template)
+            self.template = arg_kw.get('template', "")
+            self.parent = arg_kw.get('parent') or self.parent
+            self.nametemplate = arg_kw.get('nametemplate') or self.nametemplate
+            category = arg_kw.get('category', "")
+            if self.category and category:
+                self.category = ','.join([self.category, category])
+            else:
+                self.category = self.category or category
 
+    def parse_combined_template(self, template):
+        kw = {'template':'',
+              'parent':'',
+              'nametemplate':'',
+              'category':'',
+              }
+        if template and ',' in template:
+            for item in template.split(','):
+                item = item.strip()
+                # check if item is template
+                if not kw['template'] and self.request.cfg.cache.page_template_regex.search(item):
+                    kw['template'] = item 
+                # check if item is category
+                elif self.request.cfg.cache.page_category_regexact.search(item):
+                    if kw['category']:
+                        kw['category'] = ','.join([kw['category'], item])
+                    else:
+                        kw['category'] = item
+                # then item is parent or nametemplate
+                elif not kw['parent']:
+                    kw['parent'] = item
+                elif not kw['nametemplate']:
+                    kw['nametemplate'] = item
+                else:
+                    # ignore bad parameters
+                    pass
+        else:
+            kw['template'] = template
+        
+        return kw
+        
     def checkAndCombineArguments(self):
         """ Check arguments in form, return error msg
 
@@ -82,13 +126,14 @@
             pagename = self.pagename
             query = {'action': 'edit', 'backto': self.referrer}
 
-            template = self.request.form.get('template', [''])[0]
-            if template:
-                query['template'] = template
+            if self.template:
+                query['template'] = self.template
+            
+            if self.category:
+                query['category'] = self.category
 
-            parent = self.request.form.get('parent', [''])[0]
-            if parent:
-                pagename = "%s/%s" % (parent, pagename)
+            if self.parent:
+                pagename = "%s/%s" % (self.parent, pagename)
 
             url = Page(self.request, pagename).url(self.request, query)
             self.request.http_redirect(url)
diff -r 6419f0986299 MoinMoin/macro/NewPage.py
--- a/MoinMoin/macro/NewPage.py	Fri Nov 21 23:12:33 2008 +0800
+++ b/MoinMoin/macro/NewPage.py	Sat Nov 22 15:07:55 2008 +0800
@@ -25,7 +25,7 @@
 
     Usage:
 
-        <<NewPage(template, buttonLabel, parentPage)>>
+        <<NewPage(template, buttonLabel, parentPage, name_template=u"%s", type=u"select", layout=u"", category=u"")>>
 
     Examples:
 
@@ -39,14 +39,37 @@
             Create an input field with button labeled 'Create New
             Bug'.  The new page will use the BugTemplate template,
             and create the page as a subpage of MoinMoinBugs.
+
+        <<NewPage({u"AbcTemplate":u"Abc",u"XyzTemplate":u"Xyz"},
+            Create,Meetings,%Y-%m-%d_%s, category=u"CategoryX,CategoryY")>>
+
+            User can choose template from a drop down select box.
+            New page name will have the date at the beginning.
+            CategoryX and CategoryY will append at the end of the page.
+
+        <<NewPage({u"AbcTemplate,CategoryX":u"Abc",u"XyzTemplate,CategoryY":u"Xyz",u"XyzTemplate,CategoryY,CategoryZ":u"Xyz2"},
+            Create,Meetings,%Y-%m-%d_%s)>>
+
+            User can choose template from a drop down select box.
+            New page name will have the date at the beginning.
+            CategoryX, CategoryY, or CategoryZ will append at the end of the page.
     """
 
     def __init__(self, macro, template=u'', button_label=u'',
-                 parent_page=u'', name_template=u'%s'):
+                 parent_page=u'', name_template=u'%s', type=u'select', layout=u'', category=u''):
         self.macro = macro
         self.request = macro.request
         self.formatter = macro.formatter
-        self.template = template
+        if isinstance(template, dict):
+            self.template = []
+            for k,v in template.iteritems():
+                self.template.append([v,k])
+            self.template = sorted(self.template)
+            self.template = [ (item[1], item[0]) for item in self.template ]
+        else:
+            self.template = template
+        self.type = type
+        self.layout = layout
         _ = self.request.getText
         if button_label:
             # Try to get a translation, this will probably not work in
@@ -66,6 +89,7 @@
         else:
             self.parent = parent_page
         self.nametemplate = name_template
+        self.category = category
 
     def renderInPage(self):
         """ Render macro in page context
@@ -77,7 +101,16 @@
         _ = self.request.getText
 
         requires_input = '%s' in self.nametemplate
-
+        if not self.layout:
+            self.layout = """
+<table class="borderless">
+  <tr>
+    <td>""" + _("Input title: ") + """</td><td>%(input)s</td></tr>
+  <tr>
+    <td>""" + _("Select template: ") + """</td><td>%(select)s</td></tr>
+  <tr><td colspan="2" align="right">%(button)s</td></tr>
+</table>
+"""
 
         # TODO: better abstract this using the formatter
         # OSSXP: self.request.page.page_name and self.formatter.page.page_name may different, 
@@ -91,26 +124,82 @@
                 except:
                     self.parent = self.formatter.page.page_name
             
-        html = [
+        header = [
             u'<form class="macro" method="POST" action="%s/%s"><div>' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.formatter.page.page_name)),
             u'<input type="hidden" name="action" value="newpage">',
             u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(self.parent, 1),
-            u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1),
+            u'<input type="hidden" name="category" value="%s">' % wikiutil.escape(self.category, 1),
             u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(self.nametemplate, 1),
         ]
+        header = '\n'.join(header)
+        footer = u'</div></form>'
+        button = u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1)
+        
+        select = u''
+        if self.template:
+            if isinstance(self.template, basestring):
+                select = u''
+                header += u'\n<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1)
+            elif isinstance(self.template, (list,tuple)):
+                select = []
+                if self.type == "select":
+                    select.append(u'<select name="template" size="0">')
+                for item in self.template:
+                    if isinstance(item, basestring):
+                        k=item
+                        v=item
+                    else:
+                        k=item[0]
+                        v=item[1]
+                    if self.type == "select":
+                        select.append(u'<option value="%(key)s" label="%(value)s">%(value)s</option>' % \
+                                      {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
+                    else: # type == radio
+                        select.append(u'<input type="radio" name="template" value="%(key)s">%(value)s' % \
+                                      {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
+                if self.type == "select":
+                    select.append(u'</select>')
+                select = '\n'.join(select)
+        if requires_input:
+            input = u'<input type="text" name="pagename" size="30">'
+        else:
+            input = u''
+        
+        if input and select and self.layout:
+            html = '\n'.join([header,
+                              self.layout % {'button': button, 'select':select, 'input':input},
+                              footer])
+        else:
+            html = '\n'.join([header, select, input, button,footer])
 
-        if requires_input:
-            html += [
-                u'<input type="text" name="pagename" size="30">',
-            ]
-        html += [
-            u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1),
-            u'</div></form>',
-            ]
-        return self.formatter.rawHTML('\n'.join(html))
+        return self.formatter.rawHTML(html)
 
-def macro_NewPage(macro, template=u'', button_label=u'',
-                  parent_page=u'', name_template=u'%s'):
+
+def execute(macro, args):
     """ Temporary glue code to use with moin current macro system """
-    return NewPage(macro, template, button_label, parent_page, name_template).renderInPage()
+    request = macro.request
+    import re
+    pattern = re.compile(ur"""
+^(?P<template>
+      \[.*?\] # list
+    |
+      \(.*?\) # tuple
+    |
+      \{.*?\} # dict
+    |
+      (?P<mark>"').*?(?P=mark) # string with mark
+    |
+      [^,]* # string without mark
+),?(?P<args>.*)$    # others arguments
+""", re.UNICODE|re.VERBOSE)
+    template = ""
+    if args:
+        match = pattern.search(args)
+        if match:
+            template = match.group('template')
+            args = match.group('args')
+            if template:
+                if template[0] in '[({\'"':
+                    template = eval(template)
 
+    return wikiutil.invoke_extension_function(request, NewPage, args, fixed_args=[macro, template]).renderInPage()
diff -r 6419f0986299 MoinMoin/wikiutil2.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/wikiutil2.py	Sat Nov 22 15:07:55 2008 +0800
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+    MoinMoin - Wiki Extra Utility Functions
+
+    @copyright: 2008 Jiang Xin <worldhello.net@gmail.com>
+    @license: GNU GPL, see COPYING for details.
+"""
+
+import re
+from MoinMoin import wikiutil
+
+from MoinMoin import log
+logging = log.getLogger(__name__)
+
+
+def append_category(request, raw_body, category):
+    """
+    Append category at the end of raw_body
+    """
+    _ = request.getText
+    
+    # user can input multiple categories, separate by ';'
+    categorylist = []
+
+    if isinstance(category, (list,tuple)):
+        categorylist = category
+    elif isinstance(category, basestring):
+        for cat in category.split(','):
+            if cat.startswith("[["):
+                cat = cat[2:-2]
+            if request.cfg.cache.page_category_regexact.search(cat):
+                if cat not in categorylist:
+                    categorylist.append(cat)
+
+    # no valid category, return raw_body
+    if not categorylist or not raw_body:
+        return raw_body
+
+    # strip trailing whitespace
+    raw_body = raw_body.rstrip()
+
+    lines = [line for line in raw_body.splitlines() if line]
+    p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
+    p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
+    categories = map( lambda x: p_strip.search(x).groups()[0],
+                      p_split.findall(lines[-1]))
+    if categories:
+        confirmed = wikiutil.filterCategoryPages(request, categories)
+        if len(confirmed) < len(categories):
+            # This was not a categories line, add separator
+            categories = []
+
+    # Add category separator if last non-empty line contains non-categories.
+    if not categories:
+        raw_body += u'\n\n----\n'
+    
+    for cat in categorylist:
+        if cat not in categories:
+            # Add new category
+            if raw_body and raw_body[-1] != u'\n':
+                raw_body += ' '
+            raw_body += wikiutil.pagelinkmarkup(cat)
+
+    if raw_body and raw_body[-1] != u'\n':
+        raw_body += u'\n' # Should end with newline!
+
+    return raw_body
+
