nercone-modern 1.6.1__py3-none-any.whl → 1.7.0__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.
@@ -10,8 +10,11 @@ import time
10
10
  from nercone_modern.logging import ModernLogging
11
11
  from nercone_modern.progressbar import ModernProgressBar
12
12
 
13
- logger1 = ModernLogging("Main", display_level="DEBUG")
14
- logger2 = ModernLogging("Sub", display_level="DEBUG")
13
+ logger0 = ModernLogging("Demo", display_level="DEBUG", show_level=False)
14
+ show_proc = logger0.prompt("Show process name?", default="N", choices=["y", "N"], interrupt_ignore=True) == "Y"
15
+ show_level = logger0.prompt("Show level name?", default="N", choices=["y", "N"], interrupt_ignore=True) == "Y"
16
+ logger1 = ModernLogging("Main", display_level="DEBUG", show_proc=show_proc, show_level=show_level)
17
+ logger2 = ModernLogging("Sub", display_level="DEBUG", show_proc=show_proc, show_level=show_level)
15
18
 
16
19
  try:
17
20
  logger1.log("This is a debug message", "DEBUG")
@@ -22,10 +25,9 @@ try:
22
25
  logger1.log("This is a warning message", "WARNING")
23
26
  logger1.log("This is a error message", "ERROR")
24
27
  logger1.log("This is a critical error message", "CRITICAL")
25
- prompt_result = logger1.prompt("Continue demo?", default="Y", choices=["Y", "n"])
26
- logger1.log(f"Answer is: {prompt_result}", "INFO")
28
+ prompt_result = logger1.prompt("Continue demo?", default="Y", choices=["Y", "n"], interrupt_ignore=True, interrupt_default="n")
27
29
  if prompt_result == "n":
28
- print("Exiting demo. See you!")
30
+ logger1.log("Exiting demo. See you!", "INFO")
29
31
  raise SystemExit(0)
30
32
 
31
33
  progress_bar1 = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=False)
nercone_modern/color.py CHANGED
@@ -1,28 +1,28 @@
1
1
  class ModernColor:
2
- def ansi_color_by_code(color_code: int | str = 0):
2
+ def color_by_code(color_code: int | str = 0):
3
3
  return f"\033[{color_code}m"
4
4
 
5
- def ansi_color(color_name: str = "reset"):
5
+ def color(color_name: str = "reset"):
6
6
  if color_name == "reset":
7
- return ModernColor.ansi_color_by_code(0)
7
+ return ModernColor.color_by_code(0)
8
8
  elif color_name == "black":
9
- return ModernColor.ansi_color_by_code(30)
9
+ return ModernColor.color_by_code(30)
10
10
  elif color_name == "red":
11
- return ModernColor.ansi_color_by_code(31)
11
+ return ModernColor.color_by_code(31)
12
12
  elif color_name == "green":
13
- return ModernColor.ansi_color_by_code(32)
13
+ return ModernColor.color_by_code(32)
14
14
  elif color_name == "yellow":
15
- return ModernColor.ansi_color_by_code(33)
15
+ return ModernColor.color_by_code(33)
16
16
  elif color_name == "blue":
17
- return ModernColor.ansi_color_by_code(34)
17
+ return ModernColor.color_by_code(34)
18
18
  elif color_name == "magenta":
19
- return ModernColor.ansi_color_by_code(35)
19
+ return ModernColor.color_by_code(35)
20
20
  elif color_name == "cyan":
21
- return ModernColor.ansi_color_by_code(36)
21
+ return ModernColor.color_by_code(36)
22
22
  elif color_name == "white":
23
- return ModernColor.ansi_color_by_code(37)
23
+ return ModernColor.color_by_code(37)
24
24
  elif color_name in ("gray", "grey"):
25
- return ModernColor.ansi_color_by_code(90)
25
+ return ModernColor.color_by_code(90)
26
26
  else:
27
27
  return ""
28
28
 
nercone_modern/logging.py CHANGED
@@ -6,6 +6,9 @@
6
6
  # Copyright (c) 2025 DiamondGotCat #
7
7
  # ---------------------------------------------- DiamondGotCat -- #
8
8
 
9
+ import sys
10
+ from .color import ModernColor
11
+
9
12
  ModernLoggingLevels = ["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"]
