main.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python3
  2. from __future__ import annotations
  3. import argparse
  4. import json
  5. from dataclasses import dataclass
  6. from pathlib import Path
  7. from typing import Iterable
  8. from hypy_utils import printc, json_stringify, color
  9. from .color_util import AnsiMode
  10. from .neofetch_util import run_neofetch
  11. from .presets import PRESETS, ColorProfile
  12. CONFIG_PATH = Path.home() / '.config/hyfetch.json'
  13. CONFIG_PATH.parent.mkdir(exist_ok=True, parents=True)
  14. @dataclass
  15. class Config:
  16. preset: str
  17. mode: AnsiMode
  18. def save(self):
  19. CONFIG_PATH.write_text(json_stringify(self), 'utf-8')
  20. def check_config() -> Config:
  21. """
  22. Check if the configuration exists. Return the config object if it exists. If not, call the
  23. config creator
  24. TODO: Config path param
  25. :return: Config object
  26. """
  27. if CONFIG_PATH.is_file():
  28. return Config(**json.loads(CONFIG_PATH.read_text('utf-8')))
  29. return create_config()
  30. def literal_input(prompt: str, options: Iterable[str], default: str) -> str:
  31. """
  32. Ask the user to provide an input among a list of options
  33. :param prompt: Input prompt
  34. :param options: Options
  35. :param default: Default option
  36. :return: Selection
  37. """
  38. options = list(options)
  39. lows = [o.lower() for o in options]
  40. op_text = '|'.join([f'&l&n{o}&r' if o == default else o for o in options])
  41. printc(f'{prompt} ({op_text})')
  42. selection = input('> ') or default
  43. while not selection.lower() in lows:
  44. print(f'Invalid selection! {selection} is not one of {"|".join(options)}')
  45. selection = input('> ') or default
  46. print()
  47. return options[lows.index(selection)]
  48. def center_text(txt: str, spaces: int) -> str:
  49. """
  50. Put the text in the center in a defined space
  51. >>> center_text('meow', 9)
  52. ' meow '
  53. :param txt: Text
  54. :param spaces: Total space of the text
  55. :return: Text with length spaces
  56. """
  57. spaces -= len(txt)
  58. if spaces % 2 == 1:
  59. spaces -= 1
  60. txt += ' '
  61. while spaces > 0:
  62. spaces -= 2
  63. txt = f' {txt} '
  64. return txt
  65. def create_config() -> Config:
  66. """
  67. Create config interactively
  68. :return: Config object (automatically stored)
  69. """
  70. # Select color system
  71. # TODO: Demo of each color system
  72. color_system = literal_input('Which &acolor &bsystem &rdo you want to use?',
  73. ['8bit', 'rgb'], 'rgb')
  74. # Print preset
  75. print('Available presets:\n')
  76. spacing = max(max(len(k) for k in PRESETS.keys()), 30)
  77. flags = []
  78. for name, preset in PRESETS.items():
  79. flags.append([preset.color_text(' ' * spacing, foreground=False),
  80. '&0' + preset.color_text(center_text(name, spacing), foreground=False),
  81. preset.color_text(' ' * spacing, foreground=False)])
  82. flags_per_row = 3
  83. while flags:
  84. current = flags[:flags_per_row]
  85. flags = flags[flags_per_row:]
  86. for line in range(len(current[0])):
  87. printc(' '.join(flag[line] for flag in current))
  88. print()
  89. print()
  90. tmp = PRESETS['rainbow'].color_text('preset')
  91. preset = literal_input(f'Which {tmp} do you want to use?', PRESETS.keys(), 'rainbow')
  92. # Create config
  93. c = Config(preset, color_system)
  94. # Save config
  95. save = literal_input(f'Save config?', ['y', 'n'], 'y')
  96. if save == 'y':
  97. c.save()
  98. return c
  99. def run():
  100. # Create CLI
  101. hyfetch = color('&b&lhy&f&lfetch&r')
  102. parser = argparse.ArgumentParser(description=color(f'{hyfetch} - neofetch with flags <3'))
  103. parser.add_argument('-c', '--config', action='store_true', help=color(f'Configure {hyfetch}'))
  104. parser.add_argument('-p', '--preset', help=f'Use preset', choices=PRESETS.keys())
  105. parser.add_argument('-m', '--mode', help=f'Color mode', choices=['8bit', 'rgb'])
  106. parser.add_argument('--c-scale', dest='scale', help=f'Lighten colors by a multiplier', type=float)
  107. parser.add_argument('--c-set-l', dest='light', help=f'Set lightness value of the colors', type=float)
  108. args = parser.parse_args()
  109. # Load config
  110. config = check_config()
  111. # Reset config
  112. if args.config:
  113. config = create_config()
  114. # Param overwrite config
  115. if args.preset:
  116. config.preset = args.preset
  117. if args.mode:
  118. config.mode = args.mode
  119. preset = PRESETS.get(config.preset)
  120. # Lighten
  121. if args.scale:
  122. preset = ColorProfile([c.lighten(args.scale) for c in preset.colors])
  123. if args.light:
  124. preset = ColorProfile([c.set_light(args.light) for c in preset.colors])
  125. # Run
  126. run_neofetch(preset, config.mode)