3 Commits

Author SHA1 Message Date
61a37bcd0f patch bump 2026-02-28 15:48:28 +00:00
b62ee185c3 upd use section in README 2026-02-28 15:39:39 +00:00
c7365bfe4e add new help formatters for different kinds of commands 2026-02-28 15:39:26 +00:00
10 changed files with 139 additions and 46 deletions

View File

@@ -5,6 +5,8 @@
--- ---
This CLI is still in an early stage of development with many more things that could be implemented. However, the commands that are implemented should be working without issues.
## Install ## Install
#### With uv #### With uv
@@ -47,24 +49,35 @@ export VBAN_CLI_STREAMNAME=Command1
## Use ## Use
```console ### Strip Command
Usage: vban-cli COMMAND
╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────╮ Usage: vban-cli strip <index> COMMAND [ARGS]
│ bus Control the bus parameters. │
│ strip Control the strip parameters. │ examples:
│ --help (-h) Display this message and exit. │
│ --version Display application version. │ ```console
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ vban-cli strip 0 mute true
╭─ Parameters ─────────────────────────────────────────────────────────────────────────────────────╮
│ --kind Kind of Voicemeeter [env var: VBAN_CLI_KIND] [default: potato] │ vban-cli strip 1 A1 true
│ --host VBAN host [env var: VBAN_CLI_HOST] [default: localhost] │
│ --port VBAN port [env var: VBAN_CLI_PORT] [default: 6980] │ vban-cli strip 2 gain -18.7
│ --streamname VBAN stream name [env var: VBAN_CLI_STREAMNAME] [default: Command1] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
``` ```
For every command and subcommand there exists a `--help` flag for further usage information. see `vban-cli strip --help` for more info.
### Bus Command
Usage: vban-cli bus <index> COMMAND [ARGS]
examples:
```console
vban-cli bus mode normal
vban-cli bus mute true
```
see `vban-cli bus --help` for more info.
--- ---

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "vban-cli" name = "vban-cli"
version = "0.4.1" version = "0.4.2"
description = "A command-line interface for Voicemeeter leveraging VBAN." description = "A command-line interface for Voicemeeter leveraging VBAN."
readme = "README.md" readme = "README.md"
license = { text = "LICENSE" } license = { text = "LICENSE" }

View File

@@ -4,9 +4,9 @@ from cyclopts import App, Argument, Parameter
from . import console from . import console
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import BusHelpFormatter
app = App(name='bus', help_formatter=CustomHelpFormatter()) app = App(name='bus', help_formatter=BusHelpFormatter())
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 1. # See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 1.
# app.command(eq.app.meta, name='eq') # app.command(eq.app.meta, name='eq')

View File

@@ -3,9 +3,9 @@ from typing import Annotated
from cyclopts import App, Argument, Parameter from cyclopts import App, Argument, Parameter
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import StripSubcommandHelpFormatter
app = App(name='comp', help_formatter=CustomHelpFormatter()) app = App(name='comp', help_formatter=StripSubcommandHelpFormatter())
@app.meta.default @app.meta.default

View File

@@ -3,9 +3,9 @@ from typing import Annotated
from cyclopts import App, Argument, Parameter from cyclopts import App, Argument, Parameter
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import StripSubcommandHelpFormatter
app = App(name='denoiser', help_formatter=CustomHelpFormatter()) app = App(name='denoiser', help_formatter=StripSubcommandHelpFormatter())
@app.meta.default @app.meta.default

View File

@@ -3,11 +3,11 @@ from typing import Annotated
from cyclopts import App, Argument, Parameter from cyclopts import App, Argument, Parameter
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import CellHelpFormatter, EqHelpFormatter
cell_app = App(name='cell', help_formatter=CustomHelpFormatter()) cell_app = App(name='cell', help_formatter=CellHelpFormatter())
app = App(name='eq', help_formatter=CustomHelpFormatter()) app = App(name='eq', help_formatter=EqHelpFormatter())
app.command(cell_app.meta, name='cell') app.command(cell_app.meta, name='cell')

View File

@@ -3,9 +3,9 @@ from typing import Annotated
from cyclopts import App, Argument, Parameter from cyclopts import App, Argument, Parameter
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import StripSubcommandHelpFormatter
app = App(name='gate', help_formatter=CustomHelpFormatter()) app = App(name='gate', help_formatter=StripSubcommandHelpFormatter())
@app.meta.default @app.meta.default

View File