10
13
  MAX_LOG_LEVEL_WIDTH = max(len(level) for level in ModernLoggingLevels)
11
14
  LEVEL_ALIASES = {
@@ -40,10 +43,12 @@ def is_higher_priority(level_a: str, level_b: str) -> bool:
40
43
  raise ValueError(f"Unknown log level: {level_a} or {level_b}")
41
44
 
42
45
  class ModernLogging:
43
- def __init__(self, process_name: str = "App", display_level: str = "INFO", filepath: str | None = None):
46
+ def __init__(self, process_name: str = "App", display_level: str = "INFO", filepath: str | None = None, show_proc: bool | None = None, show_level: bool | None = None):
44
47
  self.process_name = process_name
45
48
  self.display_level = display_level
46
49
  self.filepath = filepath
50
+ self.show_proc = show_proc
51
+ self.show_level = show_level
47
52
  global _max_proc_width
48
53
  _max_proc_width = max(_max_proc_width, len(process_name))
49
54
 
@@ -59,7 +64,7 @@ class ModernLogging:
59
64
  with open(self.filepath, "a") as f:
60
65
  f.write(f"{log_line}\n")
61
66
 
62
- def prompt(self, message: str = "", level_text: str = "INFO", level_color: str | None = None, ignore_kbdinterrupt: bool = True, default: str | None = None, show_default: bool = False, choices: list[str] | None = None, show_choices: bool = True) -> str:
67
+ def prompt(self, message: str = "", level_text: str = "INFO", level_color: str | None = None, default: str | None = None, show_default: bool = False, choices: list[str] | None = None, show_choices: bool = True, interrupt_ignore: bool = False, interrupt_default: str | None = None) -> str:
63
68
  if not is_higher_priority(level_text, self.display_level):
64
69
  return
65
70
  global _last_process, _last_level
@@ -74,10 +79,14 @@ class ModernLogging:
74
79
  _last_process = self.process_name
75
80
  _last_level = normalize_level(level_text.strip().upper())
76
81
  answer = ""
82
+ used_default = False
77
83
  try:
78
84
  answer = input()
79
85
  except KeyboardInterrupt:
80
- if ignore_kbdinterrupt:
86
+ if interrupt_ignore:
87
+ if interrupt_default:
88
+ answer = interrupt_default
89
+ used_default = True
81
90
  print()
82
91
  else:
83
92
  raise
@@ -86,8 +95,12 @@ class ModernLogging:
86
95
  selected_default = self._select_choice(default, choices)
87
96
  if selected_default is not None:
88
97
  answer = default
98
+ used_default = True
89
99
  else:
90
100
  answer = default
101
+ used_default = True
102
+ if used_default:
103
+ self._rewrite_prompt_line_with_answer(log_line, answer)
91
104
  if self.filepath:
92
105
  with open(self.filepath, "a") as f:
93
106
  f.write(f"{log_line}{answer}\n")
@@ -107,10 +120,25 @@ class ModernLogging:
107
120
  try:
108
121
  answer = input()
109
122
  except KeyboardInterrupt:
110
- if ignore_kbdinterrupt:
123
+ if interrupt_ignore:
124
+ if interrupt_default:
125
+ answer = interrupt_default
126
+ used_default = True
111
127
  print()
112
128
  else:
113
129
  raise
130
+ used_default = False
131
+ if answer.strip() == "" and default is not None:
132
+ if choices:
133
+ selected_default = self._select_choice(default, choices)
134
+ if selected_default is not None:
135
+ answer = default
136
+ used_default = True
137
+ else:
138
+ answer = default
139
+ used_default = True
140
+ if used_default:
141
+ self._rewrite_prompt_line_with_answer(log_line, answer)
114
142
  if self.filepath:
115
143
  with open(self.filepath, "a") as f:
116
144
  f.write(f"{log_line}{answer}\n")
@@ -124,6 +152,15 @@ class ModernLogging:
124
152
  selected = self._select_choice(answer, choices)
125
153
  if selected is not None:
126
154
  return selected
155
+ return answer
156
+
157
+ def _rewrite_prompt_line_with_answer(self, log_line: str, answer: str) -> None:
158
+ try:
159
+ sys.stdout.write("\033[F\r")
160
+ sys.stdout.write(f"{log_line}{answer} \n")
161
+ sys.stdout.flush()
162
+ except Exception:
163
+ print(f"{log_line}{answer}")
127
164
 
128
165
  def _select_choice(self, answer: str, choices: list[str]) -> str | None:
129
166
  if answer in choices:
@@ -138,10 +175,10 @@ class ModernLogging:
138
175
  return lower_map[stripped.lower()]
139
176
  return None
140
177
 
141
- def make(self, message: str = "", level_text: str = "INFO", level_color: str | None = None):
178
+ def make(self, message: str = "", level_text: str = "INFO", level_color: str | None = None, show_proc: bool | None = None, show_level: bool | None = None):
142
179
  level_text = normalize_level(level_text.strip().upper())
143
- show_proc = (self.process_name != _last_process)
144
- show_level = show_proc or (level_text != _last_level)
180
+ system_show_proc = (self.process_name != _last_process)
181
+ system_show_level = system_show_proc or (level_text != _last_level)
145
182
 
146
183
  if not level_color:
147
184
  if level_text == "DEBUG":
@@ -157,45 +194,47 @@ class ModernLogging:
157
194
  else:
158
195
  level_color = 'blue'
159
196
 
160
- return self._make(message, level_text, level_color, show_proc, show_level)
197
+ if show_proc is None:
198
+ if self.show_proc is not None:
199
+ show_proc = self.show_proc
200
+ else:
201
+ show_proc = True
202
+
203
+ if show_level is None:
204
+ if self.show_level is not None:
205
+ show_level = self.show_level
206
+ else:
207
+ show_level = True
208
+
209
+ return self._make(message=message, level_text=level_text, level_color=level_color, show_proc=show_proc, show_level=show_level, system_show_proc=system_show_proc, system_show_level=system_show_level)
161
210
 
162
- def _make(self, message: str, level_text: str, level_color: str, show_proc: bool, show_level: bool):
211
+ def _make(self, message: str = "", level_text: str = "INFO", level_color: str = "blue", show_proc: bool = False, show_level: bool = False, system_show_proc: bool = True, system_show_level: bool = True):
163
212
  global _max_proc_width
164
213
  level_width = max(MAX_LOG_LEVEL_WIDTH, len(level_text))
214
+ color_bar = f"{ModernColor.color(level_color)}|{ModernColor.color('reset')}"
165
215
 
166
- proc_part = self.process_name if show_proc else ""
167
- proc_part = proc_part.ljust(_max_proc_width) if proc_part else " " * _max_proc_width
168
-
169
- if show_level:
170
- level_part = f"{self._color(level_color)}{level_text.ljust(level_width)} |{self._color('reset')}"
171
- else:
172
- level_part = (" " * level_width) + f"{self._color(level_color)} |{self._color('reset')}"
173
-
174
- return f"{proc_part} {level_part} {str(message)}"
175
-
176
- def _color(self, color_name: str = "reset"):
177
- if color_name == "cyan":
178
- return self._color_by_code(36)
179
- elif color_name == "magenta":
180
- return self._color_by_code(35)
181
- elif color_name == "yellow":
182
- return self._color_by_code(33)
183
- elif color_name == "green":
184
- return self._color_by_code(32)
185
- elif color_name == "red":
186
- return self._color_by_code(31)
187
- elif color_name == "blue":
188
- return self._color_by_code(34)
189
- elif color_name == "white":
190
- return self._color_by_code(37)
191
- elif color_name == "black":
192
- return self._color_by_code(30)
193
- elif color_name in ("gray", "grey"):
194
- return self._color_by_code(90)
195
- elif color_name == "reset":
196
- return self._color_by_code(0)
216
+ if not show_proc and not show_level:
217
+ prefix = ""
197
218
  else:
198
- return ""
199
-
200
- def _color_by_code(self, color_code: int | str = 0):
201
- return f"\033[{color_code}m"
219
+ prefix = ""
220
+ if show_proc:
221
+ if system_show_proc:
222
+ proc_part = self.process_name[:_max_proc_width].ljust(_max_proc_width)
223
+ else:
224
+ proc_part = " " * _max_proc_width
225
+ prefix += proc_part
226
+ prefix += " "
227
+ else:
228
+ if show_level:
229
+ prefix += " " * (_max_proc_width + 1)
230
+ if show_level:
231
+ if system_show_level:
232
+ level_part = level_text.ljust(level_width)
233
+ level_part = f"{ModernColor.color(level_color)}{level_part}{ModernColor.color('reset')}"
234
+ else:
235
+ level_part = " " * level_width
236
+ prefix += level_part
237
+ if show_proc:
238
+ prefix += " " * (_max_proc_width + 1)
239
+
240
+ return f"{prefix}{color_bar} {str(message)}"
@@ -8,17 +8,23 @@
8
8
 
9
9
  import sys
10
10
  import threading
11
+ from .color import ModernColor
12
+ from .logging import ModernLogging
11
13
 
12
14
  class ModernProgressBar:
13
15
  _active_bars = []
14
16
  _last_rendered = False
15
17
  _lock = threading.RLock()
16
18
 
17
- def __init__(self, total: int, process_name: str, spinner_mode=False):
19
+ def __init__(self, total: int, process_name: str, spinner_mode: bool = False, primary_color: str = "blue", secondary_color: str = "cyan", box_left: str = "[", box_right: str = "]"):
18
20
  self.total = total
21
+ self.process_name = process_name.strip()
19
22
  self.spinner_mode = spinner_mode
23
+ self.primary_color = primary_color
24
+ self.secondary_color = secondary_color
25
+ self.box_left = box_left
26
+ self.box_right = box_right
20
27
  self.current = 0
21
- self.process_name = process_name.strip()
22
28
  self.index = len(ModernProgressBar._active_bars)
23
29
  ModernProgressBar._active_bars.append(self)
24
30
  self.log_lines = 0
@@ -62,7 +68,7 @@ class ModernProgressBar:
62
68
  self._render(advance_spinner=False)
63
69
  self._start_spinner_thread_if_needed()
64
70
 
65
- def update(self, amount=1):
71
+ def update(self, amount: int = 1):
66
72
  if self._should_spin():
67
73
  self._render(advance_spinner=False)
68
74
  return
@@ -78,18 +84,12 @@ class ModernProgressBar:
78
84
  self._stop_spinner_thread()
79
85
  self._render(final=True, advance_spinner=False)
80
86
 
81
- def makeModernLogging(self, process_name: str = None):
82
- from .logging import ModernLogging
83
- if not process_name:
84
- process_name = self.process_name
85
- return ModernLogging(process_name)
86
-
87
- def logging(self, message: str = "", level: str = "INFO", modernLogging=None):
87
+ def log(self, message: str = "", level_text: str = "INFO", level_color: str | None = None, show_proc: bool | None = None, show_level: bool | None = None, modernLogging: ModernLogging = None):
88
88
  with ModernProgressBar._lock:
89
89
  self.log_lines = 0
90
90
  if modernLogging is None:
91
- modernLogging = self.makeModernLogging(self.process_name)
92
- result = modernLogging._make(message, level)
91
+ modernLogging = ModernLogging(self.process_name)
92
+ result = modernLogging.make(message=message, level_text=level_text, level_color=level_color, show_proc=show_proc, show_level=show_level)
93
93
  if self.log_lines > 0:
94
94
  move_up = self.log_lines
95
95
  else:
@@ -129,12 +129,12 @@ class ModernProgressBar:
129
129
  percentage = f"{percentage_value:3d}%"
130
130
  total_width = max(len(str(self.total)), 1)
131
131
  if final:
132
- status = "(DONE)"
132
+ status = f"{self.box_left}DONE{self.box_right}"
133
133
  elif self.spinner_mode and self._spinner_ready:
134
- status = "(RUNN)"
134
+ status = f"{self.box_left}RUNN{self.box_right}"
135
135
  else:
136
- status = f"({self.current:>{total_width}}/{self.total})"
137
- line = f"({self._color('gray')}{bar}{self._color('reset')}) {self.process_name} - {'....' if self.spinner_mode else percentage} {status} | {self.message}"
136
+ status = f"{self.box_left}{self.current:>{total_width}}/{self.total}{self.box_right}"
137
+ line = f"{ModernColor.color(self.primary_color)}{self.box_left}{ModernColor.color('reset')}{ModernColor.color('gray')}{bar}{ModernColor.color('reset')}{ModernColor.color(self.primary_color)}{self.box_right}{ModernColor.color('reset')} {self.process_name} - {'....' if self.spinner_mode else percentage} {status} | {self.message}"
138
138
  total_move_up = self.log_lines + (len(ModernProgressBar._active_bars) - self.index)
139
139
  if total_move_up > 0:
140
140
  sys.stdout.write(f"\033[{total_move_up}A")
@@ -157,48 +157,21 @@ class ModernProgressBar:
157
157
  center_bar = "-"
158
158
  filled_bar = "-"
159
159
  if self.current <= 0 and not self._spinner_ready:
160
- return f"{self._color('gray')}{empty_bar * (bar_length + 1)}"
160
+ return f"{ModernColor.color('gray')}{empty_bar * (bar_length + 1)}"
161
161
  if self.current == self.total:
162
162
  filled_length = int(progress * bar_length) + 1
163
163
  else:
164
164
  filled_length = int(progress * bar_length)
165
- return f"{self._color('blue')}{filled_bar * filled_length}{self._color('cyan')}{center_bar}{self._color('gray')}{empty_bar * (bar_length - filled_length)}"
165
+ return f"{ModernColor.color(self.primary_color)}{filled_bar * filled_length}{ModernColor.color(self.secondary_color)}{center_bar}{ModernColor.color('gray')}{empty_bar * (bar_length - filled_length)}"
166
166
  else:
167
167
  if self.current <= 0 and not self._spinner_ready:
168
- return f"{self._color('gray')}{'-' * (bar_length + 1)}"
168
+ return f"{ModernColor.color('gray')}{'-' * (bar_length + 1)}"
169
169
  spinner_symbol_length = 1
170
170
  spinner_end_bar_length = bar_length - self.spinner_step
171
171
  spinner_start_bar_length = bar_length - spinner_end_bar_length
172
172
  if advance_spinner:
173
173
  self.spinner_step = (self.spinner_step + 1) % (bar_length + 1)
174
- return f"{self._color('gray')}{'-' * spinner_start_bar_length}{self._color('blue')}{'-' * spinner_symbol_length}{self._color('gray')}{'-' * spinner_end_bar_length}"
174
+ return f"{ModernColor.color('gray')}{'-' * spinner_start_bar_length}{ModernColor.color(self.secondary_color)}{'-' * spinner_symbol_length}{ModernColor.color('gray')}{'-' * spinner_end_bar_length}"
175
175
 
176
176
  def _should_spin(self):
177
177
  return self.spinner_mode and self._spinner_ready
178
-
179
- def _color(self, color_name: str = "reset"):
180
- if color_name == "cyan":
181
- return self._color_by_code(36)
182
- elif color_name == "magenta":
183
- return self._color_by_code(35)
184
- elif color_name == "yellow":
185
- return self._color_by_code(33)
186
- elif color_name == "green":
187
- return self._color_by_code(32)
188
- elif color_name == "red":
189
- return self._color_by_code(31)
190
- elif color_name == "blue":
191
- return self._color_by_code(34)
192
- elif color_name == "white":
193
- return self._color_by_code(37)
194
- elif color_name == "black":
195
- return self._color_by_code(30)
196
- elif color_name in ("gray", "grey"):
197
- return self._color_by_code(90)
198
- elif color_name == "reset":
199
- return self._color_by_code(0)
200
- else:
201
- return ""
202
-
203
- def _color_by_code(self, color_code: int | str = 0):
204
- return f"\033[{color_code}m"
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.3
2
+ Name: nercone-modern
3
+ Version: 1.7.0
4
+ Summary: Modern CLI Library
5
+ Author: Nercone
6
+ Author-email: Nercone <nercone@diamondgotcat.net>
7
+ License: MIT
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Project-URL: Homepage, https://github.com/DiamondGotCat/nercone-modern
13
+ Description-Content-Type: text/markdown
14
+
15
+
16
+ <img width="1920" alt="nercone_modern" src="https://github.com/user-attachments/assets/15056f45-ab02-4d0d-b525-4dd51d859738" />
17
+
18
+ # nercone-modern
19
+ Modern CLI Library
20
+
21
+ ## Installation
22
+
23
+ ### uv
24
+ **Install to venv and Add to project dependencies:**
25
+ ```
26
+ uv add nercone-modern
27
+ ```
28
+
29
+ **Install to venv:**
30
+ ```
31
+ uv pip install nercone-modern
32
+ ```
33
+
34
+ ### pip
35
+ ```
36
+ pip3 install nercone-modern
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### Import
42
+
43
+ ```python
44
+ from nercone_modern.color import ModernColor
45
+ from nercone_modern.text import ModernText
46
+ from nercone_modern.logging import ModernLogging
47
+ from nercone_modern.progressbar import ModernProgressBar
48
+ ```
49
+
50
+ ### Color
51
+ ```python
52
+ from nercone_modern.color import ModernColor as Color
53
+ print(f"Build {Color.GREEN}Success{Color.RESET}")
54
+ ```
55
+
56
+ **Supported colors:**
57
+ - `CYAN`
58
+ - `MAGENTA`
59
+ - `YELLOW`
60
+ - `GREEN`
61
+ - `RED`
62
+ - `BLUE`
63
+ - `WHITE`
64
+ - `BLACK`
65
+ - `GRAY`
66
+ - `RESET`
67
+
68
+ ### Text
69
+ ```python
70
+ from nercone_modern.text import ModernText as Text
71
+ from nercone_modern.color import ModernColor as Color
72
+ print("Build" + Text("Success", color="green"))
73
+ print("Build" + Text("Failed", color=Color.RED))
74
+ ```
75
+
76
+ ### Logging
77
+ ```python
78
+ ModernLogging(
79
+ process_name: str = "App", # Process name to show in the log
80
+ display_level: str = "INFO", # The minimum level to show in the log
81
+ filepath: str | None = None, # Log file path
82
+ show_proc: bool | None = None, # Whether to show process names
83
+ show_level: bool | None = None # Whether to show level names
84
+ )
85
+ ModernLogging().log(
86
+ message: str = "", # Log contents
87
+ level_text: str = "INFO", # Level from "DEBUG", "INFO", "WARN", "ERROR" and "CRITICAL"
88
+ level_color: str # Custom color for Level (see ModernLogging.color.ModernColor)
89
+ )
90
+ ModernLogging().prompt(
91
+ message: str = "", # Log contents
92
+ level_text: str = "INFO", # Level from "DEBUG", "INFO", "WARN", "ERROR" and "CRITICAL"
93
+ level_color: str | None = None, # Custom color for Level (see ModernColor)
94
+ default: str | None = None, # Default answer
95
+ show_default: bool = False, # Whether to show default answer
96
+ choices: list[str] | None = None, # List of possible answers
97
+ show_choices: bool = True, # Whether to show choices
98
+ interrupt_ignore: bool = False, # Whether to raise an exception on KeyboardInterrupt or continue using the default argument.
99
+ interrupt_default: str | None = None # Value to use instead of the default argument when interrupt_ignore is True.
100
+ )
101
+ ```
102
+
103
+ ```python
104
+ from nercone_modern.logging import ModernLogging
105
+ logger = ModernLogging("Main", display_level="DEBUG")
106
+ logger.log("This is a test message", level_text="INFO", level_color="magenta")
107
+ answer = logger.prompt("What's your name?", level_text="INFO")
108
+ logger.log(f"Answer: {answer}", level_text="DEBUG")
109
+ answer2 = logger.prompt("Select mode", default="A", choices=["A", "b", "c", "d"], level_text="INFO")
110
+ logger.log(f"Mode: {answer2}", level_text="DEBUG")
111
+ ```
112
+
113
+ **Supported levels:**
114
+ - `DEBUG`
115
+ - `INFO`
116
+ - `WARN`
117
+ - `ERROR`
118
+ - `CRITICAL`
119
+
120
+ ### Progress Bar
121
+ ```python
122
+ ModernProgressBar(
123
+ total: int, # Total number of steps (max progress value)
124
+ process_name: str, # Name of the process shown next to the bar
125
+ spinner_mode: bool = False, # Whether to start in spinner mode instead of progress (spinner-only) mode
126
+ primary_color: str = "blue", # Color used for filled bar and brackets (see ModernColor)
127
+ secondary_color: str = "cyan", # Color used for center marker / spinner (see ModernColor)
128
+ box_left: str = "[", # Left bracket surrounding the bar and status
129
+ box_right: str = "]" # Right bracket surrounding the bar and status
130
+ )
131
+ ModernProgressBar().spinner(
132
+ enabled: bool = True # Enable or disable spinner mode dynamically
133
+ )
134
+ ModernProgressBar().spin_start() # Start spinner animation immediately
135
+ ModernProgressBar().setMessage(
136
+ message: str = "" # Message to show after the status (e.g. current step description)
137
+ )
138
+ ModernProgressBar().start() # Initial rendering and start of spinner (if enabled)
139
+ ModernProgressBar().update(
140
+ amount: int = 1 # Increase current progress by the specified amount and re-render
141
+ )
142
+ ModernProgressBar().finish() # Mark as complete, stop spinner and render final DONE state
143
+ ModernProgressBar().log(
144
+ message: str = "", # Log contents printed above the progress bar
145
+ level_text: str = "INFO", # Level from "DEBUG", "INFO", "WARN", "ERROR" and "CRITICAL"
146
+ level_color: str | None = None, # Custom color for Level (see ModernColor)
147
+ show_proc: bool | None = None, # Whether to show process names (fallbacks to ModernLogging settings)
148
+ show_level: bool | None = None, # Whether to show level names (fallbacks to ModernLogging settings)
149
+ modernLogging: ModernLogging = None # Existing ModernLogging instance to reuse. If None, a new one is created.
150
+ )
151
+ ```
152
+
153
+ ```python
154
+ from nercone_modern.progressbar import ModernProgressBar
155
+ progress_bar = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=True)
156
+
157
+ progress_bar.start()
158
+ time.sleep(5)
159
+
160
+ progress_bar.spinner(False)
161
+
162
+ progress_bar.setMessage("Step 1")
163
+
164
+ for i in range(50):
165
+ time.sleep(0.05)
166
+ progress_bar.update(amount=1)
167
+
168
+ progress_bar.setMessage("Step 2")
169
+
170
+ for i in range(25):
171
+ time.sleep(0.03)
172
+ progress_bar.update(amount=1)
173
+
174
+ progress_bar.setMessage("Step 3")
175
+
176
+ for i in range(5):
177
+ time.sleep(1)
178
+ progress_bar.update(amount=5)
179
+
180
+ progress_bar.finish()
181
+ ```
182
+
183
+ ---
184
+
185
+ ![PyPI - Version](https://img.shields.io/pypi/v/nercone-modern)
@@ -0,0 +1,9 @@
1
+ nercone_modern/__init__.py,sha256=ArF3T8FdWIhwGcL4MfYcHqMse3n5gjuyzbLNlcqRcxs,443
2
+ nercone_modern/__main__.py,sha256=5XLj1f0jTdi1IhDq79gXCQeGDIBLAkW4b_PzK9B4zj8,2458
3
+ nercone_modern/color.py,sha256=e2P9WXeGosHLCAasdE7IQW29GPZOVDMLsUCsLj6hBkM,1268
4
+ nercone_modern/logging.py,sha256=61ixjR37-ewS1RUwnNZnkNGQEBazhiSJJv5g-rLq834,10158
5
+ nercone_modern/progressbar.py,sha256=QaDqfxa9XUmI3kfw7ueuRHwylAZGm-L3d7sG7PzV1tE,7782
6
+ nercone_modern/text.py,sha256=eGxGQOJ3b-783ocLibkG62cOcYD4HLG_3diA52tU8jI,1031
7
+ nercone_modern-1.7.0.dist-info/WHEEL,sha256=w4ZtLaDgMAZW2MMZZwtH8zENekoQYBCeullI-zsXJQk,78
8
+ nercone_modern-1.7.0.dist-info/METADATA,sha256=mYxhpUMYgG2N9Fu2XcSudMC3rp7HQt8zwf10BLxKIr4,6127
9
+ nercone_modern-1.7.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.8
2
+ Generator: uv 0.9.9
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,121 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: nercone-modern
3
- Version: 1.6.1
4
- Summary: Modern CLI Library
5
- Author: Nercone
6
- Author-email: Nercone <nercone@diamondgotcat.net>
7
- License: MIT
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.6
12
- Project-URL: Homepage, https://github.com/DiamondGotCat/nercone-modern
13
- Description-Content-Type: text/markdown
14
-
15
-
16
- <img width="1920" alt="Nercone Modern" src="https://github.com/user-attachments/assets/c92b0407-916f-46ec-9116-c3388b38c88c" />
17
-
18
- # nercone-modern
19
- Modern CLI Library
20
-
21
- ## Installation
22
-
23
- ### uv
24
- **Install to venv and Add to project dependencies:**
25
- ```
26
- uv add nercone-modern
27
- ```
28
-
29
- **Install to venv:**
30
- ```
31
- uv pip install nercone-modern
32
- ```
33
-
34
- ### pip
35
- ```
36
- pip3 install nercone-modern
37
- ```
38
-
39
- ## Usage
40
-
41
- ### Import
42
-
43
- ```python
44
- from nercone_modern.color import ModernColor
45
- from nercone_modern.text import ModernText
46
- from nercone_modern.logging import ModernLogging
47
- from nercone_modern.progressbar import ModernProgressBar
48
- ```
49
-
50
- ### Color
51
- ```python
52
- from nercone_modern.color import ModernColor as Color
53
- print(f"Build {Color.GREEN}Success{Color.RESET}")
54
- ```
55
-
56
- **Supported colors:**
57
- - `CYAN`
58
- - `MAGENTA`
59
- - `YELLOW`
60
- - `GREEN`
61
- - `RED`
62
- - `BLUE`
63
- - `WHITE`
64
- - `BLACK`
65
- - `GRAY`
66
- - `RESET`
67
-
68
- ### Text
69
- ```python
70
- from nercone_modern.text import ModernText as Text
71
- from nercone_modern.color import ModernColor as Color
72
- print("Build" + Text("Success", color="green"))
73
- print("Build" + Text("Failed", color=Color.RED))
74
- ```
75
-
76
- ### Logging
77
- ```python
78
- from nercone_modern.logging import ModernLogging
79
- logger = ModernLogging("Main", display_level="DEBUG")
80
- logger.log("This is a test message", level="INFO")
81
- answer = logger.prompt("What's your name?", level="INFO")
82
- logger.log(f"Answer: {answer}", level="DEBUG")
83
- ```
84
-
85
- **Supported levels:**
86
- - `DEBUG`
87
- - `INFO`
88
- - `WARN`
89
- - `ERROR`
90
- - `CRITICAL`
91
-
92
- ### Progress Bar
93
- ```python
94
- from nercone_modern.progressbar import ModernProgressBar
95
- progress_bar = ModernProgressBar(total=100, process_name="Task 1", spinner_mode=True)
96
-
97
- progress_bar.start()
98
- time.sleep(5)
99
-
100
- progress_bar.spinner(False)
101
-
102
- progress_bar.setMessage("Step 1")
103
-
104
- for i in range(50):
105
- time.sleep(0.05)
106
- progress_bar.update(amount=1)
107
-
108
- progress_bar.setMessage("Step 2")
109
-
110
- for i in range(25):
111
- time.sleep(0.03)
112
- progress_bar.update(amount=1)
113
-
114
- progress_bar.setMessage("Step 3")
115
-
116
- for i in range(5):
117
- time.sleep(1)
118
- progress_bar.update(amount=5)
119
-
120
- progress_bar.finish()
121
- ```
@@ -1,9 +0,0 @@
1
- nercone_modern/__init__.py,sha256=ArF3T8FdWIhwGcL4MfYcHqMse3n5gjuyzbLNlcqRcxs,443
2
- nercone_modern/__main__.py,sha256=EDFIQTNrAwT4V5nzcjyn-FtAbR1g8iskDiBR7Kco1WQ,2069
3
- nercone_modern/color.py,sha256=sy7f0Fe07PZWNfM1AOt7HeuhF7uGK2_IuZHEckwgxc4,1328
4
- nercone_modern/logging.py,sha256=S_OyfAe-XbqII0wvB0wgyjlfKPokWBSG5aOu0YsPgJE,8219
5
- nercone_modern/progressbar.py,sha256=bzlGg0dSj88eli2lM0cI4xTw2FNJqlJb352jdtJbsWQ,8088
6
- nercone_modern/text.py,sha256=eGxGQOJ3b-783ocLibkG62cOcYD4HLG_3diA52tU8jI,1031
7
- nercone_modern-1.6.1.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
8
- nercone_modern-1.6.1.dist-info/METADATA,sha256=SseIvl73T1dY3ypUeuHVr2zUB7nREj1yBgQSwPxIyLw,2472
9
- nercone_modern-1.6.1.dist-info/RECORD,,