diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/CLI-in-Python.iml b/.idea/CLI-in-Python.iml new file mode 100644 index 0000000..3ae5178 --- /dev/null +++ b/.idea/CLI-in-Python.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..8d7da84 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,45 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dc9ea49 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..355067e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index ca37843..7edd507 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,6 @@ * [Мой Telegram](https://t.me/SantaSpeen "SantaSpeen"): https://t.me/SantaSpeen -Используемые библиотеки: \ No newline at end of file +Используемые библиотеки: + +* \ No newline at end of file diff --git a/scr/builtins_fix.pyi b/scr/builtins_fix.pyi new file mode 100644 index 0000000..87834ef --- /dev/null +++ b/scr/builtins_fix.pyi @@ -0,0 +1,42 @@ +class Console(object): + + def __init__(self, + prompt_in: str = ">", + prompt_out: str = "]:", + not_found: str = "Command \"%s\" not found in alias.") -> None: ... + + def __getitem__(self, item): ... + @property + def alias(self) -> dict: ... + def add(self, key: str, func: function) -> dict: ... + def log(self, s: str, r='\r') -> None: ... + def write(self, s: str, r='\r') -> None: ... + def __lshift__(self, s: AnyStr) -> None: ... + def logger_hook(self) -> None: ... + def builtins_hook(self) -> None: ... + def run(self) -> None: ... + def run_while(self, whl) -> None:... + +class console(object): + + @staticmethod + def alias() -> dict: ... + @staticmethod + def add(key: str, func: function) -> dict: ... + + @staticmethod + def run() -> None: ... + @staticmethod + def run_while(whl: Any) -> None: ... + + @staticmethod + def builtins_hook() -> None: ... + @staticmethod + def logger_hook() -> None: ... + + @staticmethod + def log(s: str) -> None: ... + @staticmethod + def write(s: str) -> None: ... + @staticmethod + def __lshift__(s: AnyStr) -> None: ... diff --git a/scr/console/Console.py b/scr/console/Console.py new file mode 100644 index 0000000..884dd3f --- /dev/null +++ b/scr/console/Console.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- + +# Developed by Ahegao Devs +# Written by: SantaSpeen +# Licence: MIT +# (c) ahegao.ovh 2022 + +import builtins +import logging +import sys +import traceback +from typing import AnyStr + + +class ConsoleIO: + + @staticmethod + def write(s: AnyStr): + sys.stdout.write(s) + + @staticmethod + def write_err(s: AnyStr): + sys.stderr.write(s) + + @staticmethod + def read(): + return sys.stdin.readline().strip() + + +# noinspection PyUnusedLocal, PyShadowingBuiltins, PyUnresolvedReferences +class Console: + + def __init__(self, + prompt_in: str = ">", + prompt_out: str = "]:", + not_found: str = "Command \"%s\" not found in alias.", + file: str or None = None, + debug: bool = False) -> None: + """ + def __init__(self, + prompt_in: str = ">", + prompt_out: str = "]:", + not_found: str = "Command \"%s\" not found in alias.") -> None: + :param prompt_in: + :param prompt_out: + :param not_found: + """ + self.__prompt_in = prompt_in + self.__prompt_out = prompt_out + self.__not_found = not_found + "\n" + self.__is_debug = debug + + self.__print = print + + self.__file = file + + self.__alias = { + "help": self.__create_help_message, + } + + self.get_IO = ConsoleIO + + def __debug(self, *x): + if self.__is_debug: + x = list(x) + x.insert(0, "\r CONSOLE DEBUG:") + self.__print(*x) + + def __getitem__(self, item): + + print(item) + + @staticmethod + def __get_max_len(arg) -> int: + arg = list(arg) + i = 0 + for a in arg: + l = len(a) + if l > i: + i = l + return i + + # noinspection PyStringFormat + def __create_help_message(self, x) -> AnyStr: + """ Print help message and alias of console commands""" + self.__debug("creating help message") + + max_len = self.__get_max_len(self.__alias.keys()) + if max_len < 7: + max_len = 7 + + message = f"%{max_len}s : Help message\n" % "Command" + for k, v in self.__alias.items(): + doc = v.__doc__ + if doc is None: + doc = " No help message found" + message += f" %{max_len}s :%s\n" % (k, doc) + + return message + + def __create_message(self, text, r="\r"): + self.__debug("create message to output") + return r + self.__prompt_out + " " + text + "\n\r" + self.__prompt_in + " " + + @property + def alias(self) -> dict: + """ + def alias(self) -> dict: + :return: dict of alias + """ + return self.__alias.copy() + + def add(self, key: str, func) -> dict: + """ + def add(self, key: str, func) -> dict: + :param key: + :param func: + :return: + """ + + key = key.format(" ", "-") + + if not isinstance(key, str): + raise TypeError("key must be string") + self.__debug(f"added user command: key={key}; func={func}") + self.__alias.update({key: func}) + return self.__alias.copy() + + def write(self, s: AnyStr, r="\r"): + s = s.replace("\n\t", "\n" + self.__prompt_out + " ").replace("\t", " ") + ConsoleIO.write(self.__create_message(s, r)) + + def log(self, s: AnyStr, r='\r') -> None: + self.write(s, r) + + def __lshift__(self, s: AnyStr) -> None: + self.write(s) + + def __builtins_print(self, + *values: object, + sep: str or None = " ", + end: str or None = None, + file: str or None = None, + flush: bool = False, + loading: bool = False) -> None: + val = list(values) + if len(val) > 0: + val.insert(0, "\r" + self.__prompt_out) + if not loading: + val.append("\r\n" + self.__prompt_in + " ") + end = "" if end is None else end + self.__print(*tuple(val), sep=sep, end=end, file=file, flush=flush) + + def logger_hook(self) -> None: + + self.__debug("used logger_hook") + + def emit(cls, record): + try: + msg = cls.format(record) + ConsoleIO.write(self.__create_message(msg)) + cls.flush() + except RecursionError: # See issue 36272 + raise + except Exception: + cls.handleError(record) + + logging.StreamHandler.emit = emit + + def builtins_hook(self) -> None: + """ + def builtins_hook(self) -> None: + :return: None + """ + self.__debug("used builtins_hook") + builtins.Console = Console + builtins.console = self + builtins.print = self.__builtins_print + + def run(self) -> None: + """ + def run(self) -> None: + :return: None + """ + self.run_while(True) + + def run_while(self, whl) -> None: + """ + def run_while(self, whl) -> None: + :param whl: run while what? + :return: None + """ + self.__debug(f"run while {whl}") + while whl: + try: + ConsoleIO.write("\r" + self.__prompt_in + " ") + cmd_in = ConsoleIO.read() + cmd = cmd_in.split(" ")[0] + if cmd == "": + pass + else: + command = self.__alias.get(cmd) + if command: + x = cmd_in[len(cmd) + 1:] + output = command(x) + if isinstance(output, str): + self.log(output) + else: + self.log(self.__not_found % cmd) + except Exception as e: + if e == KeyboardInterrupt: + raise e + ConsoleIO.write_err("\rDuring the execution of the command, an error occurred:\n\n" + + str(traceback.format_exc()) + + "\nType Enter to continue.") diff --git a/scr/console/Console.pyi b/scr/console/Console.pyi new file mode 100644 index 0000000..6844891 --- /dev/null +++ b/scr/console/Console.pyi @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +# Developed by Ahegao Devs +# Written by: SantaSpeen +# Licence: MIT +# (c) ahegao.ovh 2022 + +from _typeshed import SupportsWrite +from builtins import function +from typing import AnyStr + + +class ConsoleIO: + + @staticmethod + def write(s: AnyStr): ... + + @staticmethod + def write_err(s: AnyStr): ... + + @staticmethod + def read(): ... + + +class Console(object): + + def __init__(self, + prompt_in: str = ">", + prompt_out: str = "]:", + not_found: str = "Command \"%s\" not found in alias.", + file: SupportsWrite[str] or None = Console, + debug: bool = False) -> None: + + self.get_IO: ConsoleIO + + def __getitem__(self, item): ... + @property + def alias(self) -> dict: ... + def add(self, key: str, func: function) -> dict: ... + def log(self, s: AnyStr, r='\r') -> None: ... + def write(self, s: AnyStr, r='\r') -> None: ... + def logger_hook(self) -> None: ... + def builtins_hook(self) -> None: ... + def run(self) -> None: ... + def run_while(self, whl) -> None:... \ No newline at end of file diff --git a/scr/console/__init__.py b/scr/console/__init__.py new file mode 100644 index 0000000..a298f7d --- /dev/null +++ b/scr/console/__init__.py @@ -0,0 +1 @@ +from .Console import Console, ConsoleIO diff --git a/scr/main.py b/scr/main.py new file mode 100644 index 0000000..2d39021 --- /dev/null +++ b/scr/main.py @@ -0,0 +1,95 @@ +import logging +import os + +from console import Console, ConsoleIO + +# Init modules +cli = Console() # Console(debug=True) +logging.basicConfig(level=logging.NOTSET, format="%(asctime)s - %(name)-5s - %(levelname)-7s - %(message)s") + + +def cli_print(): + """ How can I write text to the console? Read below! """ + cli.log("cli.og") + cli.write("cli.write") + + print("\r...", end="\n\n\n") + + +def logger_preview(): + """ I use logging and want its output to be in the console! """ + cli.logger_hook() + + # All calls below will be implemented via Console + + logging.debug("Debug log") + logging.warning('Warning log') + logging.error("Error log") + logging.info("Info log") + + print("\r...", end="\n\n\n") + + +def builtins_preview(): + """ I want print to be output like cli.log """ + + # Output below without hook + + print("No builtins_hook here") + print("No builtins_hook here, but file=cli, end=''", file=cli, end="") + + cli.builtins_hook() + + # Output below from the hook + # After hook cli = console + + print("builtins_hook here") + + console.write("console.write") + console.log("console.log") + + console['[] log'] + console << "<< log" + + ConsoleIO.write("\r...\n\n") # Or console.get_IO.write("\r...\n\n") + + +def cli_echo(x: str): + """ Help message here """ + + message = "Echo message: " + x + + return message + + +def cli_error(x): + """ Print error message """ + + raise Exception("Test error message") + + +def cli_exit(): + """ Kill process """ + + pid = os.getpid() + os.system(f"kill {pid}") + + +def cli_mode(): + print("type help") + + cli.add("echo", cli_echo) + cli.add("error", cli_error) + cli.add("exit", cli_exit) + + cli.run() + + # Or you may use + # cli.run_while(lambda: ) + + +if __name__ == '__main__': + cli_print() + logger_preview() + builtins_preview() + cli_mode()