@@ -4,31 +4,24 @@ from cyclopts.help import DefaultFormatter, HelpPanel
from rich.console import Console, ConsoleOptions from rich.console import Console, ConsoleOptions
class CustomHelpFormatter(DefaultFormatter): class BaseHelpFormatter(DefaultFormatter):
"""Custom help formatter that injects an index argument into the usage line and filters it out from the parameters list. """Base help formatter that provides common functionality."""
This formatter modifies the usage line to include an <index> argument after the 'strip' command,
and filters out any parameters related to 'index' from the Parameters section of the help output.
"""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with index argument injected."""
if usage:
modified_usage = re.sub(
r'(\S+\s+[a-z]+)\s+(COMMAND)', r'\1 <index> \2', str(usage)
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')
def __call__( def __call__(
self, console: Console, options: ConsoleOptions, panel: HelpPanel self, console: Console, options: ConsoleOptions, panel: HelpPanel
) -> None: ) -> None:
"""Render a help panel, filtering out the index parameter from Parameters sections.""" """Render a help panel, filtering out hidden parameters from Parameters sections."""
if panel.title == 'Parameters': if panel.title == 'Parameters':
filtered_entries = [ filtered_entries = [
entry entry
for entry in panel.entries for entry in panel.entries
if not ( if not (
entry.names and any('index' in name.lower() for name in entry.names) entry.names
and any(
param in name.lower()
for name in entry.names
for param in self.get_filtered_params()
)
) )
] ]
@@ -41,3 +34,90 @@ class CustomHelpFormatter(DefaultFormatter):
super().__call__(console, options, filtered_panel) super().__call__(console, options, filtered_panel)
else: else:
super().__call__(console, options, panel) super().__call__(console, options, panel)
def get_filtered_params(self):
"""Return list of parameter names to filter out of help output."""
return ['index', 'band', 'ctx', 'target', 'eq_kind']
class StripHelpFormatter(BaseHelpFormatter):
"""Help formatter for strip commands that injects <index> after 'strip'."""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with index argument injected after 'strip'.
Handles both command groups (COMMAND) and individual commands (commandname [ARGS/OPTIONS]).
"""
if usage:
modified_usage = re.sub(
r'(\S+\s+strip)\s+(\w+\s+\[[^\]]+\]|\w+\s+\[[^\]]+\]|\w+(?:\s+\[[^\]]+\])*|COMMAND)',
r'\1 <index> \2',
str(usage),
)
if modified_usage == str(usage):
modified_usage = re.sub(
r'(\S+\s+strip)\s+(\w+)', r'\1 <index> \2', str(usage)
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')
class StripSubcommandHelpFormatter(BaseHelpFormatter):
"""Help formatter for strip subcommands that injects <index> after 'strip'."""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with index argument injected after 'strip'."""
if usage:
modified_usage = re.sub(
r'(\S+\s+strip)\s+(\w+)\s+(COMMAND)', r'\1 <index> \2 \3', str(usage)
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')
class BusHelpFormatter(BaseHelpFormatter):
"""Help formatter for bus commands that injects <index> after 'bus'."""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with index argument injected after 'bus'.
Handles both command groups (COMMAND) and individual commands (commandname [ARGS/OPTIONS])."""
if usage:
modified_usage = re.sub(
r'(\S+\s+bus)\s+(\w+\s+\[[^\]]+\]|\w+\s+\[[^\]]+\]|\w+(?:\s+\[[^\]]+\])*|COMMAND)',
r'\1 <index> \2',
str(usage),
)
if modified_usage == str(usage):
modified_usage = re.sub(
r'(\S+\s+bus)\s+(\w+)', r'\1 <index> \2', str(usage)
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')
class EqHelpFormatter(BaseHelpFormatter):
"""Help formatter for eq commands that works with both strip and bus commands.
Injects <index> after 'strip' or 'bus' and <band> after 'cell'."""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with proper <index> placement for both strip and bus commands."""
if usage:
modified_usage = re.sub(
r'(\S+\s+)(\w+)(\s+eq\s+)(COMMAND)', r'\1\2 <index>\3\4', str(usage)
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')
class CellHelpFormatter(BaseHelpFormatter):
"""Help formatter for cell commands that works with both strip and bus commands.
Injects <index> after 'strip' or 'bus' and <band> after 'cell'."""
def render_usage(self, console: Console, options: ConsoleOptions, usage) -> None:
"""Render the usage line with proper <index> and <band> placement."""
if usage:
modified_usage = re.sub(
r'(\S+\s+)(\w+)(\s+eq\s+cell\s+)(COMMAND)',
r'\1\2 <index>\3<band> \4',
str(usage),
)
console.print(f'[bold]Usage:[/bold] {modified_usage}')

View File

@@ -4,9 +4,9 @@ from cyclopts import App, Argument, Parameter
from . import comp, console, denoiser, eq, gate from . import comp, console, denoiser, eq, gate
from .context import Context from .context import Context
from .help import CustomHelpFormatter from .help import StripHelpFormatter
app = App(name='strip', help_formatter=CustomHelpFormatter()) app = App(name='strip', help_formatter=StripHelpFormatter())
app.command(eq.app.meta, name='eq') app.command(eq.app.meta, name='eq')
app.command(comp.app.meta, name='comp') app.command(comp.app.meta, name='comp')
app.command(gate.app.meta, name='gate') app.command(gate.app.meta, name='gate')

2
uv.lock generated
View File

@@ -124,7 +124,7 @@ wheels = [
[[package]] [[package]]
name = "vban-cli" name = "vban-cli"
version = "0.4.1" version = "0.4.2"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "cyclopts" }, { name = "cyclopts" },