aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py2man/__init__.py1
-rw-r--r--py2man/manpages.py172
-rw-r--r--py2man/options.py93
3 files changed, 266 insertions, 0 deletions
diff --git a/py2man/__init__.py b/py2man/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/py2man/__init__.py
@@ -0,0 +1 @@
+
diff --git a/py2man/manpages.py b/py2man/manpages.py
new file mode 100644
index 0000000..2490fcc
--- /dev/null
+++ b/py2man/manpages.py
@@ -0,0 +1,172 @@
+#
+#-*- coding:utf-8 -*-
+
+
+import os
+from datetime import datetime
+
+from .options import LONG_OPTIONS, SHORT_OPTS
+
+
+ActionStr = '.BR gkeys-%s (1),'
+
+ExampleHeader = '''.SH Example'''
+
+BreakStr = '''.br
+%s'''
+
+SubCmdStr = '''.IP %(cmd)s
+%(cmd-desc)s'''
+
+SubCmdHdr = '.SH \\ %s'
+
+class ManPage(object):
+
+ def __init__(self, prog, version, template, path):
+ self.prog = prog
+ self.version = version
+ self.template = template
+ self.path = path
+
+
+ @staticmethod
+ def gen_opts(options):
+ _opts = list()
+ for opt in options:
+ _opts.append(SHORT_OPTS.get(opt))
+ return _opts
+
+
+ @staticmethod
+ def gen_optsStr(firstline, data, opts):
+ indent = ' '
+ escapes = 15
+ wrapl = 72 + escapes
+ output = []
+ line = firstline.rstrip('%(opts)s') % data
+ ll = len(line)
+ l1 = True
+ for opt in opts:
+ if (ll + len(SHORT_OPTS[opt])) < wrapl:
+ line = line + '%s ' % SHORT_OPTS[opt]
+ ll = len(line)
+ else:
+ if l1:
+ output.append(line)
+ l1 = False
+ else:
+ output.append(BreakStr % line)
+ line = indent + '%s ' % SHORT_OPTS[opt]
+ ll = len(line)
+ return '\n'.join(output)
+
+
+ @staticmethod
+ def gen_actions(actions):
+ acts = []
+ for act in actions:
+ if not act.startswith("--"):
+ acts.append(ActionStr % act)
+ return '\n'.join(acts)
+
+
+ @staticmethod
+ def gen_options(options):
+ _opts = []
+ for opt in options:
+ _opts.append(LONG_OPTIONS[opt])
+ return '\n'.join(_opts)
+
+
+ @staticmethod
+ def gen_example(text):
+ example = []
+ if text:
+ for line in text.split('\n'):
+ if line and line[0] in [' ']:
+ example.append(line)
+ else:
+ example.append(BreakStr % line)
+ return '\n'.join(example)
+
+
+ @staticmethod
+ def gen_subcmd(cmds):
+ #print(cmds.values())
+ output = []
+ for cmd in list(cmds):
+ print(cmd)
+ if cmd.startswith('--'):
+ output.append(SubCmdHdr % cmd.strip('-').upper())
+ else:
+ output.append(SubCmdStr % {'cmd': cmd, 'cmd-desc': cmds[cmd]})
+ return '\n'.join(output)
+
+
+ def make_subpage(self, action, Action_Map, actions):
+ '''Create and saves one sub-command man page using the
+ classes template definition setting'''
+ actions.remove(action)
+ # remove the help group separators
+ actions = [x for x in actions if not x.startswith("---")]
+ data = {}
+ data['prog'] = self.prog
+ data['version'] = self.version
+ data['date'] = datetime.strftime(datetime.today(),'%B %d, %Y')
+ data['action'] = action
+ data['actions'] = self.gen_actions(actions)
+ data['options'] = self.gen_options(Action_Map[action]['options'])
+ data['desc'] = Action_Map[action]['desc']
+ data['long_desc'] = Action_Map[action]['long_desc']
+ if Action_Map[action]['example']:
+ data['example'] = self.gen_example(Action_Map[action]['example'])
+ data['exampleheader'] = ExampleHeader
+ else:
+ data['example'] = ''
+ data['exampleheader'] = ''
+ doc = []
+ for line in self.template.split('\n'):
+ if '%(opts)s' in line:
+ doc.append(self.gen_optsStr(
+ line, data, Action_Map[action]['options']))
+ else:
+ doc.append(line % data)
+ filepath = os.path.join(self.path, "%s-%s.1" % (self.prog, action))
+ with open(filepath, 'w', encoding='utf-8') as man:
+ man.write('\n'.join(doc))
+
+
+ def make_subpages(self, Action_Map, actions):
+ '''Create man pages for all sub-commands listed
+
+ @param prog: string of the base application command
+ @param version: string to embed in the man pages
+ @param Action_Map: Dictionary of sub-command actions and other data
+ @param actions: list of keys in Action_Map to generate pages for
+ @param location: string, path to save the newly created man pages
+ '''
+ for action in actions:
+ self.make_subpage(action, Action_Map, actions)
+
+
+ def make_prog(self, prog_map):
+ data = {}
+ data['prog'] = self.prog
+ data['version'] = self.version
+ data['date'] = datetime.strftime(datetime.today(),'%B %d, %Y')
+ data['actions'] = self.gen_actions(list(prog_map['sub-cmds']))
+ data['options'] = self.gen_options(prog_map['options'])
+ data['desc'] = prog_map['desc']
+ data['long_desc'] = prog_map['long_desc']
+ data['sub-cmds'] = self.gen_subcmd(prog_map['sub-cmds'])
+ doc = []
+ for line in self.template.split('\n'):
+ doc.append(line % data)
+ filepath = os.path.join(self.path, "%s.1" % (self.prog))
+ with open(filepath, 'w', encoding='utf-8') as man:
+ man.write('\n'.join(doc))
+
+ def read_template(self, path, filename):
+ filepath = os.path.join(path, filename)
+ with open(filepath, 'r', encoding='utf-8') as template:
+ self.template = template.read()
diff --git a/py2man/options.py b/py2man/options.py
new file mode 100644
index 0000000..1beb132
--- /dev/null
+++ b/py2man/options.py
@@ -0,0 +1,93 @@
+#
+#-*- coding:utf-8 -*-
+
+from collections import OrderedDict
+
+
+LONG_OPTIONS = OrderedDict({
+ 'help': '''.IP "-h, --help"
+show this help message and exit''',
+ 'status': '''.IP "-A, --status"
+Toggles the active status of a member for LDAP searches''',
+ 'all': '''.IP "-a, --all"
+Toggles matching all input arguments for searches''',
+ 'category': '''.IP "-C \\fICATEGORY\\fR, --category \\fICATEGORY"
+The category name of the seed file being added to.
+.br
+This name must be listed in the gkeys.conf file's
+[seeds], [seedurls] and [verify-seeds] sections''',
+ 'cleankey': '''.IP " --clean-key"
+Clean the key from the keyring due to failures.''',
+ 'cleanseed': '''.IP " --clean-seed"
+Clean the seed from the seedfile due to failures.
+.br
+Used during binary keyring release creation.''',
+ 'config': '''.IP "-c \\fICONFIG\\fR, --config \\fICONFIG\\fR"
+The path to an alternate config file''',
+ 'debug': '''.IP "-D, --debug \\fI{WARNING,INFO,FATAL,NOTSET,WARN,DEBUG,ERROR,CRITICAL}\\fR"
+The logging level to set for the logfile''',
+ 'dest': '''.IP "-d \\fIDESTINATION\\fR, --dest \\fIDESTINATION"
+The category name of the seed file being added to.''',
+ 'exact': '''.IP "-e, --exact"
+Use CASE matching in searches''',
+ 'file': '''.IP "-F \\fIFILENAME\\fR, --file \\fIFILENAME"
+The path/URL to use for the (signed) file''',
+ '1file': '''.IP "-F \\fIFILENAME\\fR, --file \\fIFILENAME"
+The path/URL to use for the (signed) file''',
+ 'fingerprint': '''.IP "-f \\fIFINGERPRINT\\fR, --fingerprint \\fIFINGERPRINT"
+The fingerprint(s) of the the key(s) or subkey(s)''',
+ 'gpgsearch': '''.IP "-g, --gpgsearch"
+Do a gpg search operation, rather than a gkey search''',
+ 'homedir': '''.IP "-H \\fIHOMEDIR\\fR, --file \\fIHOMEDIR"
+The destination for the generated key''',
+ 'keyid': '''.IP "-i \\fIKEYID\\fR, --keyid \\fIKEYID"
+The long keyid of the gpg key to search for''',
+ 'keyring': '''.IP "-k \\fIKEYRING\\fR, --keyring \\fIKEYRING"
+The name of the keyring to use for verification, etc.''',
+ 'keys': '''.IP "-K \\fIKEYS\\fR, --keys \\fIKEYS"
+The fingerprint(s) of the primary keys in the keyring.''',
+ 'mail': '''.IP "-m \\fIEMAIL\\fR, --mail \\fIEMAIL"
+The email address to search for or use.''',
+ 'nick': '''.IP "-n \\fINICK\\fR, --nick \\fINICK"
+The nick of the user whose gkey seed is being added''',
+ 'name': '''.IP "-N \\fINAME\\fR, --name \\fINAME"
+The name of the user whose gkey seed is being added''',
+ 'keydir': '''.IP "-r \\fIKEYDIR\\fR, --keydir \\fIKEYDIR"
+The key directory the key is to be installed to''',
+ 'signature': '''.IP "-s \\fISIGNATURE\\fR, --signature \\fISIGNATURE"
+The path/URL to use for the signature.''',
+ 'spec': '''.IP "-S \\fISPEC\\fR, --psec \\fISPEC"
+The spec file to use from the gkeys-gen.conf file.''',
+ 'timestamp': '''.IP "-t, --timestamp"
+Turn on timestamp use.''',
+ 'uid': '''.IP "-u \\fIUID\\fR, --uid \\fIUID"
+The user id(s) (and email) of the key(s) being added (optional)''',
+})
+
+SHORT_OPTS = OrderedDict({
+ 'help': '[\\fB\\-h\\fR]',
+ 'status': '[\\fB\\-A\\fR]',
+ 'all': '[\\fB\\-a\\fR]',
+ 'category': '[\\fB\\-C\\fR \\fICATEGORY\\fR]',
+ 'cleankey': '[\\fB\\-\\-cleankey\\fR]',
+ 'cleanseed': '[\\fB\\-\\-cleanseed\\fR]',
+ 'dest': '[\\fB\\-d\\fR \\fIDESTINATION\\fR]',
+ 'exact': '[\\fB\\-e\\fR]',
+ 'file': '[\\fB\\-F\\fR \\fIFILENAME\\fR]',
+ '1file': '[\\fB\\-F\\fR \\fIFILENAME\\fR]',
+ 'fingerprint': '[\\fB\\-f\\fR \\fIFINGERPRINT\\fR [\\fIFINGERPRINT\\fR ...]]',
+ 'gpgsearch': '[\\fB\\-g\\fR]',
+ 'homedir': '[\\fB\\-H\\fR \\fIHOMEDIR\\fR]',
+ 'keyid': '[\\fB\\-i\\fR \\fIKEYID\\fR [\\fIKEYID\\fR ...]]',
+ 'keyring': '[\\fB\\-k\\fR \\fIKEYRING\\fR]',
+ 'keys': '[\\fB\\-K\\fR [\\fIKEYS\\fR [\\fIKEYS\\fR ...]]]',
+ 'mail': '[\\fB\\-m\\fR \\fIEMAIL\\fR]',
+ 'nick': '[\\fB\\-n\\fR \\fINICK\\fR]',
+ 'name': '[\\fB\\-N\\fR [\\fINAME\\fR [\\fINAME\\fR ...]]]',
+ '1name': '[\\fB\\-N\\fR \\fINAME\\fR]',
+ 'keydir': '[\\fB\\-r\\fR \\fIKEYDIR\\fR]',
+ 'signature': '[\\fB\\-s\\fR \\fISIGNATURE\\fR]',
+ 'spec': '[\\fB\\-S\\fR \\fISPEC\\fR]',
+ 'timestamp': '[\\fB\\-t\\fR]',
+ 'uid': '[\\fB\\-u\\fR [\\fIUID\\fR [\\fIUID\\fR ...]]]',
+})