cli-ih 0.7.0__py3-none-any.whl → 0.7.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cli_ih/asyncClient.py CHANGED
@@ -1,6 +1,6 @@
1
- from typing import Coroutine, Callable, Any
1
+ from typing import Callable, Any
2
2
  from .exceptions import HandlerClosed
3
- from .utils import safe_print as print, register_handler
3
+ from .utils import safe_print as print, register_handler, SafeLogger
4
4
  import logging, warnings, asyncio, inspect, threading, sys, shutil, msvcrt
5
5
 
6
6
  class AsyncInputHandler:
@@ -10,12 +10,14 @@ class AsyncInputHandler:
10
10
  self.is_running = False
11
11
  self.thread_mode = thread_mode
12
12
  self.cursor = f"{cursor.strip()} " if cursor else ""
13
- self.global_logger = logger if logger else None
14
- self.logger = logger.getChild("InputHandler") if logger else None
13
+ self.global_logger = logger if logger else SafeLogger()
14
+ self.logger = logger.getChild("InputHandler") if logger else self.global_logger
15
15
  self.register_defaults = register_defaults
16
16
  self.print_lock = threading.Lock()
17
17
  self.input_buffer = ""
18
18
  self.processing_command = False
19
+ self.history = []
20
+ self.history_index = 0
19
21
 
20
22
  if self.register_defaults:
21
23
  self.register_default_commands()
@@ -26,34 +28,19 @@ class AsyncInputHandler:
26
28
  return self.logger
27
29
 
28
30
  def __debug(self, msg: str):
29
- if self.logger:
30
- self.logger.debug(msg)
31
- else:
32
- print(f"[DEBUG]: {msg}")
31
+ self.logger.debug(msg)
33
32
 
34
33
  def __info(self, msg: str):
35
- if self.logger:
36
- self.logger.info(msg)
37
- else:
38
- print(f"[INFO]: {msg}")
34
+ self.logger.info(msg)
39
35
 
40
36
  def __warning(self, msg: str):
41
- if self.logger:
42
- self.logger.warning(msg)
43
- else:
44
- print(f"[WARNING]: {msg}")
37
+ self.logger.warning(msg)
45
38
 
46
39
  def __error(self, msg: str):
47
- if self.logger:
48
- self.logger.error(msg)
49
- else:
50
- print(f"[ERROR]: {msg}")
40
+ self.logger.error(msg)
51
41
 
52
42
  def __exeption(self, msg: str, e: Exception):
53
- if self.logger:
54
- self.logger.exception(f"{msg}: {e}")
55
- else:
56
- print(f"[EXEPTION]: {msg}: {e}")
43
+ self.logger.exception(f"{msg}: {e}")
57
44
 
58
45
  def __register_cmd(self, name: str, func: Callable[..., Any], description: str = "", legacy=False):
59
46
  name = name.lower()
@@ -96,7 +83,6 @@ class AsyncInputHandler:
96
83
  input_queue = asyncio.Queue()
97
84
 
98
85
  def _input_worker():
99
- # Initial prompt
100
86
  with self.print_lock:
101
87
  sys.stdout.write(self.cursor)
102
88
  sys.stdout.flush()
@@ -106,37 +92,66 @@ class AsyncInputHandler:
106
92
  if msvcrt.kbhit():
107
93
  char = msvcrt.getwch()
108
94
 
109
- if char == '\r': # Enter
95
+ if char == '\xe0' or char == '\x00':
96
+ try:
97
+ scancode = msvcrt.getwch()
98
+ if scancode == 'H':
99
+ if self.history_index > 0:
100
+ self.history_index -= 1
101
+ self.input_buffer = self.history[self.history_index]
102
+ with self.print_lock:
103
+ sys.stdout.write('\r' + ' ' * (shutil.get_terminal_size().columns - 1) + '\r')
104
+ sys.stdout.write(self.cursor + self.input_buffer)
105
+ sys.stdout.flush()
106
+
107
+ elif scancode == 'P':
108
+ if self.history_index < len(self.history):
109
+ self.history_index += 1
110
+
111
+ if self.history_index == len(self.history):
112
+ self.input_buffer = ""
113
+ else:
114
+ self.input_buffer = self.history[self.history_index]
115
+
116
+ with self.print_lock:
117
+ sys.stdout.write('\r' + ' ' * (shutil.get_terminal_size().columns - 1) + '\r')
118
+ sys.stdout.write(self.cursor + self.input_buffer)
119
+ sys.stdout.flush()
120
+ except Exception:
121
+ pass
122
+
123
+ elif char == '\r':
110
124
  with self.print_lock:
