first rev
This commit is contained in:
commit
e6466fc51d
6 changed files with 580 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
.venv
|
||||||
310
cli_tool.py
Normal file
310
cli_tool.py
Normal file
|
|
@ -0,0 +1,310 @@
|
||||||
|
"""
|
||||||
|
cmd2-like CLI framework using prompt_toolkit with:
|
||||||
|
|
||||||
|
- Color support
|
||||||
|
- Command history search
|
||||||
|
- Script execution
|
||||||
|
- Nested commands
|
||||||
|
- Session logging
|
||||||
|
"""
|
||||||
|
|
||||||
|
from prompt_toolkit import PromptSession, HTML
|
||||||
|
from prompt_toolkit.history import FileHistory
|
||||||
|
from prompt_toolkit.completion import Completer, Completion
|
||||||
|
from prompt_toolkit.lexers import PygmentsLexer
|
||||||
|
from prompt_toolkit.styles import Style
|
||||||
|
from pygments.lexers.shell import BashLexer
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Custom color style
|
||||||
|
custom_style = Style.from_dict({
|
||||||
|
'prompt': 'ansicyan bold',
|
||||||
|
'command': 'ansigreen',
|
||||||
|
'error': 'ansired bold',
|
||||||
|
'warning': 'ansiyellow',
|
||||||
|
'info': 'ansiblue',
|
||||||
|
'success': 'ansigreen bold',
|
||||||
|
})
|
||||||
|
|
||||||
|
class CommandCompleter(Completer):
|
||||||
|
"""Provides autocompletion for commands and their arguments"""
|
||||||
|
def __init__(self, cli):
|
||||||
|
self.cli = cli
|
||||||
|
|
||||||
|
def get_completions(self, document, complete_event):
|
||||||
|
text = document.text_before_cursor.split()
|
||||||
|
|
||||||
|
# Command name completion
|
||||||
|
if len(text) == 0 or (len(text) == 1 and not document.text.endswith(' ')):
|
||||||
|
prefix = text[0] if text else ''
|
||||||
|
for cmd in self.cli.get_commands():
|
||||||
|
if cmd.startswith(prefix):
|
||||||
|
yield Completion(
|
||||||
|
cmd,
|
||||||
|
start_position=-len(prefix),
|
||||||
|
display=cmd,
|
||||||
|
display_meta=self.cli.get_command_help(cmd)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Command argument completion
|
||||||
|
elif len(text) >= 1:
|
||||||
|
cmd = text[0]
|
||||||
|
arg_completer = getattr(self.cli, f'argcompleter_{cmd}', None)
|
||||||
|
if arg_completer:
|
||||||
|
args = ' '.join(text[1:])
|
||||||
|
for comp in arg_completer(args):
|
||||||
|
yield Completion(comp, start_position=-len(document.current_line))
|
||||||
|
|
||||||
|
class Cmd2LikeCLI:
|
||||||
|
"""Main CLI class with advanced features"""
|
||||||
|
def __init__(self):
|
||||||
|
self.session = PromptSession(
|
||||||
|
history=FileHistory('.cmd_history'),
|
||||||
|
completer=CommandCompleter(self),
|
||||||
|
lexer=PygmentsLexer(BashLexer),
|
||||||
|
complete_while_typing=True,
|
||||||
|
enable_history_search=True,
|
||||||
|
style=custom_style
|
||||||
|
)
|
||||||
|
self.prompt = HTML('<prompt>>>> </prompt>')
|
||||||
|
self.intro = self.colorize("Welcome to Advanced CLI (Type 'help' for commands)", "info")
|
||||||
|
self.logging_active = False
|
||||||
|
self.log_file = None
|
||||||
|
self.log_file_path = "cli_session.log"
|
||||||
|
|
||||||
|
def colorize(self, text, style_type):
|
||||||
|
"""Apply color to text based on style type"""
|
||||||
|
styles = {
|
||||||
|
"command": "<command>{}</command>",
|
||||||
|
"error": "<error>{}</error>",
|
||||||
|
"warning": "<warning>{}</warning>",
|
||||||
|
"info": "<info>{}</info>",
|
||||||
|
"success": "<success>{}</success>",
|
||||||
|
}
|
||||||
|
return HTML(styles.get(style_type, "{}").format(text))
|
||||||
|
|
||||||
|
def get_commands(self):
|
||||||
|
"""Retrieves all available commands (methods starting with 'do_')"""
|
||||||
|
return [
|
||||||
|
name[3:] for name, _ in inspect.getmembers(self, inspect.ismethod)
|
||||||
|
if name.startswith('do_')
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_command_help(self, cmd):
|
||||||
|
"""Gets help text from command's docstring"""
|
||||||
|
method = getattr(self, f'do_{cmd}', None)
|
||||||
|
return method.__doc__.strip() if method and method.__doc__ else "No help available"
|
||||||
|
|
||||||
|
def start_logging(self):
|
||||||
|
"""Start session logging"""
|
||||||
|
try:
|
||||||
|
self.log_file = open(self.log_file_path, 'a')
|
||||||
|
self.logging_active = True
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
self.log_file.write(f"\n\n--- Session started at {timestamp} ---\n")
|
||||||
|
print(self.colorize(f"Logging started to {self.log_file_path}", "success"))
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error starting logging: {e}", "error"))
|
||||||
|
|
||||||
|
def stop_logging(self):
|
||||||
|
"""Stop session logging"""
|
||||||
|
if self.logging_active:
|
||||||
|
try:
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
self.log_file.write(f"\n--- Session ended at {timestamp} ---\n")
|
||||||
|
self.log_file.close()
|
||||||
|
self.logging_active = False
|
||||||
|
print(self.colorize("Logging stopped", "success"))
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error stopping logging: {e}", "error"))
|
||||||
|
|
||||||
|
def log_command(self, command):
|
||||||
|
"""Log command to file if logging is active"""
|
||||||
|
if self.logging_active:
|
||||||
|
try:
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
self.log_file.write(f"[{timestamp}] {command}\n")
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Logging error: {e}", "error"))
|
||||||
|
|
||||||
|
def cmdloop(self):
|
||||||
|
"""Main REPL loop with nested command support"""
|
||||||
|
print(self.intro)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
user_input = self.session.prompt(self.prompt)
|
||||||
|
# Process nested commands (separated by semicolons)
|
||||||
|
for cmd in user_input.split(';'):
|
||||||
|
cmd = cmd.strip()
|
||||||
|
if cmd:
|
||||||
|
self.onecmd(cmd)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print(self.colorize("\nUse 'exit' to quit", "warning"))
|
||||||
|
except EOFError:
|
||||||
|
self.do_exit("")
|
||||||
|
break
|
||||||
|
|
||||||
|
def onecmd(self, line):
|
||||||
|
"""Executes a single command"""
|
||||||
|
line = line.strip()
|
||||||
|
if not line:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Log command before execution
|
||||||
|
self.log_command(line)
|
||||||
|
|
||||||
|
parts = line.split(maxsplit=1)
|
||||||
|
cmd_name = parts[0]
|
||||||
|
args = parts[1] if len(parts) > 1 else ""
|
||||||
|
|
||||||
|
if cmd_name == "help":
|
||||||
|
self.do_help(args)
|
||||||
|
return
|
||||||
|
|
||||||
|
method_name = f"do_{cmd_name}"
|
||||||
|
method = getattr(self, method_name, None)
|
||||||
|
|
||||||
|
if method:
|
||||||
|
try:
|
||||||
|
method(args)
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error executing command: {e}", "error"))
|
||||||
|
else:
|
||||||
|
print(self.colorize(f"Unknown command: {cmd_name}", "error"))
|
||||||
|
|
||||||
|
def run_script(self, file_path):
|
||||||
|
"""Execute commands from a script file"""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#'): # Skip empty lines and comments
|
||||||
|
print(self.colorize(f"Executing: {line}", "info"))
|
||||||
|
self.onecmd(line)
|
||||||
|
print(self.colorize(f"Script '{file_path}' executed successfully", "success"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(self.colorize(f"Script file not found: {file_path}", "error"))
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error executing script: {e}", "error"))
|
||||||
|
|
||||||
|
# ------------ Built-in commands ------------
|
||||||
|
def do_help(self, arg):
|
||||||
|
"""Show help for commands"""
|
||||||
|
if arg:
|
||||||
|
# Command-specific help
|
||||||
|
help_text = self.get_command_help(arg)
|
||||||
|
print(f"{self.colorize(arg, 'command')}: {help_text}")
|
||||||
|
else:
|
||||||
|
# List all commands
|
||||||
|
print(self.colorize("\nAvailable commands:", "info"))
|
||||||
|
for cmd in self.get_commands():
|
||||||
|
print(f" {self.colorize(cmd, 'command'):15} {self.get_command_help(cmd)}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def do_echo(self, arg):
|
||||||
|
"""Echo back the input"""
|
||||||
|
print(f"Echo: {arg}")
|
||||||
|
|
||||||
|
def do_exit(self, arg):
|
||||||
|
"""Exit the application"""
|
||||||
|
self.stop_logging()
|
||||||
|
print(self.colorize("Goodbye!", "success"))
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
def do_ls(self, arg):
|
||||||
|
"""List directory contents"""
|
||||||
|
path = arg.strip() if arg else "."
|
||||||
|
try:
|
||||||
|
files = os.listdir(path)
|
||||||
|
for f in files:
|
||||||
|
full_path = os.path.join(path, f)
|
||||||
|
if os.path.isdir(full_path):
|
||||||
|
print(self.colorize(f + "/", "info"))
|
||||||
|
else:
|
||||||
|
print(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(self.colorize(f"Directory not found: {path}", "error"))
|
||||||
|
|
||||||
|
def do_run_script(self, arg):
|
||||||
|
"""Execute commands from a script file"""
|
||||||
|
if not arg:
|
||||||
|
print(self.colorize("Please specify a script file", "warning"))
|
||||||
|
return
|
||||||
|
self.run_script(arg.strip())
|
||||||
|
|
||||||
|
def do_log_start(self, arg):
|
||||||
|
"""Start session logging"""
|
||||||
|
if arg:
|
||||||
|
self.log_file_path = arg.strip()
|
||||||
|
self.start_logging()
|
||||||
|
|
||||||
|
def do_log_stop(self, arg):
|
||||||
|
"""Stop session logging"""
|
||||||
|
self.stop_logging()
|
||||||
|
|
||||||
|
def do_save_history(self, arg):
|
||||||
|
"""Save command history to file"""
|
||||||
|
file_path = arg.strip() if arg else "command_history.txt"
|
||||||
|
try:
|
||||||
|
with open('.cmd_history', 'r') as src, open(file_path, 'w') as dest:
|
||||||
|
dest.write(f"Command History - Saved at {datetime.datetime.now()}\n\n")
|
||||||
|
dest.writelines(src.readlines())
|
||||||
|
print(self.colorize(f"History saved to {file_path}", "success"))
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error saving history: {e}", "error"))
|
||||||
|
|
||||||
|
def do_system(self, arg):
|
||||||
|
"""Execute a system shell command"""
|
||||||
|
if not arg:
|
||||||
|
print(self.colorize("Please specify a command to execute", "warning"))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
arg,
|
||||||
|
shell=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
if result.stdout:
|
||||||
|
print(result.stdout)
|
||||||
|
if result.stderr:
|
||||||
|
print(self.colorize(result.stderr, "error"))
|
||||||
|
print(self.colorize(f"Command exited with code: {result.returncode}", "info"))
|
||||||
|
except Exception as e:
|
||||||
|
print(self.colorize(f"Error executing system command: {e}", "error"))
|
||||||
|
|
||||||
|
# ------------ Custom argument completers ------------
|
||||||
|
def argcompleter_ls(self, arg):
|
||||||
|
"""Directory completer for ls command"""
|
||||||
|
current_dir = os.path.dirname(arg) if arg else "."
|
||||||
|
base_name = os.path.basename(arg) if arg else ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
f.name for f in os.scandir(current_dir)
|
||||||
|
if f.name.startswith(base_name)
|
||||||
|
]
|
||||||
|
except FileNotFoundError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def argcompleter_run_script(self, arg):
|
||||||
|
"""File completer for run_script command"""
|
||||||
|
current_dir = os.path.dirname(arg) if arg else "."
|
||||||
|
base_name = os.path.basename(arg) if arg else ""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
f.name for f in os.scandir(current_dir)
|
||||||
|
if f.is_file() and f.name.startswith(base_name)
|
||||||
|
]
|
||||||
|
except FileNotFoundError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli = Cmd2LikeCLI()
|
||||||
|
cli.cmdloop()
|
||||||
19
licence.txt
Normal file
19
licence.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2025 WhirlingAI (contact@whirlingai.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
228
readme.rst
Normal file
228
readme.rst
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
Advanced CLI Framework with Prompt Toolkit
|
||||||
|
============================================
|
||||||
|
|
||||||
|
..
|
||||||
|
|
||||||
|
1. Clear feature overview with emoji icons
|
||||||
|
2. Installation instructions
|
||||||
|
3. Basic usage example
|
||||||
|
4. Command reference table
|
||||||
|
5. Detailed advanced usage scenarios
|
||||||
|
6. Customization guide for extending functionality
|
||||||
|
7. Example session demonstrating key features
|
||||||
|
8. Troubleshooting section
|
||||||
|
9. License and contribution information
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A feature-rich Python command-line interface framework inspired by cmd2 but built on prompt_toolkit with:
|
||||||
|
|
||||||
|
- Full color support
|
||||||
|
- Command history search
|
||||||
|
- Script execution capability
|
||||||
|
- Nested command support
|
||||||
|
- Session logging
|
||||||
|
- Command history saving
|
||||||
|
|
||||||
|
.. contents:: This README provides comprehensive documentation for your advanced CLI framework, including:
|
||||||
|
:depth: 1
|
||||||
|
:numbered:
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- 🎨 **Color Support**: Custom color scheme for commands, errors, and information
|
||||||
|
- 🔍 **History Search**: Press ``Ctrl+R`` to search through command history
|
||||||
|
- 📜 **Script Execution**: Run batch commands from files
|
||||||
|
- 🔗 **Nested Commands**: Execute multiple commands separated by semicolons
|
||||||
|
- 📝 **Session Logging**: Record entire sessions to files
|
||||||
|
- 💾 **History Saving**: Export command history to files
|
||||||
|
- 💻 **System Commands**: Execute shell commands directly
|
||||||
|
- 🚦 **Error Handling**: Colored error messages with details
|
||||||
|
- 🤖 **Smart Autocompletion**: Context-aware suggestions for commands and arguments
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install prompt_toolkit pygments
|
||||||
|
|
||||||
|
Basic Usage
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
python advanced_cli.py
|
||||||
|
|
||||||
|
Key Commands
|
||||||
|
------------
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| Command | Description |
|
||||||
|
+===============+=======================================================+
|
||||||
|
| help | Show help for commands |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| echo | Echo back the input |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| exit | Exit the application |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| ls | List directory contents (with color) |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| run_script | Execute commands from a script file |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| log_start | Start session logging (optional filename argument) |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| log_stop | Stop session logging |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| save_history | Save command history to file |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
| system | Execute a system shell command |
|
||||||
|
+---------------+-------------------------------------------------------+
|
||||||
|
|
||||||
|
Advanced Usage
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1. **Colorized Output**:
|
||||||
|
The CLI automatically colorizes different types of messages:
|
||||||
|
- Commands: Green
|
||||||
|
- Errors: Red
|
||||||
|
- Information: Blue
|
||||||
|
- Success messages: Bright Green
|
||||||
|
- Directories in listings: Blue
|
||||||
|
|
||||||
|
2. **Nested Commands**:
|
||||||
|
Execute multiple commands in one line by separating them with semicolons:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
>>> echo Hello; echo World; ls
|
||||||
|
|
||||||
|
3. **Script Execution**:
|
||||||
|
Create a script file (e.g., ``commands.txt``):
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
# My command script
|
||||||
|
echo Running script
|
||||||
|
ls
|
||||||
|
system date
|
||||||
|
|
||||||
|
Then execute it:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
>>> run_script commands.txt
|
||||||
|
|
||||||
|
4. **Session Logging**:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
# Start logging to a file
|
||||||
|
>>> log_start session.log
|
||||||
|
|
||||||
|
# Execute commands...
|
||||||
|
>>> echo This is being logged
|
||||||
|
>>> ls
|
||||||
|
|
||||||
|
# Stop logging
|
||||||
|
>>> log_stop
|
||||||
|
|
||||||
|
5. **History Management**:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
# Save command history to file
|
||||||
|
>>> save_history my_history.txt
|
||||||
|
|
||||||
|
6. **System Commands**:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
# Execute any system command
|
||||||
|
>>> system ls -l
|
||||||
|
>>> system python --version
|
||||||
|
|
||||||
|
Customization
|
||||||
|
-------------
|
||||||
|
1. **Add New Commands**:
|
||||||
|
Create methods starting with ``do_`` in the CLI class:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def do_mycommand(self, arg):
|
||||||
|
"""Description of mycommand"""
|
||||||
|
print(f"Executed with: {arg}")
|
||||||
|
|
||||||
|
2. **Custom Argument Completion**:
|
||||||
|
Implement argument completers for your commands:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def argcompleter_mycommand(self, arg):
|
||||||
|
return ["option1", "option2", "option3"]
|
||||||
|
|
||||||
|
3. **Modify Colors**:
|
||||||
|
Edit the style dictionary in the ``__init__`` method:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
custom_style = Style.from_dict({
|
||||||
|
'prompt': 'ansicyan bold',
|
||||||
|
'command': 'ansigreen',
|
||||||
|
'error': 'ansired bold',
|
||||||
|
# ... other styles ...
|
||||||
|
})
|
||||||
|
|
||||||
|
Example Session
|
||||||
|
---------------
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
Welcome to Advanced CLI (Type 'help' for commands)
|
||||||
|
>>> log_start session.log
|
||||||
|
Logging started to session.log
|
||||||
|
|
||||||
|
>>> ls; system date
|
||||||
|
file1.txt
|
||||||
|
file2.py
|
||||||
|
docs/
|
||||||
|
Tue Jun 19 15:30:45 CEST 2025
|
||||||
|
|
||||||
|
>>> run_script commands.txt
|
||||||
|
Executing: echo Running script
|
||||||
|
Echo: Running script
|
||||||
|
Executing: ls
|
||||||
|
file1.txt
|
||||||
|
file2.py
|
||||||
|
docs/
|
||||||
|
Executing: system date
|
||||||
|
Tue Jun 19 15:31:22 CEST 2025
|
||||||
|
Script 'commands.txt' executed successfully
|
||||||
|
|
||||||
|
>>> save_history
|
||||||
|
History saved to command_history.txt
|
||||||
|
|
||||||
|
>>> exit
|
||||||
|
Goodbye!
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
---------------
|
||||||
|
|
||||||
|
- **Command not recognized**: Ensure your method starts with ``do_`` prefix
|
||||||
|
- **Autocompletion not working**: Implement ``argcompleter_<command>`` method
|
||||||
|
- **Logging errors**: Check file write permissions
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
MIT License - Free for personal and commercial use
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create your feature branch
|
||||||
|
3. Commit your changes
|
||||||
|
4. Push to the branch
|
||||||
|
5. Create a new Pull Request
|
||||||
|
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
prompt_toolkit
|
||||||
|
pygments
|
||||||
20
todo.txt
Normal file
20
todo.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
- à ajouter au repos defder
|
||||||
|
|
||||||
|
pourquoi HTML output ?
|
||||||
|
|
||||||
|
cli_tool.py
|
||||||
|
HTML("<info>Welcome to Advanced CLI (Type 'help' for commands)</info>")
|
||||||
|
>>> help
|
||||||
|
HTML('<info>\nAvailable commands:</info>')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/media/gwen/68b01d87-e6a9-4152-acec-dc46320b5c78/gwen/defder/repos_lab/clitool/cli_tool.py", line 310, in <module>
|
||||||
|
cli.cmdloop()
|
||||||
|
File "/media/gwen/68b01d87-e6a9-4152-acec-dc46320b5c78/gwen/defder/repos_lab/clitool/cli_tool.py", line 144, in cmdloop
|
||||||
|
self.onecmd(cmd)
|
||||||
|
File "/media/gwen/68b01d87-e6a9-4152-acec-dc46320b5c78/gwen/defder/repos_lab/clitool/cli_tool.py", line 165, in onecmd
|
||||||
|
self.do_help(args)
|
||||||
|
File "/media/gwen/68b01d87-e6a9-4152-acec-dc46320b5c78/gwen/defder/repos_lab/clitool/cli_tool.py", line 205, in do_help
|
||||||
|
print(f" {self.colorize(cmd, 'command'):15} {self.get_command_help(cmd)}")
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
TypeError: unsupported format string passed to HTML.__format__
|
||||||
|
|
||||||
Loading…
Reference in a new issue