changeset 1099:07c23be08029

help: Add new help topics on routes.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 17 Feb 2018 11:53:03 -0800
parents 2323f0788170
children 1ce67d2fae0a
files piecrust/commands/base.py piecrust/commands/builtin/info.py piecrust/resources/helptopics/routes_routes_config.txt
diffstat 3 files changed, 103 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/commands/base.py	Sat Feb 17 11:52:31 2018 -0800
+++ b/piecrust/commands/base.py	Sat Feb 17 11:53:03 2018 -0800
@@ -1,6 +1,9 @@
+import os.path
 import logging
 import argparse
+import textwrap
 import functools
+from piecrust import RESOURCES_DIR
 from piecrust.pathutil import SiteNotFoundError
 
 
@@ -25,6 +28,9 @@
     def setupParser(self, parser, app):
         raise NotImplementedError()
 
+    def provideExtensions(self):
+        return None
+
     def run(self, ctx):
         raise NotImplementedError(
             "Command '%s' doesn't implement the `run` "
@@ -54,10 +60,18 @@
     def _loadExtensions(self, app):
         if self._extensions is not None:
             return
-        self._extensions = []
+
+        possible_exts = []
         for e in app.plugin_loader.getCommandExtensions():
-            if e.command_name == self.name and e.supports(app):
-                self._extensions.append(e)
+            possible_exts.append(e)
+        for c in app.plugin_loader.getCommands():
+            exts = c.provideExtensions()
+            if exts is not None:
+                possible_exts += exts
+
+        self._extensions = list(filter(
+            lambda e: e.command_name == self.name and e.supports(app),
+            possible_exts))
 
 
 class ChefCommandExtension(object):
@@ -139,3 +153,26 @@
 def get_func_command(f):
     return getattr(f, '__command_class__')
 
+
+def _get_help_topic_from_resources(command_name, topic):
+    path = os.path.join(RESOURCES_DIR, 'helptopics',
+                        '%s_%s.txt' % (command_name, topic))
+    with open(path, 'r', encoding='utf8') as fp:
+        lines = fp.readlines()
+
+    wrapped_lines = []
+    for ln in lines:
+        ln = ln.rstrip('\n')
+        if not ln:
+            wrapped_lines.append('')
+        else:
+            wrapped_lines += textwrap.wrap(ln, width=80)
+    return '\n'.join(wrapped_lines)
+
+
+class _ResourcesHelpTopics:
+    def getHelpTopic(self, topic, app):
+        category = self.__class__.__name__.lower()
+        if category.endswith('helptopic'):
+            category = category[:-len('helptopic')]
+        return _get_help_topic_from_resources(category, topic)
--- a/piecrust/commands/builtin/info.py	Sat Feb 17 11:52:31 2018 -0800
+++ b/piecrust/commands/builtin/info.py	Sat Feb 17 11:53:03 2018 -0800
@@ -1,6 +1,7 @@
 import os.path
 import logging
-from piecrust.commands.base import ChefCommand
+from piecrust.commands.base import (
+    ChefCommand, ChefCommandExtension, _ResourcesHelpTopics)
 
 
 logger = logging.getLogger(__name__)
@@ -81,6 +82,9 @@
     def setupParser(self, parser, app):
         pass
 
+    def provideExtensions(self):
+        return [RoutesHelpTopic()]
+
     def run(self, ctx):
         for route in ctx.app.routes:
             logger.info("%s:" % route.uri_pattern)
@@ -91,6 +95,50 @@
                 ', '.join(route.uri_params)))
 
 
+class RoutesHelpTopic(ChefCommandExtension, _ResourcesHelpTopics):
+    command_name = 'help'
+
+    def getHelpTopics(self):
+        return [('routes_config',
+                 "Specifying URL routes for your site's content."),
+                ('route_params',
+                 "Show the available route parameters.")]
+
+    def getHelpTopic(self, topic, app):
+        if topic != 'route_params':
+            return _ResourcesHelpTopics.getHelpTopic(self, topic, app)
+
+        import textwrap
+
+        help_txt = (
+            textwrap.fill(
+                "Route parameters can be used as placeholders when specifying "
+                "route URL patterns in your site configuration. See "
+                "`chef help routes_config` for more information.") +
+            "\n\n")
+        if app.root_dir is None:
+            help_txt += textwrap.fill(
+                "Running this help command in a PieCrust website would show "
+                "the route parameters available for your site's sources. "
+                "However, no PieCrust website has been found in the current "
+                "working directory. ")
+            return help_txt
+
+        srcs_by_types = {}
+        for src in app.sources:
+            srcs_by_types.setdefault(src.SOURCE_NAME, []).append(src)
+
+        for type_name, srcs in srcs_by_types.items():
+            help_txt += textwrap.fill(
+                "Route parameters for '%s' sources (%s):" % (
+                    type_name, ', '.join([s.name for s in srcs])))
+            help_txt += "\n"
+            for rp in srcs[0].getSupportedRouteParameters():
+                help_txt += " - %s\n" % rp.param_name
+            help_txt += "\n"
+        return help_txt
+
+
 class ShowPathsCommand(ChefCommand):
     def __init__(self):
         super(ShowPathsCommand, self).__init__()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piecrust/resources/helptopics/routes_routes_config.txt	Sat Feb 17 11:53:03 2018 -0800
@@ -0,0 +1,14 @@
+Routes are specified in the `site/routes` configuration section of your website. This should be a list, where each item is a mapping with the following entries:
+
+url: The URL pattern for the route.
+source: The name of the source this route is for.
+func (optional): The name of a templating function you can use to generate URLs for this route.
+
+The URL pattern typically includes placeholders for information obtained by the source, like a blog post's date and slug. For example:
+
+site:
+  routes:
+    - url: /myblog/%year%/%month%/%slug%
+      source: posts
+
+To know which placeholders are available, see `chef help route_params`.