111
125
  sys.stdout.write('\n')
112
126
  sys.stdout.flush()
113
127
  text = self.input_buffer
114
128
  self.input_buffer = ""
129
+
130
+ if text:
131
+ if not self.history or self.history[-1] != text:
132
+ self.history.append(text)
133
+ self.history_index = len(self.history)
134
+
115
135
  loop.call_soon_threadsafe(input_queue.put_nowait, text)
116
136
 
117
- elif char == '\x08': # Backspace
137
+ elif char == '\x08':
118
138
  if len(self.input_buffer) > 0:
119
139
  self.input_buffer = self.input_buffer[:-1]
120
140
  with self.print_lock:
121
141
  sys.stdout.write('\b \b')
122
142
  sys.stdout.flush()
123
143
 
124
- elif char == '\x03': # Ctrl+C
144
+ elif char == '\x03':
125
145
  loop.call_soon_threadsafe(input_queue.put_nowait, KeyboardInterrupt)
126
146
  break
127
147
 
128
148
  else:
129
- # Verify printable
130
149
  if char.isprintable():
131
150
  self.input_buffer += char
132
151
  with self.print_lock:
133
152
  sys.stdout.write(char)
134
153
  sys.stdout.flush()
135
154
  else:
136
- pass
137
- # Small sleep to prevent high CPU usage,
138
- # but we are in a dedicated thread so it's fine-ish,
139
- # actually explicit sleep is good.
140
155
  import time
141
156
  time.sleep(0.01)
142
157
 
@@ -146,7 +161,7 @@ class AsyncInputHandler:
146
161
  thread = threading.Thread(target=_input_worker, daemon=True)
147
162
  thread.start()
148
163
 
149
- async def _run_command(commands: dict, name: str, args: list):
164
+ async def _run_command(commands: dict[str, dict[str, Any]], name: str, args: list[str]):
150
165
  """Executes a command from the command dictionary if it exists."""
151
166
  command = commands.get(name)
152
167
  if not command:
cli_ih/client.py CHANGED
@@ -1,7 +1,7 @@
1
- from typing import Callable
1
+ from typing import Callable, Any
2
2
  from .exceptions import HandlerClosed
3
- from .utils import safe_print as print, register_handler
4
- import logging, warnings, sys, shutil, threading, msvcrt
3
+ from .utils import safe_print as print, register_handler, SafeLogger
4
+ import logging, sys, threading, warnings, inspect, shutil, msvcrt
5
5
 
6
6
  class InputHandler:
7
7
  def __init__(self, thread_mode = True, cursor = "", *, logger: logging.Logger | None = None, register_defaults: bool = True):
@@ -11,12 +11,14 @@ class InputHandler:
11
11
  self.thread_mode = thread_mode
12
12
  self.cursor = f"{cursor.strip()} " if cursor else ""
13
13
  self.thread = None
14
- self.global_logger = logger if logger else None
15
- self.logger = logger.getChild("InputHandler") if logger else None
14
+ self.global_logger = logger if logger else SafeLogger()
15
+ self.logger = logger.getChild("InputHandler") if logger else self.global_logger
16
16
  self.register_defaults = register_defaults
17
17
  self.print_lock = threading.Lock()
18
18
  self.input_buffer = ""
19
19
  self.processing_command = False
20
+ self.history = []
21
+ self.history_index = 0
20
22
 
21
23
  if self.register_defaults:
22
24
  self.register_default_commands()
@@ -27,36 +29,21 @@ class InputHandler:
27
29
  return self.logger
28
30
 
29
31
  def __debug(self, msg: str):
30
- if self.logger:
31
- self.logger.debug(msg)
32
- else:
33
- print(f"[DEBUG]: {msg}")
32
+ self.logger.debug(msg)
34
33
 
35
34
  def __info(self, msg: str):
36
- if self.logger:
37
- self.logger.info(msg)
38
- else:
39
- print(f"[INFO]: {msg}")
35
+ self.logger.info(msg)
40
36
 
41
37
  def __warning(self, msg: str):
42
- if self.logger:
43
- self.logger.warning(msg)
44
- else:
45
- print(f"[WARNING]: {msg}")
38
+ self.logger.warning(msg)
46
39
 
47
40
  def __error(self, msg: str):
48
- if self.logger:
49
- self.logger.error(msg)
50
- else:
51
- print(f"[ERROR]: {msg}")
41
+ self.logger.error(msg)
52
42
 
