v1.2.0
[1.2.0] - 2025-10-26
⚠️ BREAKING CHANGES
-
ValueTypes::Nonehas been REMOVED- Reason: Critical design flaw - impossible to distinguish between "flag defined" and "flag passed"
- Migration: Replace all
ValueTypes::NonewithValueTypes::OptionalSingle(Some(Value::Bool(false))) - How to check if flag was passed:
- When flag is not passed: value remains
Bool(false) - When flag is passed: value is updated to
Bool(true)
- When flag is not passed: value remains
- See Migration Guide in README for details
-
add_option_with_callback()signature changed- Added parameter:
stop_main_callback: bool - Existing calls must specify whether the callback should stop main execution
- Example:
.add_option_with_callback("help", "Help", "-h", "--help", ValueTypes::OptionalSingle(Some(Value::Bool(false))), true, callback)
- Added parameter:
Added
- Inheritable options feature - Allows parent commands to share options with subcommands
CommandOptionsParser::mark_inheritable(&mut self, flag: &str) -> Result<()>- Marks a single option as inheritableCommandOptionsParser::mark_inheritable_many<I, S>(&mut self, flags: I) -> Result<()>- Marks multiple options as inheritableCommandOptionsParser::inheritable_options_builder(&self) -> CommandOptionsParserBuilder- Creates a builder with only inheritable optionsFliCommand::with_parser(name, description, builder)- Creates commands with pre-configured option parsersFli::mark_inheritable(&mut self, flag: &str) -> Result<()>- Convenience method to mark root command options as inheritableFli::mark_inheritable_many<I, S>(&mut self, flags: I) -> Result<()>- Convenience method to mark multiple root options as inheritable
- Automatic option inheritance in subcommands
- Subcommands created via
subcommand()now automatically inherit options marked as inheritable from parent commands - Eliminates code duplication for common options (e.g., verbose, quiet, color flags)
- Each subcommand receives its own copy of inherited options
- Subcommands created via
- Preserved options callback control -
PreservedOption.stop_main_callbackfield- Controls whether a preserved option's callback should prevent the main command callback from executing
- When
true(e.g., --help, --version): executes the preserved callback and exits immediately - When
false(e.g., --debug): executes the preserved callback and then continues to the main callback - Enables options like
--debugthat configure state without halting execution
- Comprehensive test coverage - Added 30 new test cases covering:
- Single and multiple option inheritance (20 tests)
- Input parser command chain prediction (25 tests)
- ValueTypes::None design flaw demonstrations (4 tests)
- Nested subcommand inheritance
- Error handling for non-existent options
- Independent option copies for each subcommand
- Mixed short/long flag marking
Changed
- Enhanced
subcommand()method - Now automatically propagates inheritable options from parent to child commands- Uses
inheritable_options_builder()internally to clone marked options - Maintains backward compatibility with existing code
- Uses
- Simplified
Fli::command()method - Now usessubcommand()for automatic inheritance - Improved
add_debug_option()implementation - Now usesadd_option_with_callbackwithstop_main_callback: false- Allows --debug flag to configure debug mode and still run the main command
- Removes the manual argument checking that ran before the app starts
- Flag option handling - Flags now use
Bool(true/false)to properly track usage state- Parser sets flag value to
Bool(true)when encountered in arguments - Enables checking flag status via option parser, not just command chain
- Help display shows "flag" instead of "none" for flag-type options
- Parser sets flag value to
Fixed
- Critical bug:
ValueTypes::Nonecould not distinguish between defined and passed flags- Now using
Bool(false)(default) vsBool(true)(passed) provides clear state tracking - Applications can now reliably check if a flag was actually used
- Now using
- Parser state machine - Fixed unreachable pattern warning in value acceptance logic
Examples
use fli::Fli;
use fli::option_parser::ValueTypes;
// Parent command with common options
let mut app = Fli::new("myapp", "1.0.0", "My application");
app.add_option("verbose", "Enable verbose output", "-v", "--verbose", ValueTypes::OptionalSingle(Some(Value::Bool(false))));
app.add_option("quiet", "Suppress output", "-q", "--quiet", ValueTypes::OptionalSingle(Some(Value::Bool(false))));
// Mark options as inheritable using convenient Fli methods
app.mark_inheritable_many(&["-v", "-q"]).unwrap();
// All subcommands automatically inherit -v and -q
app.command("start", "Start the service").unwrap();
app.command("stop", "Stop the service").unwrap();
// Both subcommands now have -v/--verbose and -q/--quiet optionsAlternative using FliCommand directly:
use fli::command::FliCommand;
use fli::option_parser::ValueTypes;
let mut parent = FliCommand::new("parent", "Parent command");
parent.add_option("verbose", "Verbose", "-v", "--verbose", ValueTypes::OptionalSingle(Some(Value::Bool(false))));
parent.get_option_parser().mark_inheritable("-v").unwrap();
// Subcommand automatically inherits -v
let child = parent.subcommand("child", "Child command");