Strip roff escape sequences and formatting from text.
(text: str)
| 15 | |
| 16 | |
| 17 | def _clean_roff(text: str) -> str: |
| 18 | """Strip roff escape sequences and formatting from text.""" |
| 19 | # Remove font escapes: \fB, \fI, \fR, \fP, \f(xx |
| 20 | text = re.sub(r"\\f[BIRP]", "", text) |
| 21 | text = re.sub(r"\\f\(..", "", text) |
| 22 | # \- → - |
| 23 | text = text.replace("\\-", "-") |
| 24 | # \(en, \(em → - |
| 25 | text = re.sub(r"\\\(en|\\\(em", "-", text) |
| 26 | # \& (zero-width space) → empty |
| 27 | text = text.replace("\\&", "") |
| 28 | # \e → backslash |
| 29 | text = text.replace("\\e", "\\") |
| 30 | # \(aq, \(cq → ' |
| 31 | text = text.replace("\\(aq", "'") |
| 32 | text = text.replace("\\(cq", "'") |
| 33 | # \(lq, \(rq → " |
| 34 | text = re.sub(r"\\\(lq|\\\(rq", '"', text) |
| 35 | # \(bu → bullet (just remove) |
| 36 | text = text.replace("\\(bu", "") |
| 37 | # \~, \0, \<space> → space |
| 38 | text = text.replace("\\~", " ") |
| 39 | text = text.replace("\\0", " ") |
| 40 | text = text.replace("\\ ", " ") |
| 41 | # Remove \m[...] color directives |
| 42 | text = re.sub(r"\\m\[[^\]]*\]", "", text) |
| 43 | # Remove \s-N and \s+N size changes |
| 44 | text = re.sub(r"\\s[-+]?\d+", "", text) |
| 45 | # Remove \u (superscript), \d (subscript), \c, \:, \^, \| |
| 46 | for esc in ("\\u", "\\d", "\\c", "\\:", "\\^", "\\|"): |
| 47 | text = text.replace(esc, "") |
| 48 | # Remove \n(.x register references |
| 49 | text = re.sub(r"\\n\(?\w+", "", text) |
| 50 | # Collapse multiple spaces |
| 51 | text = re.sub(r" +", " ", text) |
| 52 | return text.strip() |
| 53 | |
| 54 | |
| 55 | def _is_section_header(line: str, name: str) -> bool: |