53
43
  def __exeption(self, msg: str, e: Exception):
54
- if self.logger:
55
- self.logger.exception(f"{msg}: {e}")
56
- else:
57
- print(f"[EXEPTION]: {msg}: {e}")
44
+ self.logger.exception(f"{msg}: {e}")
58
45
 
59
- def __register_cmd(self, name: str, func: Callable, description: str = "", legacy=False):
46
+ def __register_cmd(self, name: str, func: Callable[..., Any], description: str = "", legacy=False):
60
47
  name = name.lower()
61
48
  if not description:
62
49
  description = "A command"
@@ -66,14 +53,14 @@ class InputHandler:
66
53
  raise SyntaxError(f"Command '{name}' is already registered. If theese commands have a different case and they need to stay the same, downgrade the package version to 0.5.x")
67
54
  self.commands[name] = {"cmd": func, "description": description, "legacy": legacy}
68
55
 
69
- def register_command(self, name: str, func: Callable, description: str = ""):
56
+ def register_command(self, name: str, func: Callable[..., Any], description: str = ""):
70
57
  """(DEPRECATED) Registers a command with its associated function."""
71
58
  warnings.warn("Registering commands with `register_command` is deprecated, and should not be used.", DeprecationWarning, 2)
72
59
  self.__register_cmd(name, func, description, legacy=True)
73
60
 
74
61
  def command(self, *, name: str = "", description: str = ""):
75
62
  """Registers a command with its associated function as a decorator."""
76
- def decorator(func: Callable):
63
+ def decorator(func: Callable[..., Any]):
77
64
  lname = name or func.__name__
78
65
  self.__register_cmd(lname, func, description)
79
66
  return func
@@ -136,7 +123,6 @@ class InputHandler:
136
123
  """Continuously listens for user input and processes commands."""
137
124
  while self.is_running:
138
125
  try:
139
- # Initial prompt
140
126
  with self.print_lock:
141
127
  sys.stdout.write(self.cursor)
142
128
  sys.stdout.flush()
@@ -145,7 +131,35 @@ class InputHandler:
145
131
  if msvcrt.kbhit():
146
132
  char = msvcrt.getwch()
147
133
 
148
- if char == '\r': # Enter
134
+ if char == '\xe0' or char == '\x00':
135
+ try:
136
+ scancode = msvcrt.getwch()
137
+ if scancode == 'H':
138
+ if self.history_index > 0:
139
+ self.history_index -= 1
140
+ self.input_buffer = self.history[self.history_index]
141
+ with self.print_lock:
142
+ sys.stdout.write('\r' + ' ' * (shutil.get_terminal_size().columns - 1) + '\r')
143
+ sys.stdout.write(self.cursor + self.input_buffer)
144
+ sys.stdout.flush()
145
+
146
+ elif scancode == 'P':
147
+ if self.history_index < len(self.history):
148
+ self.history_index += 1
149
+
150
+ if self.history_index == len(self.history):
151
+ self.input_buffer = ""
152
+ else:
153
+ self.input_buffer = self.history[self.history_index]
154
+
155
+ with self.print_lock:
156
+ sys.stdout.write('\r' + ' ' * (shutil.get_terminal_size().columns - 1) + '\r')
157
+ sys.stdout.write(self.cursor + self.input_buffer)
158
+ sys.stdout.flush()
159
+ except Exception:
160
+ pass
161
+
162
+ elif char == '\r':
149
163
  with self.print_lock:
150
164
  sys.stdout.write('\n')
151
165
  sys.stdout.flush()
@@ -153,6 +167,10 @@ class InputHandler:
153
167
  self.input_buffer = ""
154
168
 
155
169
  if text:
170
+ if not self.history or self.history[-1] != text:
171
+ self.history.append(text)
172
+ self.history_index = len(self.history)
173
+
156
174
  self.processing_command = True
157
175
  cmdargs = text.split(' ')
158
176
  command_name = cmdargs[0].lower()
@@ -163,23 +181,21 @@ class InputHandler:
163
181
  self.__warning(f"Unknown command: '{command_name}'")
164
182
  self.processing_command = False
165
183
 
166
- # Break inner loop to reprompt
167
184
  break
168
185
 
169
- elif char == '\x08': # Backspace
186
+ elif char == '\x08':
170
187
  if len(self.input_buffer) > 0:
171
188
  self.input_buffer = self.input_buffer[:-1]
172
189
  with self.print_lock:
173
190
  sys.stdout.write('\b \b')
