1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
|
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2025-2026 Benjamin Abendroth <braph93@gmx.de>
'''This module contains the configuration class.'''
import sys
from .type_utils import is_list_type
def _assert_is_bool(obj, func, param):
if isinstance(obj, bool):
return
raise AssertionError(f"Config.{func}: {param}: expected bool, got `{obj}`")
class Config:
'''Configuration settings for command line completion.'''
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-many-public-methods
def __init__(self):
self.function_prefix = '_$PROG'
self.debug = False
self.abbreviate_commands = False
self.abbreviate_options = False
self.repeatable_options = False
self.inherit_options = False
self.option_stacking = True
self.long_opt_arg_sep = 'both'
self.vim_modeline = True
self.include_files = []
self.comments = []
self.keep_comments = False
self.line_length = 80
self.bash_completions_version = (2,)
self.zsh_compdef = True
self.fish_fast = False
self.fish_inline_conditions = False
self.disabled_hidden = False
self.disabled_final = False
self.disabled_groups = False
self.disabled_repeatable = False
self.disabled_when = False
def set_function_prefix(self, prefix):
'''Sets the function prefix used for generated functions.
Args:
prefix (str):
The prefix to be used. May contain the `$PROG` placeholder.
Notes:
This defaults to `_$PROG`
'''
assert isinstance(prefix, str)
self.function_prefix = prefix
def set_debug(self, enable):
'''Sets debug mode.
Args:
enable (bool):
If True, additional code for debugging is generated.
Notes:
This feature defaults to `False`.
'''
_assert_is_bool(enable, "set_debug", "enable")
self.debug = enable
def set_abbreviate_commands(self, enable):
'''Sets whether commands can be abbreviated.
Args:
enable (bool):
If True, commands can be abbreviated; if False, they cannot.
Notes:
This feature defaults to `False`.
Implementation status for shells:
Bash:
- set_abbreviate_commands(True): works
- set_abbreviate_commands(False): works
Fish:
- set_abbreviate_commands(True): works
- set_abbreviate_commands(False): works
Zsh:
- set_abbreviate_commands(True): works
- set_abbreviate_commands(False): works
See Also:
cli.CommandLine(..., abbreviate_commands=BOOL, ...)
'''
_assert_is_bool(enable, "set_abbreviate_commands", "enable")
self.abbreviate_commands = enable
def set_abbreviate_options(self, enable):
'''Sets whether options can be abbreviated.
Args:
enable (bool):
If True, options can be abbreviated; if False, they cannot.
Notes:
This feature defaults to `False`.
Implementation status for shells:
Bash:
- set_abbreviate_options(True): works
- set_abbreviate_options(False): works
Fish:
- set_abbreviate_options(True): not implemented
- set_abbreviate_options(False): works
Zsh:
- set_abbreviate_options(True): not implemented
- set_abbreviate_options(False): works
See Also:
cli.CommandLine(..., abbreviate_options=BOOL, ...)
'''
_assert_is_bool(enable, "set_abbreviate_options", "enable")
self.abbreviate_options = enable
def set_repeatable_options(self, enable):
'''Sets whether options are suggested multiple times during completion.
Args:
enable (bool):
If True, options can appear multiple times during completion;
if False, options are suggested only once.
Notes:
This feature defaults to `False`.
Implementation status for shells:
Bash:
- set_repeatable_options(True): works
- set_repeatable_options(False): works
Fish:
- set_repeatable_options(True): works
- set_repeatable_options(False): works
Zsh:
- set_repeatable_options(True): works
- set_repeatable_options(False): works
See Also:
cli.CommandLine.add_option(..., repeatable=BOOL, ...)
'''
_assert_is_bool(enable, "set_repeatable_options", "enable")
self.repeatable_options = enable
def set_inherit_options(self, enable):
'''Sets whether parent options are visible to subcommands.
Args:
enable (bool):
If True, parent options are visible to subcommands.
If False, they are not.
Notes:
This feature defaults to `False`.
Implementation status for shells:
Bash:
- set_inherit_options(True): works
- set_inherit_options(False): works
Fish:
- set_inherit_options(True): works
- set_inherit_options(False): works
Zsh:
- set_inherit_options(True): works
- set_inherit_options(False): works
See Also:
cli.CommandLine(..., inherit_options=BOOL, ...)
'''
_assert_is_bool(enable, "set_inherit_options", "enable")
self.inherit_options = enable
def set_option_stacking(self, enable):
'''Sets wether short option stacking is allowed.
Args:
enable (bool):
If True, option stacking is allowed.
If False, it is not.
Notes:
This feature defaults to `True`.
Implementation status for shells:
Bash:
- set_option_stacking(True): works
- set_option_stacking(False): not implemented
Fish:
- set_option_stacking(True): works
- set_option_stacking(False): works
Zsh:
- set_option_stacking(True): works
- set_option_stacking(False): works
'''
_assert_is_bool(enable, "set_option_stacking", "enable")
self.option_stacking = enable
def set_long_option_argument_separator(self, separator):
'''Sets which separators are used for delimiting a long option from
its argument.
Args:
separator (string):
If `space`, only the form `--option argument` is allowed.
If `equals`, only the form `--option=argument` is allowed.
If `both`, both forms are allowed.
Notes:
This feature defaults to `both`.
Implementation status for shells:
Bash:
- set_long_option_argument_separator('space'): works
- set_long_option_argument_separator('equals'): works
- set_long_option_argument_separator('both'): works
Fish:
- set_long_option_argument_separator('space'): not implemented
- set_long_option_argument_separator('equals'): not implemented
- set_long_option_argument_separator('both'): works
Zsh:
- set_long_option_argument_separator('space'): works
- set_long_option_argument_separator('equals'): works
- set_long_option_argument_separator('both'): works
'''
if separator not in ('space', 'equals', 'both'):
raise AssertionError('Config.set_long_option_argument_separator: '
'separator: Invalid value: '
'expected: `space`, `equals` or `both`')
self.long_opt_arg_sep = separator
def set_vim_modeline(self, enable):
'''Sets whether a vim modeline comment shall be appended to the code.
The modeline comment looks like this:
# vim: ft=zsh ts=2 sts=2 sw=2 et
Args:
enable (bool):
If True, add a vim modline comment;
if False, don't add a modline comment.
Notes:
This feature defaults to `True`.
'''
_assert_is_bool(enable, "set_vim_modeline", "enable")
self.vim_modeline = enable
def set_bash_completions_version(self, version):
'''Sets the version of bash-completions.
Args:
version (tuple):
A tuple in form like (2,) or (2, 12).
Notes:
This defaults to (2,).
'''
assert isinstance(version, tuple)
self.bash_completions_version = version
def set_zsh_compdef(self, enable):
'''Sets whether a `#compdef` comment is written at the top of the
generated zsh script.
The `#compdef` directive is used by Zsh to automatically associate the
generated completion file with a command, enabling autoload
functionality.
If you plan to load the Zsh completion file manually by sourcing it,
omitting this line may be necessary.
Args:
enable (bool):
If true, add a `#compdef` line on top of the file;
If false, don't add a `#compdef` line.
Notes:
This feature defaults to `True`
'''
_assert_is_bool(enable, "set_zsh_compdef", "enable")
self.zsh_compdef = enable
def set_keep_comments(self, enable):
'''Sets whether comments shall be included in the generated code.
Args:
enable (bool):
If True, comments are included.
if False, don't include comments.
Notes:
This feature defaults to `False`.
'''
_assert_is_bool(enable, "set_keep_comments", "enable")
self.keep_comments = enable
def set_line_length(self, length):
'''Sets the maximum line length of the generated code.
Args:
length (int):
The maximum line length. If zero or negative, maximum line
length is selected.
Notes:
This defaults to `80`.
'''
assert isinstance(length, int)
self.line_length = length if length > 0 else sys.maxsize
def set_fish_fast(self, enable):
'''Use faster conditions at the cost of correctness.'''
_assert_is_bool(enable, "set_fish_fast", "enable")
self.fish_fast = enable
def set_fish_inline_conditions(self, enable):
'''Don't store conditions in an extra variable.'''
_assert_is_bool(enable, "set_fish_inline_conditions", "enable")
self.fish_inline_conditions = enable
def include_file(self, file):
'''Add a file which should be included to the generated code.'''
assert isinstance(file, str), \
f"Config.include_file: file: expected str, got `{file}`"
self.include_files.append(file)
def include_many_files(self, files):
'''Add files which should be included to the generated code.'''
assert is_list_type(files)
self.include_files.extend(files)
def add_comments(self, comments):
'''Add comments to the generated output.'''
assert is_list_type(comments)
self.comments.extend(comments)
def disable_hidden(self, disable):
'''Disable hidden options.
This disables hidden options completely.
'''
_assert_is_bool(disable, "disable_hidden", "disable")
self.disabled_hidden = disable
def disable_final(self, disable):
'''Disable final options.
This disables final options completely.
'''
_assert_is_bool(disable, "disable_final", "disable")
self.disabled_final = disable
def disable_groups(self, disable):
'''Disable option grouping.
This disables the mutually exclusive feature for options completely.
'''
_assert_is_bool(disable, "disable_groups", "disable")
self.disabled_groups = disable
def disable_repeatable(self, disable):
'''Disable repeatable options.
This disables repeatable options completely.
Despite its name, this function actually does the opposite:
Instead of making all options non-repeatable, it makes all options
repeatable.
'''
_assert_is_bool(disable, "disable_repeatable", "disable")
self.disabled_repeatable = disable
def disable_when(self, disable):
'''Disable when feature.
This disables conditional options and positionals completely.
'''
_assert_is_bool(disable, "disable_when", "disable")
self.disabled_when = disable
|