Add, use, and require auto docs for all keybindings

develop
PeridexisErrant 2016-08-25 10:28:07 +10:00
parent e3ff89ba03
commit 951d293050
3 changed files with 123 additions and 18 deletions

@ -72,6 +72,8 @@ Fixes
Misc Improvements
-----------------
- Documented all default keybindings (from :file:`dfhack.init-example`) in the
docs for the relevant commands; updates enforced by build system.
- `lua` and `gui/gm-editor` now support the same aliases (``scr``, ``unit``, etc.)
- `remotefortressreader`: Added support for

@ -15,15 +15,70 @@ serve to show the default.
# pylint:disable=redefined-builtin
import fnmatch
from io import open
from itertools import starmap
import os
import re
import shlex # pylint:disable=unused-import
import sys
# -- Support :dfhack-keybind:`command` ------------------------------------
# this is a custom directive that pulls info from dfhack.init-example
from docutils import nodes
from docutils.parsers.rst import roles
def get_keybinds():
"""Get the implemented keybinds, and return a dict of
{tool: [(full_command, keybinding, context), ...]}.
"""
with open('dfhack.init-example') as f:
lines = [l.replace('keybinding add', '').strip() for l in f.readlines()
if l.startswith('keybinding add')]
keybindings = dict()
for k in lines:
first, command = k.split(' ', maxsplit=1)
bind, context = (first.split('@') + [''])[:2]
if ' ' not in command:
command = command.replace('"', '')
tool = command.split(' ')[0].replace('"', '')
keybindings[tool] = keybindings.get(tool, []) + [
(command, bind.split('-'), context)]
return keybindings
KEYBINDS = get_keybinds()
# pylint:disable=unused-argument,dangerous-default-value,too-many-arguments
def dfhack_keybind_role_func(role, rawtext, text, lineno, inliner,
options={}, content=[]):
"""Custom role parser for DFHack default keybinds."""
roles.set_classes(options)
if text not in KEYBINDS:
msg = inliner.reporter.error(
'no keybinding for {} in dfhack.init-example'.format(text),
line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
newnode = nodes.paragraph()
for cmd, key, ctx in KEYBINDS[text]:
n = nodes.paragraph()
newnode += n
n += nodes.strong('Keybinding: ', 'Keybinding: ')
for k in key:
n += nodes.inline(k, k, classes=['kbd'])
if cmd != text:
n += nodes.inline(' -> ', ' -> ')
n += nodes.literal(cmd, cmd, classes=['guilabel'])
if ctx:
n += nodes.inline(' in ', ' in ')
n += nodes.literal(ctx, ctx)
return [newnode], []
roles.register_canonical_role('dfhack-keybind', dfhack_keybind_role_func)
# -- Autodoc for DFhack scripts -------------------------------------------
def doc_dir(dirname, files):
@ -46,28 +101,41 @@ def doc_dir(dirname, files):
command = line
def doc_all_dirs():
"""Collect the commands and paths to include in our docs."""
scripts = []
for root, _, files in os.walk('scripts'):
scripts.extend(doc_dir(root, files))
return tuple(scripts)
DOC_ALL_DIRS = doc_all_dirs()
def document_scripts():
"""Autodoc for files with the magic script documentation marker strings.
Returns a dict of script-kinds to lists of .rst include directives.
"""
# 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:
for s in DOC_ALL_DIRS:
k_fname = s[0].split('/', 1)
if len(k_fname) == 1:
kinds['base'].append(s)
else:
kinds[k_fname[0]].append(s)
template = '.. _{}:\n\n.. include:: /{}\n' +\
' :start-after: {}\n :end-before: {}\n'
return {key: '\n\n'.join(starmap(template.format, sorted(value)))
def template(arg):
tmp = '.. _{}:\n\n.. include:: /{}\n' +\
' :start-after: {}\n :end-before: {}\n'
if arg[0] in KEYBINDS:
tmp += '\n:dfhack-keybind:`{}`\n'.format(arg[0])
return tmp.format(*arg)
return {key: '\n\n'.join(map(template, sorted(value)))
for key, value in kinds.items()}
def write_script_docs():
"""
Creates a file for eack kind of script (base/devel/fix/gui/modtools)
@ -97,10 +165,23 @@ def write_script_docs():
outfile.write(kinds[k])
# Actually call the docs generator
write_script_docs()
def all_keybinds_documented():
"""Check that all keybindings are documented with the :dfhack-keybind:
directive somewhere."""
configured_binds = set(KEYBINDS)
script_commands = set(i[0] for i in DOC_ALL_DIRS)
with open('./docs/Plugins.rst') as f:
plugin_binds = set(re.findall(':dfhack-keybind:`(.*?)`', f.read()))
undocumented_binds = configured_binds - script_commands - plugin_binds
if undocumented_binds:
raise ValueError('The following DFHack commands have undocumented'
'keybindings: {}'.format(sorted(undocumented_binds)))
# Actually call the docs generator and run test
write_script_docs()
all_keybinds_documented()
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.

@ -353,7 +353,8 @@ This plugin adds an option to the :kbd:`q` menu when `enabled <enable>`.
command-prompt
==============
An in-game DFHack terminal, where you can enter other commands.
Best used from a keybinding; by default :kbd:`Ctrl`:kbd:`Shift`:kbd:`P`.
:dfhack-keybind:`command-prompt`
Usage: ``command-prompt [entry]``
@ -372,13 +373,11 @@ Otherwise somewhat similar to `gui/quickcmd`.
hotkeys
=======
Opens an in-game screen showing which DFHack keybindings are
active in the current context.
active in the current context. See also `hotkey-notes`.
.. image:: images/hotkeys.png
Type ``hotkeys`` into the DFHack console to open the screen,
or bind the command to a globally active hotkey. The default
keybinding is :kbd:`Ctrl`:kbd:`F1`. See also `hotkey-notes`.
:dfhack-keybind:`hotkeys`
.. _rb:
@ -659,12 +658,16 @@ Unit order examples::
The orderings are defined in ``hack/lua/plugins/sort/*.lua``
:dfhack-keybind:`sort-units`
.. _stocks:
stocks
======
Replaces the DF stocks screen with an improved version.
:dfhack-keybind:`stocks`
.. _stocksettings:
.. _stockpiles:
@ -676,6 +679,7 @@ See `gui/stockpiles` for an in-game interface.
:copystock: Copies the parameters of the currently highlighted stockpile to the custom
stockpile settings and switches to custom stockpile placement mode, effectively
allowing you to copy/paste stockpiles easily.
:dfhack-keybind:`copystock`
:savestock: Saves the currently highlighted stockpile's settings to a file in your Dwarf
Fortress folder. This file can be used to copy settings between game saves or
@ -874,7 +878,7 @@ Invoked as::
job-material <inorganic-token>
Intended to be used as a keybinding:
:dfhack-keybind:`job-material`
* In :kbd:`q` mode, when a job is highlighted within a workshop or furnace,
changes the material of the job. Only inorganic materials can be used
@ -887,6 +891,8 @@ job-duplicate
In :kbd:`q` mode, when a job is highlighted within a workshop or furnace
building, calling ``job-duplicate`` instantly duplicates the job.
:dfhack-keybind:`job-duplicate`
.. _autogems:
autogems
@ -1076,6 +1082,8 @@ spotclean
Works like ``clean map snow mud``, but only for the tile under the cursor. Ideal
if you want to keep that bloody entrance ``clean map`` would clean up.
:dfhack-keybind:`spotclean`
.. _autodump:
autodump
@ -1098,10 +1106,16 @@ Options:
:destroy-here: As ``destroy``, but only the selected item in the :kbd:`k` list,
or inside a container.
Alias ``autodump-destroy-here``, for keybindings.
:dfhack-keybind:`autodump-destroy-here`
:visible: Only process items that are not hidden.
:hidden: Only process hidden items.
:forbidden: Only process forbidden items (default: only unforbidden).
``autodump-destroy-item`` destroys the selected item, which may be selected
in the :kbd:`k` list, or inside a container. If called again before the game
is resumed, cancels destruction of the item.
:dfhack-keybind:`autodump-destroy-item`
cleanowned
==========
@ -1139,6 +1153,8 @@ Options:
:prefs: Show dwarf preferences summary
:reload: Reload configuration file (``dfhack-config/dwarfmonitor.json``)
:dfhack-keybind:`dwarfmonitor`
Widget configuration:
The following types of widgets (defined in :file:`hack/lua/plugins/dwarfmonitor.lua`)
@ -1264,6 +1280,8 @@ zone
====
Helps a bit with managing activity zones (pens, pastures and pits) and cages.
:dfhack-keybind:`zone`
Options:
:set: Set zone or cage under cursor as default for future assigns.
@ -1738,6 +1756,8 @@ Basic commands:
to remove designations, for if you accidentally set 50 levels at once.
:diglx: Also cross z-levels, digging stairs as needed. Alias for ``digl x``.
:dfhack-keybind:`digv`
.. _digexp:
digexp
@ -2209,6 +2229,8 @@ Usage:
* When viewing unit details, body-swaps into that unit.
* In the main adventure mode screen, reverts transient swap.
:dfhack-keybind:`adv-bodyswap`
.. _createitem:
createitem