174
191
  sys.stdout.flush()
175
192
 
176
- elif char == '\x03': # Ctrl+C
193
+ elif char == '\x03':
177
194
  self.__error("Input interrupted.")
178
195
  self.is_running = False
179
196
  return
180
197
 
181
198
  else:
182
- # Verify printable
183
199
  if char.isprintable():
184
200
  self.input_buffer += char
185
201
  with self.print_lock:
cli_ih/utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import shutil
2
2
  import sys
3
+ import threading
3
4
 
4
5
  _HANDLER = None
5
6
 
@@ -7,15 +8,55 @@ def register_handler(handler):
7
8
  global _HANDLER
8
9
  _HANDLER = handler
9
10
 
10
- def safe_print(msg: str, cursor: str | None = None, input_buffer: str | None = None):
11
+ class SafeLogger:
12
+ """A dummy logger that uses safe_print to output logs to the console."""
13
+ def __init__(self):
14
+ self.handlers = []
15
+
16
+ def debug(self, msg: str):
17
+ safe_print(f"[DEBUG]: {msg}")
18
+
19
+ def info(self, msg: str):
20
+ safe_print(f"[INFO]: {msg}")
21
+
22
+ def warning(self, msg: str):
23
+ safe_print(f"[WARNING]: {msg}")
24
+
25
+ def error(self, msg: str):
26
+ safe_print(f"[ERROR]: {msg}")
27
+
28
+ def critical(self, msg: str):
29
+ safe_print(f"[CRITICAL]: {msg}")
30
+
31
+ def exception(self, msg: str):
32
+ safe_print(f"[EXCEPTION]: {msg}")
33
+
34
+ def log(self, level, msg: str):
35
+ safe_print(f"[LOG {level}]: {msg}")
36
+
37
+ def getChild(self, name):
38
+ return self
39
+
40
+ def setLevel(self, level):
41
+ pass
42
+
43
+ def getEffectiveLevel(self):
44
+ return 0
45
+
46
+
47
+ def safe_print(msg: object, cursor: str | None = None, input_buffer: str | None = None):
11
48
  """
12
49
  Prints a message safely while preserving the current input buffer and cursor.
13
50
  This ensures logs appear above the input line appropriately.
14
51
  """
52
+ try:
53
+ msg = str(msg)
54
+ except:
55
+ msg = "<Unprintable Object>"
56
+
15
57
  if cursor is None and input_buffer is None and _HANDLER is not None:
16
- lock = None
58
+ lock: threading.Lock | None = None
17
59
  try:
18
- # Try to acquire lock if available to prevent race conditions
19
60
  lock = getattr(_HANDLER, "print_lock", None)
20
61
  if lock:
21
62
  lock.acquire()
