No man pages, but almost
The AWS Command Line Interface, which is available in Debian,
provides no man page. Instead, that tool has an integrated help system,
which allows you to run commands such as
aws rds
help
, that, for what I have seen, generates some
reStructuredText, then converts it to a man page in troff format, then
calls troff to convert it to text with basic formatting, and eventually
passes it to a pager. Since this is close to what
man does, the
result looks like a degraded man page, with some features missing such
as the adaptation to the terminal width.
Well, this is better than nothing, and better than what many
under-documented tools can offer, but for several reasons, it still
sucks: most importantly, it does not respect administrators' habits and
it does not integrate with the system man database. You it does not
allow you to use commands such as
apropos
,
and you will get no man page name auto-completion from your shell since
there is no man page.Generate the man pages
Now, since the integrated help system does generate a man page
internally, we can hack it to output it, and save it to a file:
Description: Enable a mode to generate troff man pages
The awscli help system internally uses man pages, but only to convert
them to text and show them with the pager. This patch enables a mode
that prints the troff code so the user can save the man page.
.
To use that mode, run the help commands with an environment variable
OUTPUT set to 'troff', for instance:
OUTPUT='troff' aws rds help
Forwarded: no
Author: Tanguy Ortolo <tanguy+debian@ortolo.eu>
Last-Update: 2016-11-22
Index: /usr/lib/python3/dist-packages/awscli/help.py
===================================================================
--- /usr/lib/python3/dist-packages/awscli/help.py 2016-11-21 12:14:22.236254730 +0100
+++ /usr/lib/python3/dist-packages/awscli/help.py 2016-11-21 12:14:22.236254730 +0100
@@ -49,6 +49,8 @@
Return the appropriate HelpRenderer implementation for the
current platform.
"""
+ if 'OUTPUT' in os.environ and os.environ['OUTPUT'] == 'troff':
+ return TroffHelpRenderer()
if platform.system() == 'Windows':
return WindowsHelpRenderer()
else:
@@ -97,6 +99,15 @@
return contents
+class TroffHelpRenderer(object):
+ """
+ Render help content as troff code.
+ """
+
+ def render(self, contents):
+ sys.stdout.buffer.write(publish_string(contents, writer=manpage.Writer()))
+
+
class PosixHelpRenderer(PagingHelpRenderer):
"""
Render help content on a Posix-like system. This includes
This patch must be applied from the root directory with
patch -p0
, otherwise GNU patch will not
accept to work on files with absolute names.
With that patch, you can run help commands with an environment
variable
OUTPUT='troff'
to get
the man page to use it as you like, for instance:
% OUTPUT='troff' aws rds help > aws_rds.1
% man -lt aws_rds.1 lp
Generate all the man pages
Now that we are able to generate the man page of any aws command,
all we need to generate all of them is a list of all the available
commands. This is not that easy, because the commands are somehow
derived from functions provided by a Python library named botocore,
which are derived from a bunch of configuration files, and some of them
are added, removed or renamed. Anyway, I have been able to write a
Python script that does that, but it includes a static list of these
modifications:
#! /usr/bin/python3
import subprocess
import awscli.clidriver
def write_manpage(command):
manpage = open('%s.1' % '_'.join(command), 'w')
command.append('help')
process = subprocess.Popen(command,
env= 'OUTPUT': 'troff' ,
stdout=manpage)
process.wait()
manpage.close()
driver = awscli.clidriver.CLIDriver()
command_table = driver._get_command_table()
renamed_commands = \
'config': 'configservice',
'codedeploy': 'deploy',
's3': 's3api'
added_commands = \
's3': ['cp', 'ls', 'mb', 'mv', 'presign', 'rb', 'rm', 'sync',
'website']
removed_subcommands = \
'ses': ['delete-verified-email-address',
'list-verified-email-addresses',
'verify-email-address'],
'ec2': ['import-instance', 'import-volume'],
'emr': ['run-job-flow', 'describe-job-flows',
'add-job-flow-steps', 'terminate-job-flows',
'list-bootstrap-actions', 'list-instance-groups',
'set-termination-protection',
'set-visible-to-all-users'],
'rds': ['modify-option-group']
added_subcommands = \
'rds': ['add-option-to-option-group',
'remove-option-from-option-group']
# Build a dictionary of real commands, including renames, additions and
# removals.
real_commands =
for command in command_table:
subcommands = []
subcommand_table = command_table[command]._get_command_table()
for subcommand in subcommand_table:
# Skip removed subcommands
if command in removed_subcommands \
and subcommand in removed_subcommands[command]:
continue
subcommands.append(subcommand)
# Add added subcommands
if command in added_subcommands:
for subcommand in added_subcommands[command]:
subcommands.append(subcommand)
# Directly add non-renamed commands
if command not in renamed_commands:
real_commands[command] = subcommands
# Add renamed commands
else:
real_commands[renamed_commands[command]] = subcommands
# Add added commands
for command in added_commands:
real_commands[command] = added_commands[command]
# For each real command and subcommand, generate a manpage
write_manpage(['aws'])
for command in real_commands:
write_manpage(['aws', command])
for subcommand in real_commands[command]:
write_manpage(['aws', command, subcommand])
'sync', 'website']
This script will generate more than 2,000 man page files in the
current directory; you will then be able to move them to
/usr/local/share/man/man1.
Since this is a lot of man pages, it may be appropriate to
concatenate them by major command, for instance all the
aws rds
together