Return a list of lines with a unified-diff-style comparison.
(stored_mp: ParsedManpage, fresh_mp: ParsedManpage)
| 186 | |
| 187 | |
| 188 | def format_diff(stored_mp: ParsedManpage, fresh_mp: ParsedManpage) -> list[str]: |
| 189 | """Return a list of lines with a unified-diff-style comparison.""" |
| 190 | diffs = compare_manpages(stored_mp, fresh_mp) |
| 191 | out: list[str] = [] |
| 192 | |
| 193 | field_diffs = [d for d in diffs if d["type"] == "field"] |
| 194 | |
| 195 | for d in field_diffs: |
| 196 | field = d["label"] |
| 197 | _, old_val, new_val = d["details"][0] |
| 198 | out.append(f" {_BOLD}{field}:{_RESET}") |
| 199 | text_diff = _fmt_text_diff(old_val, new_val, " ") |
| 200 | if text_diff: |
| 201 | out.append(text_diff) |
| 202 | else: |
| 203 | out.append(_fmt_value(old_val, " - ", _RED)) |
| 204 | out.append(_fmt_value(new_val, " + ", _GREEN)) |
| 205 | |
| 206 | stored_opts = {_option_key(o): o for o in stored_mp.options} |
| 207 | fresh_opts = {_option_key(o): o for o in fresh_mp.options} |
| 208 | all_keys = list(dict.fromkeys(list(stored_opts.keys()) + list(fresh_opts.keys()))) |
| 209 | |
| 210 | changed_options: list[tuple[str, list | None]] = [] |
| 211 | added_options: list[object] = [] |
| 212 | removed_options: list[object] = [] |
| 213 | |
| 214 | for key in all_keys: |
| 215 | s_opt = stored_opts.get(key) |
| 216 | f_opt = fresh_opts.get(key) |
| 217 | if s_opt and f_opt: |
| 218 | opt_diffs = [] |
| 219 | for field in _OPT_FIELDS: |
| 220 | old_val = _normalize(field, getattr(s_opt, field)) |
| 221 | new_val = _normalize(field, getattr(f_opt, field)) |
| 222 | if old_val != new_val: |
| 223 | opt_diffs.append((field, old_val, new_val)) |
| 224 | changed_options.append( |
| 225 | (_fmt_flags(s_opt), opt_diffs if opt_diffs else None) |
| 226 | ) |
| 227 | elif f_opt: |
| 228 | added_options.append(f_opt) |
| 229 | else: |
| 230 | removed_options.append(s_opt) |
| 231 | |
| 232 | if changed_options or added_options or removed_options: |
| 233 | out.append(f" {_BOLD}options:{_RESET}") |
| 234 | |
| 235 | for label, opt_field_diffs in changed_options: |
| 236 | if opt_field_diffs is None: |
| 237 | out.append(f" {_DIM}{label} (unchanged){_RESET}") |
| 238 | else: |
| 239 | out.append(f" {_CYAN}{_BOLD}{label}{_RESET}") |
| 240 | for field, old_val, new_val in opt_field_diffs: |
| 241 | out.append(f" {field}:") |
| 242 | text_diff = _fmt_text_diff(old_val, new_val, " ") |
| 243 | if text_diff: |
| 244 | out.append(text_diff) |
| 245 | else: |
no test coverage detected