Browse Source

Merge branch 'master' into patch-1

Hykilpikonna 3 years ago
parent
commit
7aa46cb623
9 changed files with 126 additions and 56 deletions
  1. 3 1
      README.md
  2. 17 6
      hyfetch/color_util.py
  3. 24 13
      hyfetch/constants.py
  4. 31 27
      hyfetch/main.py
  5. 8 3
      hyfetch/models.py
  6. 7 1
      hyfetch/neofetch_util.py
  7. 26 5
      hyfetch/presets.py
  8. 5 0
      hyfetch/serializer.py
  9. 5 0
      neofetch

+ 3 - 1
README.md

@@ -21,9 +21,10 @@ Currently, these distributions have existing packages for HyFetch:
 * ArchLinux: `yay -S hyfetch` (Thanks to @ Aleksana)
 * ArchLinux: `yay -S hyfetch` (Thanks to @ Aleksana)
 * Nix (Nixpkgs): `nix-env -i hyfetch` ([In Progress](https://github.com/NixOS/nixpkgs/pull/170309))
 * 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 (NUR): ([In Progress](https://github.com/nix-community/NUR/pull/467))
-* Guix: [In progress](https://issues.guix.gnu.org/54847#8-lineno27)
+* 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`
 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`.
 > 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
 > #flake.nix
@@ -33,6 +34,7 @@ Currently, if you're using Nix the package manager or NixOS, you can use HyFetch
 >               
 >               
 > ```              
 > ```              
 > (Thanks to @ YisuiDenghua and @ linyinfeng )
 > (Thanks to @ YisuiDenghua and @ linyinfeng )
+
 ## Usage
 ## 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!
 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!

+ 17 - 6
hyfetch/color_util.py

@@ -1,13 +1,14 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
 import colorsys
 import colorsys
-from typing import NamedTuple
+from typing import NamedTuple, Callable, Optional
 
 
 from typing_extensions import Literal
 from typing_extensions import Literal
 
 
 from .constants import GLOBAL_CFG
 from .constants import GLOBAL_CFG
 
 
 AnsiMode = Literal['default', 'ansi', '8bit', 'rgb']
 AnsiMode = Literal['default', 'ansi', '8bit', 'rgb']
+LightDark = Literal['light', 'dark']
 
 
 
 
 MINECRAFT_COLORS = ["&0/\033[0;30m", "&1/\033[0;34m", "&2/\033[0;32m", "&3/\033[0;36m", "&4/\033[0;31m",
 MINECRAFT_COLORS = ["&0/\033[0;30m", "&1/\033[0;34m", "&2/\033[0;32m", "&3/\033[0;36m", "&4/\033[0;31m",
@@ -176,16 +177,26 @@ class RGB(NamedTuple):
         """
         """
         return RGB(*redistribute_rgb(*[v * multiplier for v in self]))
         return RGB(*redistribute_rgb(*[v * multiplier for v in self]))
 
 
-    def set_light(self, light: float) -> 'RGB':
+    def set_light(self, light: float, at_least: bool | None = None, at_most: bool | None = None) -> 'RGB':
         """
         """
         Set HSL lightness value
         Set HSL lightness value
 
 
         :param light: Lightness value (0-1)
         :param light: Lightness value (0-1)
+        :param at_least: Set the lightness to at least this value (no change if greater)
+        :param at_most: Set the lightness to at most this value (no change if lesser)
         :return: New color (original isn't modified)
         :return: New color (original isn't modified)
         """
         """
+        # Convert to HSL
         h, l, s = colorsys.rgb_to_hls(*[v / 255.0 for v in self])
         h, l, s = colorsys.rgb_to_hls(*[v / 255.0 for v in self])
-        return RGB(*[round(v * 255.0) for v in colorsys.hls_to_rgb(h, light, s)])
 
 
-    def set_min_light(self, light: float) -> 'RGB':
-        h, l, s = colorsys.rgb_to_hls(*[v / 255.0 for v in self])
-        return RGB(*[round(v * 255.0) for v in colorsys.hls_to_rgb(h, max(l, light), s)])
+        # Modify light value
+        if at_least is None and at_most is None:
+            l = light
+        else:
+            if at_most:
+                l = min(l, light)
+            if at_least:
+                l = max(l, light)
+
+        # Convert back to RGB
+        return RGB(*[round(v * 255.0) for v in colorsys.hls_to_rgb(h, l, s)])

+ 24 - 13
hyfetch/constants.py

@@ -4,8 +4,10 @@ import os
 from dataclasses import dataclass
 from dataclasses import dataclass
 from pathlib import Path
 from pathlib import Path
 
 
+from typing_extensions import Literal
+
 CONFIG_PATH = Path.home() / '.config/hyfetch.json'
 CONFIG_PATH = Path.home() / '.config/hyfetch.json'
-VERSION = '1.0.7'
+VERSION = '1.1.0'
 
 
 # Obtain terminal size
 # Obtain terminal size
 try:
 try:
@@ -14,20 +16,21 @@ except Exception:
     TERM_LEN = 40
     TERM_LEN = 40
 
 
 TEST_ASCII = r"""
 TEST_ASCII = r"""
-  |\___/|    
-  )     (    
- =\     /=   
-   )===(     
-  /     \    
-  |     |    
- / {txt} \   
- \       /   
-_/\_   _/_/\_
-|  |( (  |  |
-|  | ) ) |  |
-|  |(_(  |  |""".strip('\n')
+### |\___/| ###
+### )     ( ###
+## =\     /= ##
+#### )===( ####
+### /     \ ###
+### |     | ###
+## / {txt} \ ##
+## \       / ##
+_/\_\_   _/_/\_
+|##|  ( (  |##|
+|##|   ) ) |##|
+|##|  (_(  |##|""".strip('\n')
 
 
 TEST_ASCII_WIDTH = max(len(line) for line in TEST_ASCII.split('\n'))
 TEST_ASCII_WIDTH = max(len(line) for line in TEST_ASCII.split('\n'))
+DEFAULT_DARK_L = 0.
 
 
 @dataclass
 @dataclass
 class GlobalConfig:
 class GlobalConfig:
@@ -37,5 +40,13 @@ class GlobalConfig:
     debug: bool
     debug: bool
     is_light: bool
     is_light: bool
 
 
+    def light_dark(self) -> Literal['light', 'dark']:
+        return 'light' if self.is_light else 'dark'
+
+    def default_lightness(self, term: Literal['light', 'dark'] | None = None) -> float:
+        if term is None:
+            term = self.light_dark()
+        return 0.65 if term.lower() == 'dark' else 0.4
+
 
 
 GLOBAL_CFG = GlobalConfig(color_mode='8bit', override_distro=None, debug=False, is_light=False)
 GLOBAL_CFG = GlobalConfig(color_mode='8bit', override_distro=None, debug=False, is_light=False)

+ 31 - 27
hyfetch/main.py

@@ -10,7 +10,7 @@ from typing import Iterable
 
 
 from hyfetch import presets
 from hyfetch import presets
 
 
-from .color_util import printc, color, clear_screen
+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 .constants import CONFIG_PATH, VERSION, TERM_LEN, TEST_ASCII_WIDTH, TEST_ASCII, GLOBAL_CFG
 from .models import Config
 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, color_alignments
@@ -27,7 +27,10 @@ def check_config() -> Config:
     :return: Config object
     :return: Config object
     """
     """
     if CONFIG_PATH.is_file():
     if CONFIG_PATH.is_file():
-        return Config(**json.loads(CONFIG_PATH.read_text('utf-8')))
+        try:
+            return Config.from_dict(json.loads(CONFIG_PATH.read_text('utf-8')))
+        except KeyError:
+            return create_config()
 
 
     return create_config()
     return create_config()
 
 
@@ -98,9 +101,18 @@ def create_config() -> Config:
     title += f'\n&e1. Selected color mode: &r{color_system}'
     title += f'\n&e1. Selected color mode: &r{color_system}'
 
 
     ##############################
     ##############################
-    # 2. Choose preset
+    # 2. Select light/dark mode
+    clear_screen(title)
+    light_dark = literal_input(f'2. Is your terminal in &gf(#85e7e9)light mode&r or &gf(#c471ed)dark mode&r?',
+                               ['light', 'dark'], 'dark')
+    is_light = light_dark == 'light'
+    GLOBAL_CFG.is_light = is_light
+    title += f'\n&e2. Light/Dark:          &r{light_dark}'
+
+    ##############################
+    # 3. Choose preset
     clear_screen(title)
     clear_screen(title)
-    printc('&a2. Let\'s choose a flag!')
+    printc('&a3. Let\'s choose a flag!')
     printc('Available flag presets:')
     printc('Available flag presets:')
     print()
     print()
 
 
@@ -122,19 +134,10 @@ def create_config() -> Config:
         print()
         print()
 
 
     print()
     print()
-    tmp = PRESETS['rainbow'].set_light(.7).color_text('preset')
+    tmp = PRESETS['rainbow'].set_light_dl_def(light_dark).color_text('preset')
     preset = literal_input(f'Which {tmp} do you want to use?', PRESETS.keys(), 'rainbow', show_ops=False)
     preset = literal_input(f'Which {tmp} do you want to use?', PRESETS.keys(), 'rainbow', show_ops=False)
     _prs = PRESETS[preset]
     _prs = PRESETS[preset]
-    title += f'\n&e2. Selected flag:       &r{_prs.color_text(preset)}'
-
-    ##############################
-    # 3. Select light/dark mode
-    clear_screen(title)
-    light_dark = literal_input(f'3. Is your terminal in &gf(#85e7e9)light mode&r or &gf(#c471ed)dark mode&r?',
-                               ['light', 'dark'], 'dark')
-    is_light = light_dark == 'light'
-    GLOBAL_CFG.is_light = is_light
-    title += f'\n&e3. Light/Dark:          &r{light_dark}'
+    title += f'\n&e3. Selected flag:       &r{_prs.color_text(preset)}'
 
 
     #############################
     #############################
     # 4. Dim/lighten colors
     # 4. Dim/lighten colors
@@ -146,14 +149,14 @@ def create_config() -> Config:
     # Print cats
     # Print cats
     num_cols = TERM_LEN // (TEST_ASCII_WIDTH + 2)
     num_cols = TERM_LEN // (TEST_ASCII_WIDTH + 2)
     ratios = [col / (num_cols - 1) for col in range(num_cols)]
     ratios = [col / (num_cols - 1) for col in range(num_cols)]
-    ratios = [r * 0.6 + 0.2 for r in ratios]
+    ratios = [(r * 0.4 + 0.1) if is_light else (r * 0.4 + 0.5) for r in ratios]
     lines = [ColorAlignment('horizontal').recolor_ascii(TEST_ASCII.replace(
     lines = [ColorAlignment('horizontal').recolor_ascii(TEST_ASCII.replace(
-        '{txt}', f'{r * 100:.0f}%'.center(5)), _prs.set_light(r)).split('\n') for r in ratios]
+        '{txt}', f'{r * 100:.0f}%'.center(5)), _prs.set_light_dl(r, light_dark)).split('\n') for r in ratios]
     [printc('  '.join(line)) for line in zip(*lines)]
     [printc('  '.join(line)) for line in zip(*lines)]
 
 
     while True:
     while True:
         print()
         print()
-        printc('Which brightness level look the best? (Default: unset)')
+        printc(f'Which brightness level look the best? (Default: left blank = {GLOBAL_CFG.default_lightness(light_dark):.2f} for {light_dark} mode)')
         lightness = input('> ').strip().lower() or None
         lightness = input('> ').strip().lower() or None
 
 
         # Parse lightness
         # Parse lightness
@@ -170,11 +173,12 @@ def create_config() -> Config:
             printc('&cUnable to parse lightness value, please input it as a decimal or percentage (e.g. 0.5 or 50%)')
             printc('&cUnable to parse lightness value, please input it as a decimal or percentage (e.g. 0.5 or 50%)')
 
 
     if lightness:
     if lightness:
-        _prs = _prs.set_light(lightness)
+        _prs = _prs.set_light_dl(lightness, light_dark)
     title += f'\n&e4. Brightness:          &r{f"{lightness:.2f}" if lightness else "unset"}'
     title += f'\n&e4. Brightness:          &r{f"{lightness:.2f}" if lightness else "unset"}'
 
 
     #############################
     #############################
     # 5. Color arrangement
     # 5. Color arrangement
+    color_alignment = None
     while True:
     while True:
         clear_screen(title)
         clear_screen(title)
         printc(f'&a5. Let\'s choose a color arrangement!')
         printc(f'&a5. Let\'s choose a color arrangement!')
@@ -184,8 +188,8 @@ def create_config() -> Config:
         asc = get_distro_ascii()
         asc = get_distro_ascii()
         asc_width = ascii_size(asc)[0]
         asc_width = ascii_size(asc)[0]
         asciis = [
         asciis = [
-            ['Horizontal'.center(asc_width), *ColorAlignment('horizontal').recolor_ascii(asc, _prs).split('\n')],
-            ['Vertical'.center(asc_width), *ColorAlignment('vertical').recolor_ascii(asc, _prs).split('\n')],
+            [*ColorAlignment('horizontal').recolor_ascii(asc, _prs).split('\n'), 'Horizontal'.center(asc_width)],
+            [*ColorAlignment('vertical').recolor_ascii(asc, _prs).split('\n'), 'Vertical'.center(asc_width)],
         ]
         ]
         ascii_per_row = TERM_LEN // (asc_width + 2)
         ascii_per_row = TERM_LEN // (asc_width + 2)
 
 
@@ -195,10 +199,10 @@ def create_config() -> Config:
         while len(pis) < len(set(re.findall('(?<=\\${c)[0-9](?=})', asc))):
         while len(pis) < len(set(re.findall('(?<=\\${c)[0-9](?=})', asc))):
             pis += pis
             pis += pis
         perm = list(permutations(pis))
         perm = list(permutations(pis))
-        random_count = ascii_per_row - 2
+        random_count = ascii_per_row * 2 - 2
         choices = random.sample(perm, random_count)
         choices = random.sample(perm, random_count)
         choices = [{i: n for i, n in enumerate(c)} for c in choices]
         choices = [{i: n for i, n in enumerate(c)} for c in choices]
-        asciis += [[f'random{i}'.center(asc_width), *ColorAlignment('custom', r).recolor_ascii(asc, _prs).split('\n')]
+        asciis += [[*ColorAlignment('custom', r).recolor_ascii(asc, _prs).split('\n'), f'random{i}'.center(asc_width)]
                    for i, r in enumerate(choices)]
                    for i, r in enumerate(choices)]
 
 
         while asciis:
         while asciis:
@@ -219,7 +223,7 @@ def create_config() -> Config:
         if choice in ['horizontal', 'vertical']:
         if choice in ['horizontal', 'vertical']:
             color_alignment = ColorAlignment(choice)
             color_alignment = ColorAlignment(choice)
         elif choice.startswith('random'):
         elif choice.startswith('random'):
-            color_alignment = ColorAlignment('custom', choices[int(choice[6]) - 1])
+            color_alignment = ColorAlignment('custom', choices[int(choice[6])])
         else:
         else:
             raise NotImplementedError()
             raise NotImplementedError()
 
 
@@ -242,7 +246,7 @@ def create_config() -> Config:
 
 
 def run():
 def run():
     # Create CLI
     # Create CLI
-    hyfetch = color('&b&lhy&f&lfetch&r')
+    hyfetch = color('&b&lhyfetch&r')
     parser = argparse.ArgumentParser(description=color(f'{hyfetch} - neofetch with flags <3'))
     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('-c', '--config', action='store_true', help=color(f'Configure {hyfetch}'))
@@ -298,9 +302,9 @@ def run():
     if args.scale:
     if args.scale:
         preset = preset.lighten(args.scale)
         preset = preset.lighten(args.scale)
     if args.light:
     if args.light:
-        preset = preset.set_light(args.light)
+        preset = preset.set_light_raw(args.light)
     if config.lightness:
     if config.lightness:
-        preset = preset.set_light(config.lightness)
+        preset = preset.set_light_dl(config.lightness)
 
 
     # Debug recommendations
     # Debug recommendations
     if args.debug_list:
     if args.debug_list:

+ 8 - 3
hyfetch/models.py

@@ -4,20 +4,25 @@ from dataclasses import dataclass
 
 
 from typing_extensions import Literal
 from typing_extensions import Literal
 
 
-from .color_util import AnsiMode
+from .color_util import AnsiMode, LightDark
 from .constants import CONFIG_PATH
 from .constants import CONFIG_PATH
 from .neofetch_util import ColorAlignment
 from .neofetch_util import ColorAlignment
-from .serializer import json_stringify
+from .serializer import json_stringify, from_dict
 
 
 
 
 @dataclass
 @dataclass
 class Config:
 class Config:
     preset: str
     preset: str
     mode: AnsiMode
     mode: AnsiMode
-    light_dark: Literal['light', 'dark'] = 'dark'
+    light_dark: LightDark = 'dark'
     lightness: float | None = None
     lightness: float | None = None
     color_align: ColorAlignment = ColorAlignment('horizontal')
     color_align: ColorAlignment = ColorAlignment('horizontal')
 
 
+    @classmethod
+    def from_dict(cls, d: dict):
+        d['color_align'] = ColorAlignment.from_dict(d['color_align'])
+        return from_dict(cls, d)
+
     def save(self):
     def save(self):
         CONFIG_PATH.parent.mkdir(exist_ok=True, parents=True)
         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')

+ 7 - 1
hyfetch/neofetch_util.py

@@ -1,5 +1,6 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
+import inspect
 import os
 import os
 import platform
 import platform
 import re
 import re
@@ -15,6 +16,7 @@ from typing_extensions import Literal
 from hyfetch.color_util import color
 from hyfetch.color_util import color
 from .constants import GLOBAL_CFG
 from .constants import GLOBAL_CFG
 from .presets import ColorProfile
 from .presets import ColorProfile
+from .serializer import from_dict
 
 
 RE_NEOFETCH_COLOR = re.compile('\\${c[0-9]}')
 RE_NEOFETCH_COLOR = re.compile('\\${c[0-9]}')
 
 
@@ -67,6 +69,10 @@ class ColorAlignment:
     # Foreground/background ascii color index
     # Foreground/background ascii color index
     fore_back: tuple[int, int] = ()
     fore_back: tuple[int, int] = ()
 
 
+    @classmethod
+    def from_dict(cls, d: dict):
+        return from_dict(cls, d)
+
     def recolor_ascii(self, asc: str, preset: ColorProfile) -> str:
     def recolor_ascii(self, asc: str, preset: ColorProfile) -> str:
         """
         """
         Use the color alignment to recolor an ascii art
         Use the color alignment to recolor an ascii art
@@ -177,7 +183,7 @@ def run_neofetch(preset: ColorProfile, alignment: ColorAlignment):
 color_alignments = {
 color_alignments = {
     'fedora': ColorAlignment('horizontal', fore_back=(2, 1)),
     'fedora': ColorAlignment('horizontal', fore_back=(2, 1)),
     'ubuntu': ColorAlignment('horizontal', fore_back=(2, 1)),
     'ubuntu': ColorAlignment('horizontal', fore_back=(2, 1)),
-    'nixos': ColorAlignment('custom', {1: 1, 2: 0}),
+    'NixOS.*': ColorAlignment('custom', {1: 1, 2: 0}),
     # 'arch': ColorAlignment('horizontal'),
     # 'arch': ColorAlignment('horizontal'),
     # 'centos': ColorAlignment('horizontal'),
     # 'centos': ColorAlignment('horizontal'),
 }
 }

+ 26 - 5
hyfetch/presets.py

@@ -4,7 +4,8 @@ from typing import Iterable
 
 
 from typing_extensions import Literal
 from typing_extensions import Literal
 
 
-from .color_util import RGB
+from .color_util import RGB, LightDark
+from .constants import GLOBAL_CFG
 
 
 
 
 def remove_duplicates(seq: Iterable) -> list:
 def remove_duplicates(seq: Iterable) -> list:
@@ -100,17 +101,37 @@ class ColorProfile:
         """
         """
         return ColorProfile([c.lighten(multiplier) for c in self.colors])
         return ColorProfile([c.lighten(multiplier) for c in self.colors])
 
 
-    def set_light(self, light: float):
+    def set_light_raw(self, light: float, at_least: bool | None = None, at_most: bool | None = None) -> 'ColorProfile':
         """
         """
         Set HSL lightness value
         Set HSL lightness value
 
 
         :param light: Lightness value (0-1)
         :param light: Lightness value (0-1)
+        :param at_least: Set the lightness to at least this value (no change if greater)
+        :param at_most: Set the lightness to at most this value (no change if lesser)
         :return: New color profile (original isn't modified)
         :return: New color profile (original isn't modified)
         """
         """
-        return ColorProfile([c.set_light(light) for c in self.colors])
+        return ColorProfile([c.set_light(light, at_least, at_most) for c in self.colors])
 
 
-    def set_min_light(self, light: float):
-        return ColorProfile([c.set_min_light(light) for c in self.colors])
+    def set_light_dl(self, light: float, term: LightDark = GLOBAL_CFG.light_dark()):
+        """
+        Set HSL lightness value with respect to dark/light terminals
+
+        :param light: Lightness value (0-1)
+        :param term: Terminal color (can be "dark" or "light")
+        :return: New color profile (original isn't modified)
+        """
+        assert term.lower() in ['light', 'dark']
+        at_least, at_most = (True, None) if term.lower() == 'dark' else (None, True)
+        return self.set_light_raw(light, at_least, at_most)
+
+    def set_light_dl_def(self, term: LightDark | None = None):
+        """
+        Set default lightness with respect to dark/light terminals
+
+        :param term: Terminal color (can be "dark" or "light")
+        :return: New color profile (original isn't modified)
+        """
+        return self.set_light_dl(GLOBAL_CFG.default_lightness(term), term)
 
 
     def unique_colors(self) -> ColorProfile:
     def unique_colors(self) -> ColorProfile:
         """
         """

+ 5 - 0
hyfetch/serializer.py

@@ -1,6 +1,7 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
 import dataclasses
 import dataclasses
+import inspect
 import json
 import json
 from datetime import datetime, date
 from datetime import datetime, date
 
 
@@ -41,3 +42,7 @@ def json_stringify(obj: object, indent: int | None = None) -> str:
     :return: Json strings
     :return: Json strings
     """
     """
     return json.dumps(obj, indent=indent, cls=EnhancedJSONEncoder, ensure_ascii=False)
     return json.dumps(obj, indent=indent, cls=EnhancedJSONEncoder, ensure_ascii=False)
+
+
+def from_dict(cls, d: dict):
+    return cls(**{k: v for k, v in d.items() if k in inspect.signature(cls).parameters})

+ 5 - 0
neofetch

@@ -11598,6 +11598,11 @@ main() {
     return 0
     return 0
 }
 }
 
 
+get_ascii_distro_name() {
+    get_distro
+    echo "$ascii_distro"
+}
+
 get_print_ascii() {
 get_print_ascii() {
     cache_uname
     cache_uname
     get_os
     get_os