@@ -33,8 +74,7 @@ def safe_print(msg: str, cursor: str | None = None, input_buffer: str | None = N
33
74
  if lock:
34
75
  lock.release()
35
76
  else:
36
- # Fallback or explicit arguments
37
- _do_safe_print(msg, cursor or "", input_buffer or "")
77
+ _do_safe_print(msg, str(cursor or ""), str(input_buffer or ""))
38
78
 
39
79
  def _do_safe_print(msg: str, cursor: str, input_buffer: str):
40
80
  try:
@@ -42,10 +82,7 @@ def _do_safe_print(msg: str, cursor: str, input_buffer: str):
42
82
  except:
43
83
  columns = 80
44
84
 
45
- # Clear line
46
85
  sys.stdout.write('\r' + ' ' * (columns - 1) + '\r')
47
- # Print message
48
86
  sys.stdout.write(f"{msg}\n")
49
- # Reprint cursor and buffer
50
87
  sys.stdout.write(f"{cursor}{input_buffer}")
51
88
  sys.stdout.flush()
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.4
2
+ Name: cli_ih
3
+ Version: 0.7.1.1
4
+ Summary: A background command handler for python's command-line interface.
5
+ Author-email: Hotment <michatchuplay@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+
9
+ # InputHandler Library
10
+
11
+ A lightweight Python library for creating interactive command-line interfaces with custom command registration, input handling, and clean log output. It supports synchronous and asynchronous modes, threaded input processing, and enhanced logging.
12
+
13
+ ## Features
14
+
15
+ - **Command Registration**: Register commands with decorators and descriptions.
16
+ - **Threaded Input**: Non-blocking input handling by default.
17
+ - **Safe Printing**: Logs appear above the input line, preserving your typed text and cursor position.
18
+ - **Command History**: Navigate recent commands with Up/Down arrow keys.
19
+ - **Sync & Async**: Support for both synchronous and asynchronous (asyncio) applications.
20
+ - **Colored Logging**: Built-in support for colored log messages.
21
+
22
+ ## Installation
23
+
24
+ `pip install cli_ih`
25
+
26
+ ## Quick Start (Synchronous)
27
+
28
+ ```python
29
+ from cli_ih import InputHandler, safe_print
30
+
31
+ handler = InputHandler(cursor="> ")
32
+
33
+ # Use safe_print instead of print to keep the input line clean!
34
+ @handler.command(name="greet", description="Greets the user.")
35
+ def greet(name):
36
+ safe_print(f"Hello, {name}!")
37
+
38
+ @handler.command(name="add", description="Adds two numbers.")
39
+ def add(a, b):
40
+ safe_print(int(a) + int(b))
41
+
42
+ handler.start()
43
+
44
+ # Using safe_print allows you to print logs in the background
45
+ # without messing up the user's current input line.
46
+ ```
47
+
48
+ ## Async Client Example
49
+
50
+ The `AsyncInputHandler` integrates with `asyncio`. The `start()` method is non-blocking when `thread_mode=True` (default).
51
+
52
+ ```python
53
+ import asyncio
54
+ from cli_ih import AsyncInputHandler, safe_print
55
+
56
+ handler = AsyncInputHandler(cursor="Async> ")
57
+
58
+ @handler.command(name="greet", description="Greets the user asynchronously.")
59
+ async def greet(name):
60
+ await asyncio.sleep(1)
61
+ safe_print(f"Hello, {name}")
62
+
63
+ @handler.command(name="add", description="Adds two numbers.")
64
+ async def add(a, b):
65
+ safe_print(int(a) + int(b))
66
+
67
+ # Start the handler (runs in a separate thread by default)
68
+ handler.start()
69
+
70
+ # Keep the main thread alive or run your main event loop
71
+ async def main():
72
+ while handler.is_running:
73
+ await asyncio.sleep(1)
74
+
75
+ if __name__ == "__main__":
76
+ asyncio.run(main())
77
+ ```
78
+
79
+ ## Key Considerations
80
+
81
+ ### Safe Printing
82
+ Always use `from cli_ih import safe_print` for outputting text to the console. This utility automatically detects the active input handler and ensures that your log message is printed *above* the current input line, preserving the user's cursor and any text they are currently typing.
83
+
84
+ ```python
85
+ from cli_ih import safe_print
86
+
87
+ # Good
88
+ safe_print("Log message")
89
+
90
+ # Avoid (might disrupt input line)
91
+ print("Log message")
92
+ ```
93
+
94
+ ### Thread Mode
95
+ Both `InputHandler` and `AsyncInputHandler` accept a `thread_mode` parameter (default `True`).
96
+ - `thread_mode=True`: The input loop runs in a separate thread. `start()` returns immediately.
97
+ - `thread_mode=False`: The input loop runs in the current thread. `start()` blocks until exit.
98
+
99
+ ### Command History
100
+ Use the **Up** and **Down** arrow keys to cycle through your previously entered commands, just like in a standard terminal.
@@ -0,0 +1,9 @@
1
+ cli_ih/__init__.py,sha256=wCwv9grczxpu7EXqunCdFgAWlx3XEZVw4O4U3fs45PY,278
2
+ cli_ih/asyncClient.py,sha256=56RLucih5qVNuxFR0EefExyohSheOh0BjomSoTMBEkU,12633
3
+ cli_ih/client.py,sha256=7jrFFrLdXln5VS4EG_YEse9oaa6n4FnUll5rvZNFiTc,12284
4
+ cli_ih/exceptions.py,sha256=0xqaMCVu-yEURIrB6wEhbf6kfdsRmODJBoDsQTOp29s,156
5
+ cli_ih/utils.py,sha256=3WcqvHrwwsiBYlkzIV51_SLsbtqpqEcN5v4Hu3E48Uw,2501
6
+ cli_ih-0.7.1.1.dist-info/METADATA,sha256=LO2NUmmDsuOAGtVEQsXuJZ7Cm3FuF45-1LyXPK7Nx7U,3413
7
+ cli_ih-0.7.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
+ cli_ih-0.7.1.1.dist-info/top_level.txt,sha256=Ve1CRLNXhPyPSkpN0xLu26roh30LQCpNzkF61BZYfk0,7
9
+ cli_ih-0.7.1.1.dist-info/RECORD,,
@@ -1,86 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: cli_ih
3
- Version: 0.7.0
4
- Summary: A background command handler for python's command-line interface.
5
- Author-email: Hotment <michatchuplay@gmail.com>
6
- Requires-Python: >=3.8
7
- Description-Content-Type: text/markdown
8
-
9
- # InputHandler Library
10
-
11
- A lightweight Python library for creating interactive command-line interfaces with custom command registration and input handling. It supports threaded input processing and includes enhanced logging with color-coded output.
12
-
13
- ## Features
14
-
15
- - Command registration system with descriptions
16
- - Threaded or non-threaded input handling
17
- - Colored logging with support for debug mode
18
- - Built-in `help`, `debug`, and `exit` commands
19
- - Error handling for missing or invalid command arguments
20
- - NEW: Register commands with decorators
21
-
22
- ## Installation
23
-
24
- `pip install cli_ih`
25
-
26
- ## Quick Start
27
-
28
- ```python
29
- from cli_ih import InputHandler
30
-
31
- def greet(args):
32
- print(f"Hello, {' '.join(args)}!")
33
-
34
- handler = InputHandler(cursor="> ")
35
- # NEW
36
- @handler.command(name="add", description="Performs the `+` operator on the first 2 arguments.") # The name param will use the func name if its not provided
37
- def add(args):
38
- print(int(args[0])+int(args[1]))
39
-
40
- handler.register_command("greet", greet, "Greets the user. Usage: greet [name]")
41
- handler.start()
42
-
43
- # Now type commands like:
44
- # > greet world
45
- # Hello, world!
46
- # > add 1 2
47
- # 3
48
- # > help
49
- # Available commands:
50
- # help: Displays all the available commands
51
- # debug: If a logger is present changes the logging level to DEBUG.
52
- # exit: Exits the Input Handler irreversibly.
53
- # add: Performs the `+` operator on the first 2 arguments.
54
- # greet: Greets the user. Usage: greet [name]
55
- #
56
- # > debug
57
- # > exit
58
- ```
59
-
60
- ## New Async client
61
- ```python
62
- import asyncio
63
- from cli_ih import AsyncInputHandler
64
-
65
- print(cli_ih.__version__)
66
-
67
- handler = AsyncInputHandler(cursor="> ")
68
-
69
- @handler.command(name="greet", description="Greets the user. Usage: greet [name]")
70
- async def greet(name, *args):
71
- await asyncio.sleep(1)
72
- print(f"Hello, {name}{" " if args else ""}{' '.join(args)}!")
73
- # NEW
74
- @handler.command(name="add", description="Performs the `+` operator on the first 2 arguments.")
75
- async def add(a, b):
76
- print(a+b)
77
-
78
- asyncio.run(handler.start())
79
- ```
80
-
81
- ## Additional Info
82
-
83
- - You can provide a valid logger `logger=logger` to the `InputHandler` to enable logging (this will be removed soon)
84
- - You can provide the `thread_mode` param to the `InputHandler` class to set if it shoud run in a thread or no.
85
- (If you are using the `cli-ih` module on its own without any other background task set `thread_mode=False` to false)
86
- - You can also provide a `cursor` param to the `InputHandler` class to set the cli cursor (default cusor is empty)
@@ -1,9 +0,0 @@
1
- cli_ih/__init__.py,sha256=wCwv9grczxpu7EXqunCdFgAWlx3XEZVw4O4U3fs45PY,278
2
- cli_ih/asyncClient.py,sha256=L7nCURM15Y9BIrSyfdeLB8PPddr1OF3IA8NWY26HyQQ,11171
3
- cli_ih/client.py,sha256=GWZH5YX2dDV7A2usgnX9xDm8xVjwLSj09sh5vfHSW-Y,10573
4
- cli_ih/exceptions.py,sha256=0xqaMCVu-yEURIrB6wEhbf6kfdsRmODJBoDsQTOp29s,156
5
- cli_ih/utils.py,sha256=HstJPjjlTfVKz68sHU_whSBsOoBKhxizCcycNyQeK2k,1685
6
- cli_ih-0.7.0.dist-info/METADATA,sha256=yu19a6SGAo79STCAgcxBVU4cqbvcYgIZ_KE7hyl_OcY,2789
7
- cli_ih-0.7.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
- cli_ih-0.7.0.dist-info/top_level.txt,sha256=Ve1CRLNXhPyPSkpN0xLu26roh30LQCpNzkF61BZYfk0,7
9
- cli_ih-0.7.0.dist-info/RECORD,,