168 lines
4.5 KiB
Python
Executable file
168 lines
4.5 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
from hypy_utils import printc, json_stringify, color
|
|
|
|
from .color_util import AnsiMode
|
|
from .neofetch_util import run_neofetch
|
|
from .presets import PRESETS, ColorProfile
|
|
|
|
CONFIG_PATH = Path.home() / '.config/hyfetch.json'
|
|
CONFIG_PATH.parent.mkdir(exist_ok=True, parents=True)
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
preset: str
|
|
mode: AnsiMode
|
|
|
|
def save(self):
|
|
CONFIG_PATH.write_text(json_stringify(self), 'utf-8')
|
|
|
|
|
|
def check_config() -> Config:
|
|
"""
|
|
Check if the configuration exists. Return the config object if it exists. If not, call the
|
|
config creator
|
|
|
|
TODO: Config path param
|
|
|
|
:return: Config object
|
|
"""
|
|
if CONFIG_PATH.is_file():
|
|
return Config(**json.loads(CONFIG_PATH.read_text('utf-8')))
|
|
|
|
return create_config()
|
|
|
|
|
|
def literal_input(prompt: str, options: Iterable[str], default: str) -> str:
|
|
"""
|
|
Ask the user to provide an input among a list of options
|
|
|
|
:param prompt: Input prompt
|
|
:param options: Options
|
|
:param default: Default option
|
|
:return: Selection
|
|
"""
|
|
options = list(options)
|
|
lows = [o.lower() for o in options]
|
|
|
|
op_text = '|'.join([f'&l&n{o}&r' if o == default else o for o in options])
|
|
printc(f'{prompt} ({op_text})')
|
|
selection = input('> ') or default
|
|
while not selection.lower() in lows:
|
|
print(f'Invalid selection! {selection} is not one of {"|".join(options)}')
|
|
selection = input('> ') or default
|
|
print()
|
|
|
|
return options[lows.index(selection)]
|
|
|
|
|
|
def center_text(txt: str, spaces: int) -> str:
|
|
"""
|
|
Put the text in the center in a defined space
|
|
|
|
>>> center_text('meow', 9)
|
|
' meow '
|
|
|
|
:param txt: Text
|
|
:param spaces: Total space of the text
|
|
:return: Text with length spaces
|
|
"""
|
|
spaces -= len(txt)
|
|
|
|
if spaces % 2 == 1:
|
|
spaces -= 1
|
|
txt += ' '
|
|
|
|
while spaces > 0:
|
|
spaces -= 2
|
|
txt = f' {txt} '
|
|
|
|
return txt
|
|
|
|
|
|
def create_config() -> Config:
|
|
"""
|
|
Create config interactively
|
|
|
|
:return: Config object (automatically stored)
|
|
"""
|
|
# Select color system
|
|
# TODO: Demo of each color system
|
|
color_system = literal_input('Which &acolor &bsystem &rdo you want to use?',
|
|
['8bit', 'rgb'], 'rgb')
|
|
|
|
# Print preset
|
|
print('Available presets:\n')
|
|
spacing = max(max(len(k) for k in PRESETS.keys()), 30)
|
|
flags = []
|
|
for name, preset in PRESETS.items():
|
|
flags.append([preset.color_text(' ' * spacing, foreground=False),
|
|
'&0' + preset.color_text(center_text(name, spacing), foreground=False),
|
|
preset.color_text(' ' * spacing, foreground=False)])
|
|
flags_per_row = 3
|
|
while flags:
|
|
current = flags[:flags_per_row]
|
|
flags = flags[flags_per_row:]
|
|
for line in range(len(current[0])):
|
|
printc(' '.join(flag[line] for flag in current))
|
|
print()
|
|
|
|
print()
|
|
tmp = PRESETS['rainbow'].color_text('preset')
|
|
preset = literal_input(f'Which {tmp} do you want to use?', PRESETS.keys(), 'rainbow')
|
|
|
|
# Create config
|
|
c = Config(preset, color_system)
|
|
|
|
# Save config
|
|
save = literal_input(f'Save config?', ['y', 'n'], 'y')
|
|
if save == 'y':
|
|
c.save()
|
|
|
|
return c
|
|
|
|
|
|
def run():
|
|
# Create CLI
|
|
hyfetch = color('&b&lhy&f&lfetch&r')
|
|
parser = argparse.ArgumentParser(description=color(f'{hyfetch} - neofetch with flags <3'))
|
|
|
|
parser.add_argument('-c', '--config', action='store_true', help=color(f'Configure {hyfetch}'))
|
|
parser.add_argument('-p', '--preset', help=f'Use preset', choices=PRESETS.keys())
|
|
parser.add_argument('-m', '--mode', help=f'Color mode', choices=['8bit', 'rgb'])
|
|
parser.add_argument('--c-scale', dest='scale', help=f'Lighten colors by a multiplier', type=float)
|
|
parser.add_argument('--c-set-l', dest='light', help=f'Set lightness value of the colors', type=float)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Load config
|
|
config = check_config()
|
|
|
|
# Reset config
|
|
if args.config:
|
|
config = create_config()
|
|
|
|
# Param overwrite config
|
|
if args.preset:
|
|
config.preset = args.preset
|
|
if args.mode:
|
|
config.mode = args.mode
|
|
|
|
preset = PRESETS.get(config.preset)
|
|
|
|
# Lighten
|
|
if args.scale:
|
|
preset = ColorProfile([c.lighten(args.scale) for c in preset.colors])
|
|
if args.light:
|
|
preset = ColorProfile([c.set_light(args.light) for c in preset.colors])
|
|
|
|
# Run
|
|
run_neofetch(preset, config.mode)
|