diff --git a/docs/3rdparty.rst b/docs/3rdparty.rst deleted file mode 100644 index 351f41699..000000000 --- a/docs/3rdparty.rst +++ /dev/null @@ -1,12 +0,0 @@ -###################### -Complete Scripts Index -###################### - -This is the complete index of documentation pulled from script source files. - -.. toctree:: - :glob: - :maxdepth: 2 - - /scripts/**include-all - diff --git a/docs/Scripts.rst b/docs/Scripts.rst index 2eecf2562..0e072e48f 100644 --- a/docs/Scripts.rst +++ b/docs/Scripts.rst @@ -15,35 +15,27 @@ or from the init file. only be interrupted every 256 instructions. Use ``kill-lua force`` to interrupt the next instruction. -Here's an index to documentation pulled from script source files: - -.. toctree:: - :glob: - :maxdepth: 2 - - /docs/3rdparty/ - - Here's the contents page for this document: .. contents:: -================= -3rd-party scripts -================= -This listing is autogenerated from ``.rst`` files in the 3rdparty scripts directory. +The following pages document all the standard DFHack scripts. -.. warning:: +.. toctree:: + :glob: + :maxdepth: 2 + + /docs/_auto/* - Because this documentation is pulled in from external sources, - it may not match the DFHack distribution exactly. - * Some scripts should have a prefix (eg listed as ``myscript``, - should be ``gui/myscript``) but don't. - * Some sections of documentation may refer to scripts which are - not distributed with DFHack. +.. warning:: + The following documentation is pulled in from external ``README`` files. + + - it may not match the DFHack docs style + - some scripts have incorrect names, or are documented but unavailable + - some scripts have entries here and are also included above .. toctree:: :glob: diff --git a/docs/conf.py b/docs/conf.py index ea7305c95..61095a7c9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,41 +18,71 @@ from io import open import os import shlex import sys +import shutil + + +def doc_dir(dirname, files): + """Yield (command, includepath) for each script in the directory.""" + sdir = os.path.relpath(dirname, '..').replace('\\', '/').replace('../', '') + for f in files: + if f[-3:] not in {'lua', '.rb'}: + continue + with open(os.path.join(dirname, f), 'r', encoding='utf8') as fstream: + text = [l.rstrip() for l in fstream.readlines() if l.strip()] + command = None + for line in text: + if line == len(line) * '=': + if command is not None: + yield command, sdir + '/' + f + break + command = line + # later, print an error for missing docs here + + +def document_scripts(): + """Autodoc for files with the magic script documentation marker strings. + + Creates a file for eack kind of script (base/devel/fix/gui/modtools) + with all the ".. include::" directives to pull out docs between the + magic strings. + """ + # First, we collect the commands and paths to include in our docs + scripts = [] + for root, _, files in os.walk('../scripts'): + scripts.extend(doc_dir(root, files)) + # Next we split by type and create include directives sorted by command + kinds = {'base': [], 'devel': [], 'fix': [], 'gui': [], 'modtools': []} + for s in scripts: + k_fname = s[0].split('/', 1) + if len(k_fname) == 1: + kinds['base'].append(s) + else: + kinds.get(k_fname[0], []).append(s) + template = ('.. include:: /{}\n :start-after: BEGIN_DOCS\n' + ' :end-before: END_DOCS') + for key, value in kinds.items(): + kinds[key] = [ + template.format(x[1]) for x in sorted(value, key=lambda x: x[0])] + # Finally, we write our _auto/* files for each kind of script + if not os.path.isdir('_auto'): + os.mkdir('_auto') + head = { + 'base': 'Basic Scripts', + 'devel': 'Development Scripts', + 'fix': 'Bugfixing Scripts', + 'gui': 'GUI Scripts', + 'modtools': 'Scripts for Modders'} + for k in head: + title = '{l}\n{t}\n{l}\n\n'.format(t=head[k], l=len(head[k])*'#') + mode = 'w' if sys.version_info.major > 2 else 'wb' + with open('_auto/{}.rst'.format(k), mode) as outfile: + outfile.write(title) + outfile.write('\n\n'.join(kinds[k])) + + +# Actually call the docs generator +document_scripts() -from os import listdir -from os.path import isfile, join, isdir, relpath - -currentDir = '@CMAKE_CURRENT_SOURCE_DIR@' -if currentDir.startswith('@'): - # Not running in CMake - currentDir = '.' - -def makeIncludeAll(directory, extension): - outputFile = join(directory,'include-all.rst') - files = [ f for f in listdir(directory) if isfile(join(directory,f)) and f.endswith(extension) ] - files.sort() - dname = relpath(directory, relpath('..', currentDir)).replace('\\', '/') - while dname.startswith('..'): - dname = dname[3:] - TEMPLATE = '.. include:: /{}/{}\n :start-after: BEGIN_DOCS\n :end-before: END_DOCS' - out = [] - for f in files: - with open(join(directory,f), 'r', encoding='utf8') as fstream: - data = fstream.read().replace('\n','') - if 'BEGIN_DOCS' in data: - out.append(TEMPLATE.format(dname, f)) - if out: - # Only write the file if the index is not empty - with open(outputFile, 'w' if sys.version_info.major > 2 else 'wb') as outfile: - outfile.write(len(dname)*'=' + '\n' + dname + '\n' + len(dname)*'=' + '\n\n') - outfile.write('\n\n'.join(out)) - -def makeAllIncludeAll(directory, extension): - for root, subdirs, files in os.walk(directory): - if isdir(root): - makeIncludeAll(root, extension) - -makeAllIncludeAll(currentDir + '/scripts', '.lua') # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the