Compare commits

...

28 Commits

Author SHA1 Message Date
Azalea (on HyDEV-Daisy) 2c8261dc9a [F] Make config path only when it's needed 2022-04-25 14:38:59 -04:00
Azalea (on HyDEV-Daisy) 3219547c92 [U] Update changelog 2022-04-25 14:06:51 -04:00
Azalea (on HyDEV-Daisy) b0bc4e64a9 [O] Remove HyPyUtils Dependency 2022-04-25 14:05:20 -04:00
Azalea (on HyDEV-Daisy) 7bb049ea20 [U] Release v1.0.5 2022-04-25 03:23:50 -04:00
Hykilpikonna 73becf78c4 [U] Update changelog 2022-04-25 03:22:54 -04:00
Hykilpikonna 7f949fe6b2 [PR] #2 coloursofnoise - Fix terminal emulator detection
Fix terminal emulator detection
2022-04-25 03:21:51 -04:00
coloursofnoise 9abdae5fb4 Fix terminal emulator detection 2022-04-20 13:03:07 -07:00
Azalea (on HyDEV-Daisy) 6ff45d0edd [+] Add AUR package 2022-04-16 00:45:15 -04:00
Hykilpikonna 99f99efc1c [U] Link pull request 2022-04-14 19:35:58 -04:00
Azalea (on HyDEV-Daisy) 0c08b3950f [U] Update changelog 2022-04-14 19:34:48 -04:00
Azalea (on HyDEV-Daisy) 2fc419476d [U] Release v1.0.4 - more flags! 2022-04-14 19:33:56 -04:00
Hykilpikonna abac3b2bb3 [PR] Merge pull request #1 from SadiePi/flagcolorcodes
Add some flags from flagcolorcodes.com
2022-04-12 14:29:53 -04:00
Azalea (on HyDEV-Daisy) 43924305b9 [U] Dynamic dependency version 2022-04-11 01:45:15 -04:00
Sadie Dotzler 29f771caec remove temporary alias 2022-04-10 22:04:45 -07:00
Sadie Dotzler 35f5e6eec9 flagcolorcodes page 1 2022-04-10 21:51:21 -07:00
Hykilpikonna 0a7356a560 [U] Update todo list 2022-04-10 23:50:13 -04:00
Hykilpikonna 6a5edd037a [U] Add nixos readme 2022-04-10 23:43:11 -04:00
Azalea (on HyDEV-Daisy) 2b5ef302a5 [F] Fix missing dependency for setuptools 2022-04-10 23:27:10 -04:00
Azalea (on HyDEV-Daisy) 81364f55a2 [+] Changelog 2022-04-10 22:58:43 -04:00
Azalea (on HyDEV-Daisy) 6209018caa [U] Release v1.0.2 2022-04-10 22:50:37 -04:00
Azalea (on HyDEV-Daisy) b9dfa5e200 [+] Python 3.7 3.8 support 2022-04-10 22:50:11 -04:00
Azalea (on HyDEV-Daisy) 9ec3f74c0d [O] Optimize grayscale 2022-04-10 22:45:56 -04:00
Azalea (on HyDEV-Daisy) 39e14aec90 [F] Fix RGB to 8bit conversion 2022-04-10 22:43:34 -04:00
Azalea (on HyDEV-Daisy) 5d08179cea [+] Add 8bit support 2022-04-10 22:28:35 -04:00
Hykilpikonna 1ff2ea73ec [+] Write readme 2022-04-10 07:15:52 -04:00
Hykilpikonna 71fb76d4f7 [U] Add macos example 2022-04-10 18:49:51 +08:00
Hykilpikonna a687cb328e [U] Add images in readme 2022-04-10 06:49:20 -04:00
Azalea (on HyDEV-Daisy) 0a6a61a013 [+] Deploy script 2022-04-10 06:45:53 -04:00
11 changed files with 406 additions and 23 deletions
+89
View File
@@ -1,3 +1,92 @@
# HyFetch
neofetch with pride flags <3
![image](https://user-images.githubusercontent.com/22280294/162614541-af2b4660-f1f7-4287-b978-1aa2266ac70f.png)
## Installation
### Method 1: Install using Python pip (Recommended)
Install Python >= 3.7 first. Then, just do:
```sh
pip install hyfetch
```
### Method 2: Install using system package manager
Currently, these distributions have existing packages for HyFetch:
* ArchLinux: `yay -S hyfetch` (Thanks to @ Aleksana)
* Guix: [In progress](https://issues.guix.gnu.org/54847#8-lineno27)
## Usage
When you run `hyfetch` for the first time, it will prompt you to choose a color system and a preset. Just follow the prompt, and everything should work (hopefully). If something doesn't work, feel free to submit an issue!
#### Q: How do I change my config?
A: Use `hyfetch -c`
#### Q: What do I do if the color is too dark/light for my theme?
A: You can try setting the colors' "lightness" using the `--c-set-l` parameter. The value should be between 0 and 1. For example, if you are using dark theme and the rainbow flag is too dark to display, you can type:
```sh
hyfetch -p rainbow --c-set-l 0.8
```
Feel free to experiment with it!
![image](https://user-images.githubusercontent.com/22280294/162614553-eb758e4e-1936-472c-8ca7-b601c696c6eb.png)
## Change Log
### TODO
* [ ] Add interactive configurator for adjusting brightness
* [ ] Add configuration to emphasize certain parts of the original ASCII art (to make icons like Fedora and Ubuntu look nicer)
### 1.0.7
* Fix: Make config path not on init but when it's actually needed.
### 1.0.6
* Remove `hypy_utils` dependency to make packaging easier.
### 1.0.5
* Fix terminal emulator detection ([PR #2](https://github.com/hykilpikonna/hyfetch/pull/2))
### 1.0.4
* Add more flags ([PR #1](https://github.com/hykilpikonna/hyfetch/pull/1))
### 1.0.3
* Fix missing dependency for setuptools
### 1.0.2
* Implement RGB to 8bit conversion
* Add support for Python 3.7 and 3.8
### 1.0.1
* Included 11 flag presets
* Ability to lighten colors with `--c-set-l <lightness>`
* Command-line flag chooser
* Supports Python >= 3.9
## More Screenshots
![image](https://user-images.githubusercontent.com/22280294/162614578-3b878abb-2a32-4427-997e-f90b3f5cfd7c.png)
![image](https://user-images.githubusercontent.com/22280294/162661621-f1c61338-7857-4d3f-9fe3-c6b635d68c38.png)
## Original Readme from Neofetch Below
<h3 align="center"><img src="https://i.imgur.com/ZQI2EYz.png" alt="logo" height="100px"></h3> <h3 align="center"><img src="https://i.imgur.com/ZQI2EYz.png" alt="logo" height="100px"></h3>
<p align="center">A command-line system information tool written in bash 3.2+</p> <p align="center">A command-line system information tool written in bash 3.2+</p>
Executable
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Stop on error
set -e
# Remove old build
rm -rf dist/*
rm -rf build/*
# Build
python setup.py sdist bdist_wheel
# Check built files
twine check dist/*
# Upload
twine upload dist/*
+5 -1
View File
@@ -1,6 +1,10 @@
__version__ = '1.0.1' from __future__ import annotations
from . import main from . import main
__version__ = main.VERSION
if __name__ == '__main__': if __name__ == '__main__':
main.run() main.run()
+74 -4
View File
@@ -1,5 +1,52 @@
from __future__ import annotations
import colorsys import colorsys
from typing import NamedTuple from typing import NamedTuple
from typing_extensions import Literal
AnsiMode = Literal['default', 'ansi', '8bit', 'rgb']
MINECRAFT_COLORS = ["&0/\033[0;30m", "&1/\033[0;34m", "&2/\033[0;32m", "&3/\033[0;36m", "&4/\033[0;31m",
"&5/\033[0;35m", "&6/\033[0;33m", "&7/\033[0;37m", "&8/\033[1;30m", "&9/\033[1;34m",
"&a/\033[1;32m", "&b/\033[1;36m", "&c/\033[1;31m", "&d/\033[1;35m", "&e/\033[1;33m",
"&f/\033[1;37m",
"&r/\033[0m", "&l/\033[1m", "&o/\033[3m", "&n/\033[4m", "&-/\n"]
MINECRAFT_COLORS = [(r[:2], r[3:]) for r in MINECRAFT_COLORS]
def color(msg: str) -> str:
"""
Replace extended minecraft color codes in string
:param msg: Message with minecraft color codes
:return: Message with escape codes
"""
for code, esc in MINECRAFT_COLORS:
msg = msg.replace(code, esc)
while '&gf(' in msg or '&gb(' in msg:
i = msg.index('&gf(') if '&gf(' in msg else msg.index('&gb(')
end = msg.index(')', i)
code = msg[i + 4:end]
fore = msg[i + 2] == 'f'
if code.startswith('#'):
rgb = tuple(int(code.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
else:
code = code.replace(',', ' ').replace(';', ' ').replace(' ', ' ')
rgb = tuple(int(c) for c in code.split(' '))
msg = msg[:i] + RGB(*rgb).to_ansi_rgb(foreground=fore) + msg[end + 1:]
return msg
def printc(msg: str):
"""
Print with color
:param msg: Message with minecraft color codes
"""
print(color(msg + '&r'))
def redistribute_rgb(r: int, g: int, b: int) -> tuple[int, int, int]: def redistribute_rgb(r: int, g: int, b: int) -> tuple[int, int, int]:
@@ -61,17 +108,32 @@ class RGB(NamedTuple):
c = '38' if foreground else '48' c = '38' if foreground else '48'
return f'\033[{c};2;{self.r};{self.g};{self.b}m' return f'\033[{c};2;{self.r};{self.g};{self.b}m'
def to_ansi_256(self, foreground: bool = True) -> str: def to_ansi_8bit(self, foreground: bool = True) -> str:
""" """
Convert RGB to ANSI 256 Color Escape Code. Convert RGB to ANSI 8bit 256 Color Escape Code.
This encoding supports 256 colors in total. This encoding supports 256 colors in total.
:return: ANSI 256 escape code like \033[38;5;206m' :return: ANSI 256 escape code like \033[38;5;206m'
""" """
raise NotImplementedError() r, g, b = self.r, self.g, self.b
sep = 42.5
def to_ansi_16(self) -> str: while True:
if r < sep or g < sep or b < sep:
gray = r < sep and g < sep and b < sep
break
sep += 42.5
if gray:
color = 232 + (r + g + b) / 33
else:
color = 16 + int(r / 256. * 6) * 36 + int(g / 256. * 6) * 6 + int(b / 256. * 6)
c = '38' if foreground else '48'
return f'\033[{c};5;{int(color)}m'
def to_ansi_16(self, foreground: bool = True) -> str:
""" """
Convert RGB to ANSI 16 Color Escape Code Convert RGB to ANSI 16 Color Escape Code
@@ -79,6 +141,14 @@ class RGB(NamedTuple):
""" """
raise NotImplementedError() raise NotImplementedError()
def to_ansi(self, mode: AnsiMode, foreground: bool = True):
if mode == 'rgb':
return self.to_ansi_rgb(foreground)
if mode == '8bit':
return self.to_ansi_8bit(foreground)
if mode == 'ansi':
return self.to_ansi_16(foreground)
def lighten(self, multiplier: float) -> 'RGB': def lighten(self, multiplier: float) -> 'RGB':
""" """
Lighten the color by a multiplier Lighten the color by a multiplier
+15 -8
View File
@@ -1,26 +1,28 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from __future__ import annotations
import argparse import argparse
import json import json
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Literal, Iterable from typing import Iterable
from hypy_utils import printc, json_stringify, color
from .color_util import AnsiMode, printc, color
from .neofetch_util import run_neofetch from .neofetch_util import run_neofetch
from .presets import PRESETS, ColorProfile from .presets import PRESETS, ColorProfile
from .serializer import json_stringify
CONFIG_PATH = Path.home() / '.config/hyfetch.json' CONFIG_PATH = Path.home() / '.config/hyfetch.json'
CONFIG_PATH.parent.mkdir(exist_ok=True, parents=True) VERSION = '1.0.7'
@dataclass @dataclass
class Config: class Config:
preset: str preset: str
mode: Literal['default', 'ansi', '8bit', 'rgb'] mode: AnsiMode
def save(self): def save(self):
CONFIG_PATH.parent.mkdir(exist_ok=True, parents=True)
CONFIG_PATH.write_text(json_stringify(self), 'utf-8') CONFIG_PATH.write_text(json_stringify(self), 'utf-8')
@@ -95,7 +97,7 @@ def create_config() -> Config:
# Select color system # Select color system
# TODO: Demo of each color system # TODO: Demo of each color system
color_system = literal_input('Which &acolor &bsystem &rdo you want to use?', color_system = literal_input('Which &acolor &bsystem &rdo you want to use?',
['ansi', '8bit', 'rgb'], 'rgb') ['8bit', 'rgb'], 'rgb')
# Print preset # Print preset
print('Available presets:\n') print('Available presets:\n')
@@ -135,12 +137,17 @@ def run():
parser.add_argument('-c', '--config', action='store_true', help=color(f'Configure {hyfetch}')) 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('-p', '--preset', help=f'Use preset', choices=PRESETS.keys())
parser.add_argument('-m', '--mode', help=f'Color mode', choices=['ansi', '8bit', 'rgb']) 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-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) parser.add_argument('--c-set-l', dest='light', help=f'Set lightness value of the colors', type=float)
parser.add_argument('-V', '--version', dest='version', action='store_true', help=f'Check version')
args = parser.parse_args() args = parser.parse_args()
if args.version:
print(f'Version is {VERSION}')
return
# Load config # Load config
config = check_config() config = check_config()
@@ -163,4 +170,4 @@ def run():
preset = ColorProfile([c.set_light(args.light) for c in preset.colors]) preset = ColorProfile([c.set_light(args.light) for c in preset.colors])
# Run # Run
run_neofetch(preset) run_neofetch(preset, config.mode)
+5 -2
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import os import os
import re import re
from pathlib import Path from pathlib import Path
@@ -6,6 +8,7 @@ from tempfile import TemporaryDirectory
import pkg_resources import pkg_resources
from .color_util import AnsiMode
from .presets import ColorProfile from .presets import ColorProfile
@@ -27,7 +30,7 @@ def get_distro_ascii() -> str:
return check_output([get_command_path(), "print_ascii"]).decode().strip() return check_output([get_command_path(), "print_ascii"]).decode().strip()
def run_neofetch(preset: ColorProfile): def run_neofetch(preset: ColorProfile, mode: AnsiMode):
# Get existing ascii # Get existing ascii
asc = get_distro_ascii() asc = get_distro_ascii()
@@ -37,7 +40,7 @@ def run_neofetch(preset: ColorProfile):
# Add new colors # Add new colors
lines = asc.split('\n') lines = asc.split('\n')
colors = preset.with_length(len(lines)) colors = preset.with_length(len(lines))
asc = '\n'.join([colors[i].to_ansi_rgb() + l for i, l in enumerate(lines)]) asc = '\n'.join([colors[i].to_ansi(mode) + l for i, l in enumerate(lines)])
# Write temp file # Write temp file
with TemporaryDirectory() as tmp_dir: with TemporaryDirectory() as tmp_dir:
+127 -3
View File
@@ -1,7 +1,6 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from typing_extensions import Literal
from typing import Literal, Optional
from .color_util import RGB from .color_util import RGB
@@ -82,7 +81,6 @@ class ColorProfile:
result += '\033[0m' result += '\033[0m'
return result return result
PRESETS: dict[str, ColorProfile] = { PRESETS: dict[str, ColorProfile] = {
'rainbow': ColorProfile([ 'rainbow': ColorProfile([
'#E50000', '#E50000',
@@ -158,4 +156,130 @@ PRESETS: dict[str, ColorProfile] = {
'#ABABAB', '#ABABAB',
'#000000' '#000000'
]), ]),
# below sourced from https://www.flagcolorcodes.com/flags/pride
# goto f"https://www.flagcolorcodes.com/{preset}" for info
# todo: sane sorting
'autosexual': ColorProfile([
'#99D9EA',
'#7F7F7F'
]),
'intergender': ColorProfile([
# todo: use weighted spacing
'#900DC2',
'#900DC2',
'#FFE54F',
'#900DC2',
'#900DC2',
]),
'greygender': ColorProfile([
'#B3B3B3',
'#B3B3B3',
'#FFFFFF',
'#062383',
'#062383',
'#FFFFFF',
'#535353',
'#535353',
]),
'akiosexual': ColorProfile([
'#F9485E',
'#FEA06A',
'#FEF44C',
'#FFFFFF',
'#000000',
]),
'transmasculine': ColorProfile([
'#FF8ABD',
'#CDF5FE',
'#9AEBFF',
'#74DFFF',
'#9AEBFF',
'#CDF5FE',
'#FF8ABD',
]),
'demifaun': ColorProfile([
'#7F7F7F',
'#7F7F7F',
'#C6C6C6',
'#C6C6C6',
'#FCC688',
'#FFF19C',
'#FFFFFF',
'#8DE0D5',
'#9682EC',
'#C6C6C6',
'#C6C6C6',
'#7F7F7F',
'#7F7F7F',
]),
'neutrois': ColorProfile([
'#FFFFFF',
'#1F9F00',
'#000000'
]),
'biromantic alt 2': ColorProfile([
'#8869A5',
'#D8A7D8',
'#FFFFFF',
'#FDB18D',
'#151638',
]),
'biromantic alt 2': ColorProfile([
'#740194',
'#AEB1AA',
'#FFFFFF',
'#AEB1AA',
'#740194',
]),
'autoromantic': ColorProfile([ # symbol interpreted
'#99D9EA',
'#99D9EA',
'#99D9EA',
'#99D9EA',
'#99D9EA',
'#000000',
'#3DA542',
'#3DA542',
'#000000',
'#7F7F7F',
'#7F7F7F',
'#7F7F7F',
'#7F7F7F',
'#7F7F7F',
]),
# i didn't expect this one to work. cool!
'boyflux alt 2': ColorProfile([
'#E48AE4',
'#9A81B4',
'#55BFAB',
'#FFFFFF',
'#A8A8A8',
'#81D5EF',
'#81D5EF',
'#81D5EF',
'#81D5EF',
'#81D5EF',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#69ABE5',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
'#5276D4',
]),
} }
+43
View File
@@ -0,0 +1,43 @@
from __future__ import annotations
import dataclasses
import json
from datetime import datetime, date
class EnhancedJSONEncoder(json.JSONEncoder):
"""
An improvement to the json.JSONEncoder class, which supports:
encoding for dataclasses, encoding for datetime, and sets
"""
def default(self, o: object) -> object:
# Support encoding dataclasses
# https://stackoverflow.com/a/51286749/7346633
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
# Support encoding datetime
if isinstance(o, (datetime, date)):
return o.isoformat()
# Support for sets
# https://stackoverflow.com/a/8230505/7346633
if isinstance(o, set):
return list(o)
return super().default(o)
def json_stringify(obj: object, indent: int | None = None) -> str:
"""
Serialize json string with support for dataclasses and datetime and sets and with custom
configuration.
Preconditions:
- obj != None
:param obj: Objects
:param indent: Indent size or none
:return: Json strings
"""
return json.dumps(obj, indent=indent, cls=EnhancedJSONEncoder, ensure_ascii=False)
+1 -1
View File
@@ -3315,7 +3315,7 @@ get_term() {
name="$(get_process_name "$parent")" name="$(get_process_name "$parent")"
case ${name// } in case ${name// } in
"${SHELL/*\/}"|*"sh"|"screen"|"su"*|"newgrp") ;; "${SHELL/*\/}"|*"sh"|"screen"|"su"*|"newgrp"|"hyfetch") ;;
"login"*|*"Login"*|"init"|"(init)") "login"*|*"Login"*|"init"|"(init)")
term="$(tty)" term="$(tty)"
+6 -2
View File
@@ -1,6 +1,8 @@
import pathlib import pathlib
from setuptools import setup
import hyfetch import hyfetch
from setuptools import setup, find_packages
# The directory containing this file # The directory containing this file
HERE = pathlib.Path(__file__).parent HERE = pathlib.Path(__file__).parent
@@ -22,13 +24,15 @@ setup(
classifiers=[ classifiers=[
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
], ],
packages=['hyfetch'], packages=['hyfetch'],
package_data={'hyfetch': ['hyfetch/*']}, package_data={'hyfetch': ['hyfetch/*']},
include_package_data=True, include_package_data=True,
install_requires=['hypy_utils==1.0.5'], install_requires=['setuptools', 'typing_extensions'],
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"hyfetch=hyfetch.main:run", "hyfetch=hyfetch.main:run",
+24 -2
View File
@@ -1,4 +1,5 @@
from hyfetch.color_util import RGB from hyfetch.color_util import RGB, printc
from hyfetch.neofetch_util import get_command_path, run_neofetch
from hyfetch.presets import PRESETS from hyfetch.presets import PRESETS
@@ -6,10 +7,31 @@ def print_colors_test(colors: list[RGB]):
print(''.join(f'{c.to_ansi_rgb()}#' for c in colors)) print(''.join(f'{c.to_ansi_rgb()}#' for c in colors))
if __name__ == '__main__': def test_preset_length():
p = PRESETS.get('transgender') p = PRESETS.get('transgender')
print_colors_test(p.with_length(9)) print_colors_test(p.with_length(9))
print_colors_test(p.with_length(6)) print_colors_test(p.with_length(6))
p = PRESETS.get('nonbinary') p = PRESETS.get('nonbinary')
print_colors_test(p.with_length(7)) print_colors_test(p.with_length(7))
print_colors_test(p.with_length(6)) print_colors_test(p.with_length(6))
def test_command_path():
print(get_command_path())
def test_rgb_8bit_conversion():
for r in range(0, 255, 16):
for g in range(0, 255, 16):
print(RGB(r, g, 0).to_ansi_rgb(False), end=' ')
printc('&r')
print()
for r in range(0, 255, 16):
for g in range(0, 255, 16):
print(RGB(r, g, 0).to_ansi_8bit(False), end=' ')
printc('&r')
print()
if __name__ == '__main__':
test_rgb_8bit_conversion()