processed man page source - the path to the original source man page name - the name of this man page as extracted by manpage.manpage synopsis - the synopsis of this man page as extracted by manpage.manpage options - a list of options extracted from this man page aliases - a lis
| 77 | |
| 78 | |
| 79 | class ParsedManpage(BaseModel): |
| 80 | """processed man page |
| 81 | |
| 82 | source - the path to the original source man page |
| 83 | name - the name of this man page as extracted by manpage.manpage |
| 84 | synopsis - the synopsis of this man page as extracted by manpage.manpage |
| 85 | options - a list of options extracted from this man page |
| 86 | aliases - a list of aliases found for this man page |
| 87 | dashless_opts - allow interpreting options without a leading '-' |
| 88 | subcommands - list of subcommand names extracted from the manpage; when non-empty, |
| 89 | the matcher looks ahead for e.g. "git commit" and resolves it to the git-commit manpage |
| 90 | updated - whether this man page was manually updated |
| 91 | nested_cmd - specifies if positional arguments to this program can start a nested command, |
| 92 | e.g. sudo, xargs |
| 93 | """ |
| 94 | |
| 95 | source: str |
| 96 | name: str |
| 97 | synopsis: str | None = None |
| 98 | options: list[Option] = [] |
| 99 | aliases: list[tuple[str, int]] = [] |
| 100 | dashless_opts: bool = False |
| 101 | subcommands: list[str] = [] |
| 102 | updated: bool = False |
| 103 | nested_cmd: bool | str = False |
| 104 | extractor: str | None = None |
| 105 | extraction_meta: ExtractionMeta | None = None |
| 106 | |
| 107 | @property |
| 108 | def name_section(self): |
| 109 | name, section = util.name_section(os.path.basename(self.source)[:-3]) |
| 110 | return f"{name}({section})" |
| 111 | |
| 112 | @property |
| 113 | def section(self): |
| 114 | name, section = util.name_section(os.path.basename(self.source)[:-3]) |
| 115 | return section |
| 116 | |
| 117 | @property |
| 118 | def positionals(self): |
| 119 | # go over all options and look for those with the same 'positional' |
| 120 | # field; prefix-bearing positionals are excluded from ordered |
| 121 | # consumption — they can only be claimed by a token carrying their |
| 122 | # prefix (see prefixed_positionals) |
| 123 | groups = collections.OrderedDict() |
| 124 | for opt in self.options: |
| 125 | if opt.positional and not opt.prefix: |
| 126 | groups.setdefault(opt.positional, []).append(opt) |
| 127 | |
| 128 | # merge all the options under the same argument to a single string |
| 129 | for k, ln in groups.items(): |
| 130 | groups[k] = "\n\n".join([p.text for p in ln]) |
| 131 | |
| 132 | return groups |
| 133 | |
| 134 | @property |
| 135 | def prefixed_positionals(self): |
| 136 | """ordered mapping of positional name -> (prefix, merged help text) |
no outgoing calls