Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 512d40f4de | |||
| 17a28c0495 | |||
| de0d381ee2 | |||
| 4835bbba40 | |||
| e35db2b838 | |||
| 9c187da44a | |||
| 0d5cb3da51 | |||
| 255e1d3f99 | |||
| 9dfbeeb3fe |
@@ -19,21 +19,13 @@ pip install hyfetch
|
||||
Currently, these distributions have existing packages for HyFetch:
|
||||
|
||||
* ArchLinux: `yay -S hyfetch` (Thanks to @ Aleksana)
|
||||
* Nix (Nixpkgs): `nix-env -i hyfetch` ([In Progress](https://github.com/NixOS/nixpkgs/pull/170309))
|
||||
* Nix (NUR): ([In Progress](https://github.com/nix-community/NUR/pull/467))
|
||||
* Nix (Nixpkgs): `nix-env -i hyfetch` ([In Progress](https://github.com/NixOS/nixpkgs/pull/170309))
|
||||
* Nix ([NUR](nur.nix-community.org)): Install package `nur.repos.YisuiMilena.hyfetch`. (Thanks to @ YisuiDenghua)
|
||||
* Guix: `guix install hyfetch` (Thanks to @ WammKD)
|
||||
|
||||
Currently, if you're using Nix the package manager or NixOS, you can use HyFetch with `nix-env -if https://github.com/hykilpikonna/hyfetch/tarball/master -A hyfetch`
|
||||
|
||||
> Now `hyfetch` is available in our NixOS-CN's flake. You can add [NixOS-CN](https://github.com/nixos-cn/flakes) in your [Nix Flake](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html) at first, then install package `hyfetch`.
|
||||
> ```
|
||||
> #flake.nix
|
||||
>
|
||||
> environment.systemPackages =
|
||||
> [ nixos-cn.legacyPackages.${system}.hyfetch ];
|
||||
>
|
||||
> ```
|
||||
> (Thanks to @ YisuiDenghua and @ linyinfeng )
|
||||
> `hyfetch` is also available in our NixOS-CN's flake. You can add [NixOS-CN](https://github.com/nixos-cn/flakes) in your [Nix Flake](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html) at first, then install package `hyfetch`. (Thanks to @ YisuiDenghua and @ linyinfeng )
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from numpy import ndarray
|
||||
|
||||
from .color_util import RGB
|
||||
|
||||
|
||||
def create_gradient_hex(colors: list[str], resolution: int = 300) -> ndarray:
|
||||
"""
|
||||
Create gradient array from hex
|
||||
"""
|
||||
colors = np.array([RGB.from_hex(s) for s in colors])
|
||||
return create_gradient(colors, resolution)
|
||||
|
||||
|
||||
def create_gradient(colors: ndarray, resolution: int) -> ndarray:
|
||||
"""
|
||||
Create gradient 2d array.
|
||||
|
||||
Usage: arr[ratio / len(arr), :] = Scaled gradient color at that point
|
||||
"""
|
||||
result = np.zeros((resolution * (len(colors) - 1), 3), dtype='uint8')
|
||||
|
||||
# Create gradient mapping
|
||||
for i in range(len(colors) - 1):
|
||||
c1 = colors[i, :]
|
||||
c2 = colors[i + 1, :]
|
||||
bi = i * resolution
|
||||
|
||||
for r in range(resolution):
|
||||
ratio = r / resolution
|
||||
result[bi + r, :] = c2 * ratio + c1 * (1 - ratio)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_raw(gradient: ndarray, ratio: float) -> ndarray:
|
||||
"""
|
||||
:param gradient: Gradient array (2d)
|
||||
:param ratio: Between 0-1
|
||||
:return: RGB subarray (1d, has 3 values)
|
||||
"""
|
||||
if ratio == 1:
|
||||
return gradient[-1, :]
|
||||
|
||||
i = int(ratio * len(gradient))
|
||||
return gradient[i, :]
|
||||
|
||||
|
||||
class Scale:
|
||||
colors: ndarray
|
||||
rgb: ndarray
|
||||
|
||||
def __init__(self, scale: list[str], resolution: int = 300):
|
||||
self.colors = np.array([RGB.from_hex(s) for s in scale])
|
||||
self.rgb = create_gradient(self.colors, resolution)
|
||||
|
||||
def __call__(self, ratio: float) -> RGB:
|
||||
"""
|
||||
:param ratio: Between 0-1
|
||||
"""
|
||||
return RGB(*get_raw(self.rgb, ratio))
|
||||
|
||||
|
||||
def test_color_scale():
|
||||
scale = Scale(['#232323', '#4F1879', '#B43A78', '#F98766', '#FCFAC0'])
|
||||
|
||||
colors = 100
|
||||
for i in range(colors + 1):
|
||||
print(scale(i / colors).to_ansi_rgb(False), end=' ')
|
||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
from typing_extensions import Literal
|
||||
|
||||
CONFIG_PATH = Path.home() / '.config/hyfetch.json'
|
||||
VERSION = '1.1.2'
|
||||
VERSION = '1.1.3-pre.1'
|
||||
|
||||
# Obtain terminal size
|
||||
try:
|
||||
|
||||
+45
-24
@@ -13,7 +13,8 @@ from hyfetch import presets
|
||||
from .color_util import printc, color, clear_screen, LightDark
|
||||
from .constants import CONFIG_PATH, VERSION, TERM_LEN, TEST_ASCII_WIDTH, TEST_ASCII, GLOBAL_CFG
|
||||
from .models import Config
|
||||
from .neofetch_util import run_neofetch, get_distro_ascii, ColorAlignment, ascii_size, color_alignments
|
||||
from .neofetch_util import run_neofetch, get_distro_ascii, ColorAlignment, ascii_size, fore_back, \
|
||||
get_fore_back
|
||||
from .presets import PRESETS
|
||||
|
||||
|
||||
@@ -54,13 +55,29 @@ def literal_input(prompt: str, options: Iterable[str], default: str, show_ops: b
|
||||
else:
|
||||
printc(f'{prompt} (default: {default})')
|
||||
|
||||
selection = input('> ') or default
|
||||
while not selection.lower() in lows:
|
||||
def find_selection(sel: str):
|
||||
if not sel:
|
||||
return None
|
||||
|
||||
# Find exact match
|
||||
if sel in lows:
|
||||
return options[lows.index(sel)]
|
||||
|
||||
# Find starting abbreviation
|
||||
for i, op in enumerate(lows):
|
||||
if op.startswith(sel):
|
||||
return options[i]
|
||||
|
||||
return None
|
||||
|
||||
selection = input('> ').lower() or default
|
||||
while not find_selection(selection):
|
||||
print(f'Invalid selection! {selection} is not one of {"|".join(options)}')
|
||||
selection = input('> ') or default
|
||||
selection = input('> ').lower() or default
|
||||
|
||||
print()
|
||||
|
||||
return options[lows.index(selection)]
|
||||
return find_selection(selection)
|
||||
|
||||
|
||||
def create_config() -> Config:
|
||||
@@ -181,29 +198,30 @@ def create_config() -> Config:
|
||||
color_alignment = None
|
||||
while True:
|
||||
clear_screen(title)
|
||||
printc(f'&a5. Let\'s choose a color arrangement!')
|
||||
printc(f'You can choose standard horizontal or vertical alignment, or use one of the random color schemes, or assign colors yourself (TODO).')
|
||||
print()
|
||||
|
||||
asc = get_distro_ascii()
|
||||
asc_width = ascii_size(asc)[0]
|
||||
asciis = [
|
||||
[*ColorAlignment('horizontal').recolor_ascii(asc, _prs).split('\n'), 'Horizontal'.center(asc_width)],
|
||||
[*ColorAlignment('vertical').recolor_ascii(asc, _prs).split('\n'), 'Vertical'.center(asc_width)],
|
||||
fore_back = get_fore_back()
|
||||
arrangements = [
|
||||
('Horizontal', ColorAlignment('horizontal', fore_back=fore_back)),
|
||||
('Vertical', ColorAlignment('vertical'))
|
||||
]
|
||||
ascii_per_row = TERM_LEN // (asc_width + 2)
|
||||
|
||||
# Random color schemes
|
||||
# ascii_indices =
|
||||
pis = list(range(len(_prs.unique_colors().colors)))
|
||||
while len(pis) < len(set(re.findall('(?<=\\${c)[0-9](?=})', asc))):
|
||||
slots = len(set(re.findall('(?<=\\${c)[0-9](?=})', asc)))
|
||||
while len(pis) < slots:
|
||||
pis += pis
|
||||
perm = list(permutations(pis))
|
||||
perm = {p[:slots] for p in permutations(pis)}
|
||||
random_count = ascii_per_row * 2 - 2
|
||||
choices = random.sample(perm, random_count)
|
||||
choices = [{i: n for i, n in enumerate(c)} for c in choices]
|
||||
asciis += [[*ColorAlignment('custom', r).recolor_ascii(asc, _prs).split('\n'), f'random{i}'.center(asc_width)]
|
||||
for i, r in enumerate(choices)]
|
||||
if random_count > len(perm):
|
||||
choices = perm
|
||||
else:
|
||||
choices = random.sample(perm, random_count)
|
||||
choices = [{i + 1: n for i, n in enumerate(c)} for c in choices]
|
||||
arrangements += [(f'random{i}', ColorAlignment('custom', r)) for i, r in enumerate(choices)]
|
||||
asciis = [[*ca.recolor_ascii(asc, _prs).split('\n'), k.center(asc_width)] for k, ca in arrangements]
|
||||
|
||||
while asciis:
|
||||
current = asciis[:ascii_per_row]
|
||||
@@ -213,6 +231,8 @@ def create_config() -> Config:
|
||||
[printc(' '.join(line)) for line in zip(*current)]
|
||||
print()
|
||||
|
||||
printc(f'&a5. Let\'s choose a color arrangement!')
|
||||
printc(f'You can choose standard horizontal or vertical alignment, or use one of the random color schemes.')
|
||||
print('You can type "roll" to randomize again.')
|
||||
print()
|
||||
choice = literal_input(f'Your choice?', ['horizontal', 'vertical', 'roll'] + [f'random{i}' for i in range(random_count)], 'horizontal')
|
||||
@@ -220,12 +240,13 @@ def create_config() -> Config:
|
||||
if choice == 'roll':
|
||||
continue
|
||||
|
||||
if choice in ['horizontal', 'vertical']:
|
||||
color_alignment = ColorAlignment(choice)
|
||||
elif choice.startswith('random'):
|
||||
color_alignment = ColorAlignment('custom', choices[int(choice[6])])
|
||||
# Save choice
|
||||
arrangement_index = {k.lower(): ca for k, ca in arrangements}
|
||||
if choice in arrangement_index:
|
||||
color_alignment = arrangement_index[choice]
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
print('Invalid choice.')
|
||||
continue
|
||||
|
||||
break
|
||||
|
||||
@@ -309,7 +330,7 @@ def run():
|
||||
# Debug recommendations
|
||||
if args.debug_list:
|
||||
distro = args.debug_list
|
||||
ca = color_alignments[distro]
|
||||
ca = fore_back[distro]
|
||||
|
||||
print(distro)
|
||||
GLOBAL_CFG.override_distro = distro
|
||||
|
||||
@@ -150,6 +150,10 @@ def get_distro_ascii(distro: str | None = None) -> str:
|
||||
return normalize_ascii(check_output([get_command_path(), cmd]).decode().strip())
|
||||
|
||||
|
||||
def get_distro_name():
|
||||
return check_output([get_command_path(), 'ascii_distro_name']).decode().strip()
|
||||
|
||||
|
||||
def run_neofetch(preset: ColorProfile, alignment: ColorAlignment):
|
||||
asc = get_distro_ascii()
|
||||
w, h = ascii_size(asc)
|
||||
@@ -179,12 +183,26 @@ def run_neofetch(preset: ColorProfile, alignment: ColorAlignment):
|
||||
subprocess.run(full_cmd)
|
||||
|
||||
|
||||
# Color alignment recommendations
|
||||
color_alignments = {
|
||||
'fedora': ColorAlignment('horizontal', fore_back=(2, 1)),
|
||||
'ubuntu': ColorAlignment('horizontal', fore_back=(2, 1)),
|
||||
'NixOS.*': ColorAlignment('custom', {1: 1, 2: 0}),
|
||||
# 'arch': ColorAlignment('horizontal'),
|
||||
# 'centos': ColorAlignment('horizontal'),
|
||||
def get_fore_back(distro: str | None = None) -> tuple[int, int] | None:
|
||||
"""
|
||||
Get recommended foreground-background configuration for distro, or None if the distro ascii is
|
||||
not suitable for fore-back configuration.
|
||||
|
||||
:return:
|
||||
"""
|
||||
if not distro and GLOBAL_CFG.override_distro:
|
||||
distro = GLOBAL_CFG.override_distro
|
||||
if not distro:
|
||||
distro = get_distro_name().lower()
|
||||
for k, v in fore_back.items():
|
||||
if distro.startswith(k.lower()):
|
||||
return v
|
||||
return None
|
||||
|
||||
|
||||
# Foreground-background recommendation
|
||||
fore_back = {
|
||||
'fedora': (2, 1),
|
||||
'ubuntu': (2, 1),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user