Add script to generate command documentation (#2161)

* Add mdutils to docs dependencies

* Add script to generate the command docs

---

Co-authored-by: Niko <nikoshell20@gmail.com>
pull/2163/head
Gulshan Singh 2 years ago committed by GitHub
parent 7ae13403de
commit 5e77036b77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

12
poetry.lock generated

@ -894,6 +894,16 @@ files = [
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
[[package]]
name = "mdutils"
version = "1.6.0"
description = "Useful package for creating Markdown files while executing python code."
optional = false
python-versions = "^3.6"
files = [
{file = "mdutils-1.6.0.tar.gz", hash = "sha256:647f3cf00df39fee6c57fa6738dc1160fce1788276b5530c87d43a70cdefdaf1"},
]
[[package]]
name = "mergedeep"
version = "1.3.4"
@ -2329,4 +2339,4 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "29623ce1dc12d602affb54c4a9a8e32e64c61829ed782ccc9462339afec6a204"
content-hash = "68e08925a9c889db020f8bd5f2267319c62b7f78c4ec32baabefa665d0c4d731"

@ -188,6 +188,7 @@ vermin = "^1.6.0"
optional = true
[tool.poetry.group.docs.dependencies]
mdutils = "*"
mkdocs = "*"
mkdocs-gen-files = "*"
mkdocs-material = "*"

@ -0,0 +1,162 @@
from pprint import pprint
import pwndbg.commands
from collections import defaultdict
import argparse
import os
import io
import sys
from mdutils.mdutils import MdUtils
def dprint(ob):
print(dir(ob))
def save_to_file(filename, data):
with open(filename, 'w') as f:
f.write(data)
def inline_code(code):
return f"`{code}`"
def md_help(filename, parser, name):
mdFile = MdUtils(filename)
mdFile.new_header(level=1, title=name)
if parser.description:
mdFile.new_header(level=2, title="Description")
mdFile.new_paragraph(parser.description)
mdFile.new_header(level=2, title="Usage:")
mdFile.insert_code(parser.format_usage(), language="bash")
used_actions = {}
options_positional = ["Positional Argument", "Help"]
options_optional = ["Short", "Long", "Default", "Help"]
# Process positional arguments
if parser._positionals._group_actions:
for action in parser._positionals._group_actions:
list_of_str = [inline_code(action.dest), action.help]
this_id = id(action)
if this_id in used_actions:
continue
used_actions[this_id] = True
options_positional.extend(list_of_str)
mdFile.new_header(level=2, title="Positional Arguments")
options_positional = [
inline_code(di) if di is None else di.replace("\n", " ") for di in options_positional
]
mdFile.new_table(
columns=2,
rows=len(options_positional) // 2,
text=options_positional,
text_align="left",
)
# Process optional arguments
if parser._option_string_actions:
for k in parser._option_string_actions:
action = parser._option_string_actions[k]
list_of_str = ["", "", "", action.help]
this_id = id(action)
if this_id in used_actions:
continue
used_actions[this_id] = True
for opt in action.option_strings:
# --, long option
if len(opt) > 1 and opt[1] in parser.prefix_chars:
list_of_str[1] = inline_code(opt)
# short opt
elif len(opt) > 0 and opt[0] in parser.prefix_chars:
list_of_str[0] = inline_code(opt)
if not (
isinstance(action.default, bool)
or isinstance(action, argparse._VersionAction)
or isinstance(action, argparse._HelpAction)
):
default = (
action.default
if isinstance(action.default, str)
else repr(action.default)
)
list_of_str[2] = inline_code(default)
options_optional.extend(list_of_str)
mdFile.new_header(level=2, title="Optional Arguments")
options_optional = [
inline_code(di) if di is None else di.replace("\n", " ") for di in options_optional
]
mdFile.new_table(
columns=4,
rows=len(options_optional) // 4,
text=options_optional,
text_align="left",
)
mdFile.create_md_file()
commands_info = {}
cmd = {}
commands = defaultdict(list)
for i in dir(pwndbg.commands):
fn = getattr(pwndbg.commands, i)
# print(dir(fn))
for j in dir(fn):
if isinstance(getattr(fn, j), pwndbg.commands.Command):
fn2 = getattr(fn, j)
category = fn2.category
parser = fn2.parser
if category is None:
category = 'Other'
else:
category = category.value
commands[category].append(j)
filename = f'commands/{i}/{j}.md'
parser = (getattr(fn2, 'parser'))
cmd[parser.prog] = i
directory = os.path.dirname(filename)
os.makedirs(directory, exist_ok=True)
commands_info[j] = {
"name": j,
"command_name": parser.prog,
"category": category,
"module": i,
"desc": parser.description.splitlines()[0] or ''
}
data = ""
md_help(filename, parser, parser.prog)
pprint(cmd)
# use d dict to create index
mdFile = MdUtils('commands/index.md')
mdFile.new_header(level=1, title="Commands")
for k, v in commands.items():
mdFile.new_header(level=2, title=f"{k}")
items = []
for i in v:
info = commands_info[i]
try:
items.append(f' [{info["command_name"]}]({info["module"]}/{i}.md) {info["desc"]}')
except Exception as e:
print(f"-> {e}")
mdFile.new_list(items=items)
mdFile.create_md_file()
Loading…
Cancel
Save