forked from genewildish/Mainline
fix(pipeline): Use config display value in auto-injection
- Change line 477 in controller.py to use self.config.display or "terminal" - Previously hardcoded "terminal" ignored config and CLI arguments - Now auto-injection respects the validated display configuration fix(app): Add warnings for auto-selected display - Add warning in pipeline_runner.py when --display not specified - Add warning in main.py when --pipeline-display not specified - Both warnings suggest using null display for headless mode feat(completion): Add bash/zsh/fish completion scripts - completion/mainline-completion.bash - bash completion - completion/mainline-completion.zsh - zsh completion - completion/mainline-completion.fish - fish completion - Provides completions for --display, --pipeline-source, --pipeline-effects, --pipeline-camera, --preset, --theme, --viewport, and other flags
This commit is contained in:
99
completion/mainline-completion.bash
Normal file
99
completion/mainline-completion.bash
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Mainline bash completion script
|
||||||
|
#
|
||||||
|
# To install:
|
||||||
|
# source /path/to/completion/mainline-completion.bash
|
||||||
|
#
|
||||||
|
# Or add to ~/.bashrc:
|
||||||
|
# source /path/to/completion/mainline-completion.bash
|
||||||
|
|
||||||
|
_mainline_completion() {
|
||||||
|
local cur prev words cword
|
||||||
|
_init_completion || return
|
||||||
|
|
||||||
|
# Get current word and previous word
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
|
||||||
|
# Completion options based on previous word
|
||||||
|
case "${prev}" in
|
||||||
|
--display)
|
||||||
|
# Display backends
|
||||||
|
COMPREPLY=($(compgen -W "terminal null replay websocket pygame moderngl" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--pipeline-source)
|
||||||
|
# Available sources
|
||||||
|
COMPREPLY=($(compgen -W "headlines poetry empty fixture pipeline-inspect" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--pipeline-effects)
|
||||||
|
# Available effects (comma-separated)
|
||||||
|
local effects="afterimage border crop fade firehose glitch hud motionblur noise tint"
|
||||||
|
COMPREPLY=($(compgen -W "${effects}" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--pipeline-camera)
|
||||||
|
# Camera modes
|
||||||
|
COMPREPLY=($(compgen -W "feed scroll horizontal omni floating bounce radial" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--pipeline-border)
|
||||||
|
# Border modes
|
||||||
|
COMPREPLY=($(compgen -W "off simple ui" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--pipeline-display)
|
||||||
|
# Display backends (same as --display)
|
||||||
|
COMPREPLY=($(compgen -W "terminal null replay websocket pygame moderngl" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--theme)
|
||||||
|
# Theme colors
|
||||||
|
COMPREPLY=($(compgen -W "green orange purple blue red" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--viewport)
|
||||||
|
# Viewport size suggestions
|
||||||
|
COMPREPLY=($(compgen -W "80x24 100x30 120x40 60x20" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
|
||||||
|
--preset)
|
||||||
|
# Presets (would need to query available presets)
|
||||||
|
COMPREPLY=($(compgen -W "demo demo-base demo-pygame demo-camera-showcase poetry headlines empty test-basic test-border test-scroll-camera" -- "${cur}"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Flag completion (start with --)
|
||||||
|
if [[ "${cur}" == -* ]]; then
|
||||||
|
COMPREPLY=($(compgen -W "
|
||||||
|
--display
|
||||||
|
--pipeline-source
|
||||||
|
--pipeline-effects
|
||||||
|
--pipeline-camera
|
||||||
|
--pipeline-display
|
||||||
|
--pipeline-ui
|
||||||
|
--pipeline-border
|
||||||
|
--viewport
|
||||||
|
--preset
|
||||||
|
--theme
|
||||||
|
--websocket
|
||||||
|
--websocket-port
|
||||||
|
--allow-unsafe
|
||||||
|
--help
|
||||||
|
" -- "${cur}"))
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _mainline_completion mainline.py
|
||||||
|
complete -F _mainline_completion python\ -m\ engine.app
|
||||||
|
complete -F _mainline_completion python\ -m\ mainline
|
||||||
81
completion/mainline-completion.fish
Normal file
81
completion/mainline-completion.fish
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Fish completion script for Mainline
|
||||||
|
#
|
||||||
|
# To install:
|
||||||
|
# source /path/to/completion/mainline-completion.fish
|
||||||
|
#
|
||||||
|
# Or copy to ~/.config/fish/completions/mainline.fish
|
||||||
|
|
||||||
|
# Define display backends
|
||||||
|
set -l display_backends terminal null replay websocket pygame moderngl
|
||||||
|
|
||||||
|
# Define sources
|
||||||
|
set -l sources headlines poetry empty fixture pipeline-inspect
|
||||||
|
|
||||||
|
# Define effects
|
||||||
|
set -l effects afterimage border crop fade firehose glitch hud motionblur noise tint
|
||||||
|
|
||||||
|
# Define camera modes
|
||||||
|
set -l cameras feed scroll horizontal omni floating bounce radial
|
||||||
|
|
||||||
|
# Define border modes
|
||||||
|
set -l borders off simple ui
|
||||||
|
|
||||||
|
# Define themes
|
||||||
|
set -l themes green orange purple blue red
|
||||||
|
|
||||||
|
# Define presets
|
||||||
|
set -l presets demo demo-base demo-pygame demo-camera-showcase poetry headlines empty test-basic test-border test-scroll-camera test-figment test-message-overlay
|
||||||
|
|
||||||
|
# Main completion function
|
||||||
|
function __mainline_complete
|
||||||
|
set -l cmd (commandline -po)
|
||||||
|
set -l token (commandline -t)
|
||||||
|
|
||||||
|
# Complete display backends
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --display' -a "$display_backends" -d 'Display backend'
|
||||||
|
|
||||||
|
# Complete sources
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --pipeline-source' -a "$sources" -d 'Data source'
|
||||||
|
|
||||||
|
# Complete effects
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --pipeline-effects' -a "$effects" -d 'Effect plugin'
|
||||||
|
|
||||||
|
# Complete camera modes
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --pipeline-camera' -a "$cameras" -d 'Camera mode'
|
||||||
|
|
||||||
|
# Complete display backends (pipeline)
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --pipeline-display' -a "$display_backends" -d 'Display backend'
|
||||||
|
|
||||||
|
# Complete border modes
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --pipeline-border' -a "$borders" -d 'Border mode'
|
||||||
|
|
||||||
|
# Complete themes
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --theme' -a "$themes" -d 'Color theme'
|
||||||
|
|
||||||
|
# Complete presets
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --preset' -a "$presets" -d 'Preset name'
|
||||||
|
|
||||||
|
# Complete viewport sizes
|
||||||
|
complete -c mainline.py -n '__fish_seen_argument --viewport' -a '80x24 100x30 120x40 60x20' -d 'Viewport size (WxH)'
|
||||||
|
|
||||||
|
# Complete flag options
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --display' -l display -d 'Display backend' -a "$display_backends"
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --preset' -l preset -d 'Preset to use' -a "$presets"
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --viewport' -l viewport -d 'Viewport size (WxH)' -a '80x24 100x30 120x40 60x20'
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --theme' -l theme -d 'Color theme' -a "$themes"
|
||||||
|
complete -c mainline.py -l websocket -d 'Enable WebSocket server'
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --websocket-port' -l websocket-port -d 'WebSocket port' -a '8765'
|
||||||
|
complete -c mainline.py -l allow-unsafe -d 'Allow unsafe pipeline configuration'
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --help' -l help -d 'Show help'
|
||||||
|
|
||||||
|
# Pipeline-specific flags
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --pipeline-source' -l pipeline-source -d 'Data source' -a "$sources"
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --pipeline-effects' -l pipeline-effects -d 'Effect plugins (comma-separated)' -a "$effects"
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --pipeline-camera' -l pipeline-camera -d 'Camera mode' -a "$cameras"
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --pipeline-display' -l pipeline-display -d 'Display backend' -a "$display_backends"
|
||||||
|
complete -c mainline.py -l pipeline-ui -d 'Enable UI panel'
|
||||||
|
complete -c mainline.py -n 'not __fish_seen_argument --pipeline-border' -l pipeline-border -d 'Border mode' -a "$borders"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Register the completion function
|
||||||
|
__mainline_complete
|
||||||
48
completion/mainline-completion.zsh
Normal file
48
completion/mainline-completion.zsh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#compdef mainline.py
|
||||||
|
|
||||||
|
# Mainline zsh completion script
|
||||||
|
#
|
||||||
|
# To install:
|
||||||
|
# source /path/to/completion/mainline-completion.zsh
|
||||||
|
#
|
||||||
|
# Or add to ~/.zshrc:
|
||||||
|
# source /path/to/completion/mainline-completion.zsh
|
||||||
|
|
||||||
|
# Define completion function
|
||||||
|
_mainline() {
|
||||||
|
local -a commands
|
||||||
|
local curcontext="$curcontext" state line
|
||||||
|
typeset -A opt_args
|
||||||
|
|
||||||
|
_arguments -C \
|
||||||
|
'(-h --help)'{-h,--help}'[Show help]' \
|
||||||
|
'--display=[Display backend]:backend:(terminal null replay websocket pygame moderngl)' \
|
||||||
|
'--preset=[Preset to use]:preset:(demo demo-base demo-pygame demo-camera-showcase poetry headlines empty test-basic test-border test-scroll-camera test-figment test-message-overlay)' \
|
||||||
|
'--viewport=[Viewport size]:size:(80x24 100x30 120x40 60x20)' \
|
||||||
|
'--theme=[Color theme]:theme:(green orange purple blue red)' \
|
||||||
|
'--websocket[Enable WebSocket server]' \
|
||||||
|
'--websocket-port=[WebSocket port]:port:' \
|
||||||
|
'--allow-unsafe[Allow unsafe pipeline configuration]' \
|
||||||
|
'(-)*: :{_files}' \
|
||||||
|
&& ret=0
|
||||||
|
|
||||||
|
# Handle --pipeline-* arguments
|
||||||
|
if [[ -n ${words[*]} ]]; then
|
||||||
|
_arguments -C \
|
||||||
|
'--pipeline-source=[Data source]:source:(headlines poetry empty fixture pipeline-inspect)' \
|
||||||
|
'--pipeline-effects=[Effect plugins]:effects:(afterimage border crop fade firehose glitch hud motionblur noise tint)' \
|
||||||
|
'--pipeline-camera=[Camera mode]:camera:(feed scroll horizontal omni floating bounce radial)' \
|
||||||
|
'--pipeline-display=[Display backend]:backend:(terminal null replay websocket pygame moderngl)' \
|
||||||
|
'--pipeline-ui[Enable UI panel]' \
|
||||||
|
'--pipeline-border=[Border mode]:mode:(off simple ui)' \
|
||||||
|
'--viewport=[Viewport size]:size:(80x24 100x30 120x40 60x20)' \
|
||||||
|
&& ret=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
# Register completion function
|
||||||
|
compdef _mainline mainline.py
|
||||||
|
compdef _mainline "python -m engine.app"
|
||||||
|
compdef _mainline "python -m mainline"
|
||||||
@@ -254,6 +254,16 @@ def run_pipeline_mode_direct():
|
|||||||
|
|
||||||
# Create display using validated display name
|
# Create display using validated display name
|
||||||
display_name = result.config.display or "terminal" # Default to terminal if empty
|
display_name = result.config.display or "terminal" # Default to terminal if empty
|
||||||
|
|
||||||
|
# Warn if display was auto-selected (not explicitly specified)
|
||||||
|
if not display_name:
|
||||||
|
print(
|
||||||
|
" \033[38;5;226mWarning: No --pipeline-display specified, using default: terminal\033[0m"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
" \033[38;5;245mTip: Use --pipeline-display null for headless mode (useful for testing)\033[0m"
|
||||||
|
)
|
||||||
|
|
||||||
display = DisplayRegistry.create(display_name)
|
display = DisplayRegistry.create(display_name)
|
||||||
if not display:
|
if not display:
|
||||||
print(f" \033[38;5;196mFailed to create display: {display_name}\033[0m")
|
print(f" \033[38;5;196mFailed to create display: {display_name}\033[0m")
|
||||||
|
|||||||
@@ -189,10 +189,19 @@ def run_pipeline_mode(preset_name: str = "demo"):
|
|||||||
# CLI --display flag takes priority over preset
|
# CLI --display flag takes priority over preset
|
||||||
# Check if --display was explicitly provided
|
# Check if --display was explicitly provided
|
||||||
display_name = preset.display
|
display_name = preset.display
|
||||||
if "--display" in sys.argv:
|
display_explicitly_specified = "--display" in sys.argv
|
||||||
|
if display_explicitly_specified:
|
||||||
idx = sys.argv.index("--display")
|
idx = sys.argv.index("--display")
|
||||||
if idx + 1 < len(sys.argv):
|
if idx + 1 < len(sys.argv):
|
||||||
display_name = sys.argv[idx + 1]
|
display_name = sys.argv[idx + 1]
|
||||||
|
else:
|
||||||
|
# Warn user that display is falling back to preset default
|
||||||
|
print(
|
||||||
|
f" \033[38;5;226mWarning: No --display specified, using preset default: {display_name}\033[0m"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
" \033[38;5;245mTip: Use --display null for headless mode (useful for testing/capture)\033[0m"
|
||||||
|
)
|
||||||
|
|
||||||
display = DisplayRegistry.create(display_name)
|
display = DisplayRegistry.create(display_name)
|
||||||
if not display and not display_name.startswith("multi"):
|
if not display and not display_name.startswith("multi"):
|
||||||
|
|||||||
@@ -474,9 +474,10 @@ class Pipeline:
|
|||||||
not self._find_stage_with_capability("display.output")
|
not self._find_stage_with_capability("display.output")
|
||||||
and "display" not in self._stages
|
and "display" not in self._stages
|
||||||
):
|
):
|
||||||
display = DisplayRegistry.create("terminal")
|
display_name = self.config.display or "terminal"
|
||||||
|
display = DisplayRegistry.create(display_name)
|
||||||
if display:
|
if display:
|
||||||
self.add_stage("display", DisplayStage(display, name="terminal"))
|
self.add_stage("display", DisplayStage(display, name=display_name))
|
||||||
injected.append("display")
|
injected.append("display")
|
||||||
|
|
||||||
# Rebuild pipeline if stages were injected
|
# Rebuild pipeline if stages were injected
|
||||||
|
|||||||
Reference in New Issue
Block a user