list_distros.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. """
  2. List distributions supported by neofetch
  3. """
  4. from __future__ import annotations
  5. import string
  6. import textwrap
  7. from dataclasses import dataclass
  8. from pathlib import Path
  9. import regex
  10. RE_SPLIT = regex.compile('EOF[ \n]*?;;')
  11. RE_COLORS = regex.compile("""(?<=set_colors )[a-z\\d ]+(?=\n)""")
  12. @dataclass
  13. class AsciiArt:
  14. match: str
  15. color: str
  16. ascii: str
  17. def get_friendly_name(self) -> str:
  18. return self.match.split("|")[0].strip(string.punctuation + '* ')\
  19. .replace('"', '').replace('*', '')
  20. def substr(s: str, start: str, end: str | None = None):
  21. """
  22. Get substring between start and end
  23. """
  24. start = s.index(start) + len(start)
  25. if end is None:
  26. return s[start:]
  27. return s[start:s.index(end, start)]
  28. def parse_ascii_distros() -> list[AsciiArt]:
  29. """
  30. Parse ascii distros from neofetch script
  31. """
  32. nf = (Path(__file__).parent.parent / 'neofetch').read_text()
  33. # Get the content of "get_distro_ascii" function
  34. nf = nf[nf.index('get_distro_ascii() {\n'):]
  35. nf = nf[:nf.index('\n}\n')]
  36. # Remove trailing spaces
  37. while ' \n' in nf:
  38. nf = nf.replace(' \n', '\n')
  39. # Split by blocks
  40. blocks = [sub.strip() for b in regex.split('case .*? in\n', nf) for sub in RE_SPLIT.split(b)]
  41. # Parse blocks
  42. def parse_block(block: str) -> AsciiArt:
  43. try:
  44. # Get ascii art
  45. assert "'EOF'\n" in block
  46. art = substr(block, "'EOF'\n")
  47. # Join \
  48. block = block.replace('\\\n', ' ')
  49. # Get switch-case matching parameter
  50. match = block.split('\n')[0].strip()
  51. assert match.endswith(')')
  52. match = match[:-1]
  53. # Get colors
  54. color = RE_COLORS.findall(block)[0]
  55. if len(color) == 0:
  56. raise Exception(block)
  57. return AsciiArt(match, color, art)
  58. except AssertionError:
  59. pass
  60. out = [parse_block(block) for block in blocks]
  61. return [v for v in out if v]
  62. def wrap(text: str, max_len: int, leading_space: int):
  63. length = max_len - leading_space
  64. lines = [line for raw in text.split('\n') for line in textwrap.wrap(raw, length) or ['']]
  65. return '\n'.join(' ' * leading_space + line if line else line for line in lines)
  66. def generate_help(max_len: int = 100, leading_space: int = 32):
  67. distros = sorted(list({a.get_friendly_name() for a in parse_ascii_distros()}), key=str.casefold)
  68. smalls = [d.replace('_small', '') for d in distros if d.endswith('_small')]
  69. olds = [d.replace('_old', '') for d in distros if d.endswith('_old')]
  70. distros = [d for d in distros if not d.endswith('_small') and not d.endswith('_old')]
  71. out = f"NOTE: {', '.join(distros)} have ascii logos.\n\n"\
  72. f"NOTE: {', '.join(olds)} have 'old' logo variants, use {{distro}}_old to use them.\n\n" \
  73. f"NOTE: {', '.join(smalls)} have 'small' logo variants, use {{distro}}_small to use them."
  74. return wrap(out, max_len, leading_space)
  75. if __name__ == '__main__':
  76. print(generate_help(100, 0))
  77. print(generate_help())