1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
6
from zope.interface import Interface, Attribute
8
from twisted.lore import process, indexer, numberer, htmlbook
10
from twisted.python import usage, reflect
11
from twisted import plugin as plugin
13
class IProcessor(Interface):
17
name = Attribute("The user-facing name of this processor")
19
moduleName = Attribute(
20
"The fully qualified Python name of the object defining "
21
"this processor. This object (typically a module) should "
22
"have a C{factory} attribute with C{generate_<output>} methods.")
25
class Options(usage.Options):
27
longdesc = "lore converts documentation formats."
29
optFlags = [["plain", 'p', "Report filenames without progress bar"],
30
["null", 'n', "Do not report filenames"],
31
["number", 'N', "Add chapter/section numbers to section headings"],
35
["input", "i", 'lore'],
36
["inputext", "e", ".xhtml", "The extension that your Lore input files have"],
37
["docsdir", "d", None],
39
["output", "o", 'html'],
40
["index", "x", None, "The base filename you want to give your index file"],
41
["book", "b", None, "The book file to generate a book from"],
42
["prefixurl", None, "", "The prefix to stick on to relative links; only useful when processing directories"],
45
#zsh_altArgDescr = {"foo":"use this description for foo instead"}
46
#zsh_multiUse = ["foo", "bar"]
47
#zsh_mutuallyExclusive = [("foo", "bar"), ("bar", "baz")]
48
#zsh_actions = {"foo":'_files -g "*.foo"', "bar":"(one two three)"}
49
#zsh_actionDescr = {"logfile":"log file name", "random":"random seed"}
50
zsh_extras = ["*:files:_files"]
52
def __init__(self, *args, **kw):
53
usage.Options.__init__(self, *args, **kw)
56
def opt_config(self, s):
58
k, v = s.split('=', 1)
63
def parseArgs(self, *files):
67
def getProcessor(input, output, config):
68
plugins = plugin.getPlugins(IProcessor)
70
if plug.name == input:
71
module = reflect.namedModule(plug.moduleName)
74
# try treating it as a module name
76
module = reflect.namedModule(input)
78
print '%s: no such input: %s' % (sys.argv[0], input)
81
return process.getProcessor(module, output, config)
82
except process.NoProcessorError, e:
83
print "%s: %s" % (sys.argv[0], e)
86
def getWalker(df, opt):
87
klass = process.Walker
89
klass = process.PlainReportingWalker
91
klass = process.NullReportingWalker
92
return klass(df, opt['inputext'], opt['linkrel'])
95
def runGivenOptions(opt):
96
"""Do everything but parse the options; useful for testing.
97
Returns a descriptive string if there's an error."""
101
book = htmlbook.Book(opt['book'])
103
df = getProcessor(opt['input'], opt['output'], opt.config)
105
return 'getProcessor() failed'
107
walker = getWalker(df, opt)
110
for filename in opt['files']:
111
walker.walked.append(('', filename))
113
for filename in book.getFiles():
114
walker.walked.append(('', filename))
116
walker.walkdir(opt['docsdir'] or '.', opt['prefixurl'])
119
indexFilename = opt['index']
121
indexFilename = book.getIndexFilename()
126
indexer.setIndexFilename("%s.%s" % (indexFilename, opt['output']))
128
indexer.setIndexFilename(None)
130
## TODO: get numberSections from book, if any
131
numberer.setNumberSections(opt['number'])
136
for (file, errors) in walker.failures:
138
print "%s:%s" % (file, error)
139
return 'Walker failures'
146
except usage.UsageError, errortext:
147
print '%s: %s' % (sys.argv[0], errortext)
148
print '%s: Try --help for usage details.' % sys.argv[0]
151
result = runGivenOptions(opt)
157
if __name__ == '__main__':