The name restrictions for options and subcommands are now much looser, allowing a wider variety of characters than before, even spaces can be used (use quotes to include a space in most shells). The default configuration parser was improved, allowing your configuration to sit in a larger file. And option callbacks have a few new settings, allowing them to be run even if the option is not passed, or every time the option is parsed.
- Option/subcommand name restrictions have been relaxed. Most characters are now allowed. #627
- The config parser can accept streams, specify a specific section, and inline comment characters are supported #630
force_callback
&trigger_on_parse
added, allowing a callback to always run on parse even if not present or every time the option is parsed #631- Bugfix(cmake): Only add
CONFIGURE_DEPENDS
if CLI11 is the main project #633 - Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent path #635
- Bugfix: The single header file generation was missing the include guard. #620
- A collision with
min
/max
macros on Windows has been fixed. #642 - Tests pass with Boost again #646
- Running the pre-commit hooks in development no longer requires docker for clang-format #647
- Use
main
for the main branch of the repository #657 - Bugfix(cmake): Enforce at least C++11 when using CMake target #656
- Build: Don't run doxygen and CTest includes if a submodule #656
- Build: Avoid a warning on CMake 3.22 #656
- Build: Support compiling the tests with an external copy of Catch2 #653
- Change the way the default value is displayed in the included help text generation from
=XXXXX
to[XXXXX]
to clean up some situations in which the text looked awkward and unclear #666 - Fix a bug where a subcommand callback could be executed multiple times if it was a member of an option group #666
- Fix an issue where the detection of RTTI being disabled on certain visual studio platforms did not disable the use of dynamic cast calls #666
- Add additional tests concerning the use of aliases for option groups in config files #666
- Resolve strict-overflow warning on some GCC compilers #666
This version focuses on cleaning up deprecated functionality, and some minor default changes. The config processing is TOML compliant now. Atomics and complex numbers are directly supported, along with other container improvements. A new version flag option has finally been added. Subcommands are significantly improved with new features and bugfixes for corner cases. This release contains a lot of backend cleanup, including a complete overhaul of the testing system and single file generation system.
- Built-in config format is TOML compliant now #435
- More powerful containers, support for
%%
separator #423 - Support atomic types #520 and complex types natively #423
- Add a type validator
CLI::TypeValidator<TYPE>
#526 - Add a version flag easily #452, with help message #601
- Support
->silent()
on subcommands. #529 - Add alias section to help for subcommands #545
- Allow quotes to specify a program name #605
- Backend: redesigned MakeSingleFiles to have a higher level of manual control, to support future features. #546
- Backend: moved testing from GTest to Catch2 #574
- Bugfix: avoid duplicated and missed calls to the final callback #584
- Bugfix: support embedded newlines in more places #592
- Bugfix: avoid listing helpall as a required flag #530
- Bugfix: avoid a clash with WINDOWS define #563
- Bugfix: the help flag didn't get processed when a config file was required #606
- Bugfix: fix description of non-configurable subcommands in config #604
- Build: support pkg-config #523
- Removed deprecated set commands, use validators instead. #565
- The final "defaulted" bool has been removed, use
->capture_default_str()
instead. Useapp.option_defaults()->always_capture_default()
to set this for all future options. #597- Use
add_option
on a complex number instead ofadd_complex
, which has been removed.
Config file handling was revamped to fix common issues, and now supports reading TOML.
Adding options is significantly more powerful with support for things like
std::tuple
and std::array
, including with transforms. Several new
configuration options were added to facilitate a wider variety of apps. GCC
4.7 is no longer supported.
- Config files refactored, supports TOML (may become default output in 2.0) #362
- Added two template parameter form of
add_option
, allowingstd::optional
to be supported without a special import #285 string_view
now supported in reasonable places #300, #285immediate_callback
,final_callback
, andparse_complete_callback
added to support controlling the App callback order #292, #313- Multiple positional arguments maintain order if
positionals_at_end
is set. #306 - Pair/tuple/array now supported, and validators indexed to specific components in the objects #307, #310
- Footer callbacks supported #309
- Subcommands now support needs (including nameless subcommands) #317
- More flexible type size, more useful
add_complex
#325, #370 - Added new validators
CLI::NonNegativeNumber
andCLI::PositiveNumber
#342 - Transform now supports arrays #349
- Option groups can be hidden #356
- Add
CLI::deprecate_option
andCLI::retire_option
functions #358 - More flexible and safer Option
default_val
#387 - Backend: Cleaner type traits #286
- Backend: File checking updates #341
- Backend: Using pre-commit to format, checked in GitHub Actions #336
- Backend: Clang-tidy checked again, CMake option now
CL11_CLANG_TIDY
#390 - Backend: Warning cleanup, more checks from klocwork #350, Effective C++ #354, clang-tidy #360, CUDA NVCC #365, cross compile #373, sign conversion #382, and cpplint #400
- Docs: CLI11 Tutorial now hosted in the same repository #304, #318, #374
- Bugfix: Fixed undefined behavior in
checked_multiply
#290 - Bugfix:
->check()
was adding the name to the wrong validator #320 - Bugfix: Resetting config option works properly #301
- Bugfix: Hidden flags were showing up in error printout #333
- Bugfix: Enum conversion no longer broken if stream operator added #348
- Build: The meson build system supported #299
- Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is now required. #160
- Build: Restructured significant portions of CMake build system #394
- Some deprecated methods dropped
add_set*
should be replaced with->check
/->transform
andCLI::IsMember
since 1.8get_defaultval
was replaced byget_default_str
in 1.8- The true/false 4th argument to
add_option
is expected to be removed in 2.0, use->capture_default_str()
since 1.8
This is a patch version that backports fixes from the development of 2.0.
- Support relative inclusion #475
- Fix cases where spaces in paths could break CMake support #471
- Fix an issue with string conversion #421
- Cross-compiling improvement for Conan.io #430
- Fix option group default propagation #450
- Fix for C++20 #459
- Support compiling with RTTI off #461
Set handling has been completely replaced by a new backend that works as a Validator or Transformer. This provides a single interface instead of the 16 different functions in App. It also allows ordered collections to be used, custom functions for filtering, and better help and error messages. You can also use a collection of pairs (like std::map
) to transform the match into an output. Also new are inverted flags, which can cancel or reduce the count of flags, and can also support general flag types. A new add_option_fn
lets you more easily program CLI11 options with the types you choose. Vector options now support a custom separator. Apps can now be composed with unnamed subcommand support. The final bool "defaults" flag when creating options has been replaced by ->capture_default_str()
(ending an old limitation in construction made this possible); the old method is still available but may be removed in future versions.
- Replaced default help capture:
.add_option("name", value, "", True)
becomes.add_option("name", value)->capture_default_str()
#242 - Added
.always_capture_default()
#242 - New
CLI::IsMember
validator replaces set validation #222 IsMember
also supports container of pairs, transform allows modification of result #228- Added new Transformers,
CLI::AsNumberWithUnit
andCLI::AsSizeValue
#253 - Much more powerful flags with different values #211, general types #235
add_option
now supports bool due to unified bool handling #211- Support for composable unnamed subcommands #216
- Reparsing is better supported with
.remaining_for_passthrough()
#265 - Custom vector separator using
->delimiter(char)
#209, #221, #240 - Validators added for IP4 addresses and positive numbers #210 and numbers #262
- Minimum required Boost for optional Optionals has been corrected to 1.61 #226
- Positionals can stop options from being parsed with
app.positionals_at_end()
#223 - Added
validate_positionals
#262 - Positional parsing is much more powerful #251, duplicates supported #247
- Validators can be negated with
!
#230, and now handle tname functions #228 - Better enum support and streaming helper #233 and #228
- Cleanup for shadow warnings #232
- Better alignment on multiline descriptions #269
- Better support for aarch64 #266
- Respect
BUILD_TESTING
only if CLI11 is the main project; otherwise,CLI11_TESTING
must be used #277 - Drop auto-detection of experimental optional and boost::optional; must be enabled explicitly (too fragile) #277 #279
.add_option(..., true)
should be replaced by.add_option(...)->capture_default_str()
orapp.option_defaults()->always_capture_default()
can be usedapp.add_set("--name", value, {"choice1", "choice2"})
should becomeapp.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))
- The
_ignore_case
version of this can be replaced by addingCLI::ignore_case
to the argument list inIsMember
- The
_ignore_underscore
version of this can be replaced by addingCLI::ignore_underscore
to the argument list inIsMember
- The
_ignore_case_underscore
version of this can be replaced by adding both functions listed above to the argument list inIsMember
- If you want an exact match to the original choice after one of the modifier functions matches, use
->transform
instead of->check
- The
_mutable
versions of this can be replaced by passing a pointer or shared pointer intoIsMember
- An error with sets now produces a
ValidationError
instead of aConversionError
The parsing procedure now maps much more sensibly to complex, nested subcommand structures. Each phase of the parsing happens on all subcommands before moving on with the next phase of the parse. This allows several features, like required environment variables, to work properly even through subcommand boundaries.
Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names. Adding a set that you plan to change later must now be done with add_mutable_set
.
- Support Windows style options with
->allow_windows_style_options
. #187 On by default on Windows. #190 - Added
parse(string)
to split up and parse a command-line style string directly. #186 - Added
ignore_underscore
and related functions, to ignore underscores when matching names. #185 - The default INI Config will now add quotes to strings with spaces #195
- The default message now will mention the help-all flag also if present #197
- Added
->description
to set Option descriptions #199 - Mutating sets (introduced in Version 1.6) now have a clear add method,
add_mutable_set*
, since the set reference should not expire #200 - Subcommands now track how many times they were parsed in a parsing process.
count()
with no arguments will return the number of times a subcommand was encountered. #178 - Parsing is now done in phases:
shortcurcuits
,ini
,env
,callbacks
, andrequirements
; all subcommands complete a phase before moving on. #178 - Calling parse multiple times is now officially supported without
clear
(automatic). #178 - Dropped the mostly undocumented
short_circuit
property, as help flag parsing is a bit more complex, and the default callback behavior of options now works properly. #179 - Use the standard
BUILD_TESTING
overCLI11_TESTING
if defined #183 - Cleanup warnings #191
- Remove deprecated names:
set_footer
,set_name
,set_callback
, andset_type_name
. Use without theset_
instead. #192
->short_circuit()
is no longer needed, just remove it if you were using it - raising an exception will happen in the proper place now without it.->add_set*
becomes->add_mutable_set*
if you were using the editable set featurefooter
,name
,callback
, andtype_name
must be used instead of theset_*
versions (deprecated previously).
This version provides a quick patch for a (correct) warning from GCC 8 for the windows options code.
- Fix for Windows style option parsing #201
- Improve
add_subcommand
when throwing an exception #204 - Better metadata for Conan package #202
Added a new formatting system #109. You can now set the formatter on Apps. This has also simplified the internals of Apps and Options a bit by separating most formatting code.
- Added
CLI::Formatter
andformatter
slot for apps, inherited. FormatterBase
is the minimum required.FormatterLambda
provides for the easy addition of an arbitrary function.- Added
help_all
support (not added by default).
Changes to the help system (most normal users will not notice this):
- Renamed
single_name
toget_name(false, false)
(the default). - The old
get_name()
is nowget_name(false, true)
. - The old
get_pname()
is nowget_name(true, false)
. - Removed
help_*
functions. - Protected function
_has_help_positional
removed. format_help
can now be chained.- Added getters for the missing parts of options (help no longer uses any private parts).
- Help flags now use new
short_circuit
property to simplify parsing. #121
New for Config file reading and writing #121:
- Overridable, bidirectional Config.
- ConfigINI provided and used by default.
- Renamed ini to config in many places.
- Has
config_formatter()
andget_config_formatter()
. - Dropped prefix argument from
config_to_str
. - Added
ConfigItem
. - Added an example of a custom config format using nlohmann/json. #138
Validators are now much more powerful #118, all built in validators upgraded to the new form:
- A subclass of
CLI::Validator
is now also accepted. - They now can set the type name to things like
PATH
andINT in [1-4]
. - Validators can be combined with
&
and|
. - Old form simple validators are still accepted.
Other changes:
- Fixing
parse(args)
'sargs
setting and ordering after parse. #141 - Replaced
set_custom_option
withtype_name
andtype_size
instead ofset_custom_option
. Methods returnthis
. #136 - Dropped
set_
on Option'stype_name
,default_str
, anddefault_val
. #136 - Removed
set_
from App'sfailure_message
,footer
,callback
, andname
. #136 - Fixed support
N<-1
fortype_size
. #140 - Added
->each()
to make adding custom callbacks easier. #126 - Allow empty options
add_option("-n",{})
to be edited later witheach
#142 - Added filter argument to
get_subcommands
,get_options
; use empty filter{}
to avoid filtering. - Added
get_groups()
to get groups. - Better support for manual options with
get_option
,set_results
, andempty
. #119 lname
andsname
have getters, addedconst get_parent
. #120- Using
add_set
will now capture L-values for sets, allowing further modification. #113 - Dropped duplicate way to run
get_type_name
(get_typeval
). - Removed
requires
in favor ofneeds
(deprecated in last version). #112 - Const added to argv. #126
Backend and testing changes:
- Internally,
type_name
is now a lambda function; for sets, this reads the set live. #116 - Cleaner tests without
app.reset()
(andreset
is nowclear
). #141 - Better CMake policy handling. #110
- Includes are properly sorted. #120
- Testing (only) now uses submodules. #111
This version provides a few fixes for special cases, such as mixing with Windows.h
and better defaults
for systems like Hunter. The one new feature is the ability to produce "branded" single file output for
providing custom namespaces or custom macro names.
- Added fix and test for including Windows.h #145
- No longer build single file by default if main project, supports systems stuck on Python 2.6 #149, #151
- Branding support for single file output #150
This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes.
- Fixed help-all formatting #163
- Printing help-all on nested command now fixed (App)
- Missing space after help-all restored (Default formatter)
- More detail printed on help all (Default formatter)
- Help-all subcommands get indented with inner blank lines removed (Default formatter)
detail::find_and_replace
added to utilities
- Fixed CMake install as subproject with
CLI11_INSTALL
flag. #156 - Fixed warning about local variable hiding class member with MSVC #157
- Fixed compile error with default settings on Clang 7 and libc++ #158
- Fixed special case of
--help
on subcommands (general fix planned for 1.7) #168 - Removing an option with links #179
This version introduced support for optionals, along with clarification and examples of custom conversion overloads. Enums now have been dropped from the automatic conversion system, allowing explicit protection for out-of-range ints (or a completely custom conversion). This version has some internal cleanup and improved support for the newest compilers. Several bugs were fixed, as well.
Note: This is the final release with requires
, please switch to needs
.
- Fix unlimited short options eating two values before checking for positionals when no space present #90
- Symmetric exclude text when excluding options, exclude can be called multiple times #64
- Support for
std::optional
,std::experimental::optional
, andboost::optional
added if__has_include
is supported #95 - All macros/CMake variables now start with
CLI11_
instead of justCLI_
#95 - The internal stream was not being cleared before use in some cases. Fixed. #95
- Using an enum now requires explicit conversion overload #97
- The separator
--
now is removed when it ends unlimited arguments #100
Other, non-user facing changes:
- Added
Macros.hpp
with better C++ mode discovery #95 - Deprecated macros added for all platforms
- C++17 is now tested on supported platforms #95
- Informational printout now added to CTest #95
- Better single file generation #95
- Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next version of GTest)
- Types now have a specific size, separate from the expected number - cleaner and more powerful internally #92
- Examples now run as part of testing #99
This patch release adds better access to the App programmatically, to assist with writing custom converters to other formats. It also improves the help output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way unlimited options and positionals interact.
- Make mixing unlimited positionals and options more intuitive #102
- Add missing getters
get_options
andget_description
to App #105 - The app name now can be set, and will override the auto name if present #105
- Add
(REQUIRED)
for required options #104 - Print simple name for Needs/Excludes #104
- Use Needs instead of Requires in help print #104
- Groups now are listed in the original definition order #106
This is a quick patch release that makes LICENSE part of the single header file, making it easier to include. Minor cleanup from codacy. No significant code changes from 1.5.1.
This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
This version fixes the optional search in the single file version; some macros were not yet defined when it did the search. You can define the CLI11_*_OPTIONAL
macros to 0 if needed to eliminate the search.
This version adds lots of smaller fixes and additions after the refactor in version 1.3. More ways to download and use CLI11 in CMake have been added. INI files have improved support.
- Lexical cast is now more strict than before #68 and fails on overflow #84
- Added
get_parent()
to access the parent from a subcommand - Added
ExistingPath
validator #73 app.allow_ini_extras()
added to allow extras in INI files #70- Multiline INI comments now supported
- Descriptions can now be written with
config_to_str
#66 - Double printing of error message fixed #77
- Renamed
requires
toneeds
to avoid C++20 keyword #75, #82 - MakeSingleHeader now works if outside of git #78
- Adding install support for CMake #79, improved support for
find_package
#83, #84 - Added support for Conan.io #83
This version focused on refactoring several key systems to ensure correct behavior in the interaction of different settings. Most caveats about features only working on the main App have been addressed, and extra arguments have been reworked. Inheritance of defaults makes configuring CLI11 much easier without having to subclass. Policies add new ways to handle multiple arguments to match your favorite CLI programs. Error messages and help messages are better and more flexible. Several bugs and odd behaviors in the parser have been fixed.
- Added a version macro,
CLI11_VERSION
, along with*_MAJOR
,*_MINOR
, and*_PATCH
, for programmatic access to the version. - Reworked the way defaults are set and inherited; explicit control given to user with
->option_defaults()
#48 - Hidden options now are based on an empty group name, instead of special "hidden" keyword #48
parse
no longer returns (soCLI11_PARSE
is always usable) #37- Added
remaining()
andremaining_size()
#37 allow_extras
andprefix_command
are now valid on subcommands #37- Added
take_last
to only take last value passed #40 - Added
multi_option_policy
and shortcuts to provide more control than just a take last policy #59 - More detailed error messages in a few cases #41
- Footers can be added to help #42
- Help flags are easier to customize #43
- Subcommand now support groups #46
CLI::RuntimeError
added, for easy exit with error codes #45- The clang-format script is now no longer "hidden" #48
- The order is now preserved for subcommands (list and callbacks) #49
- Tests now run individually, utilizing CMake 3.10 additions if possible #50
- Failure messages are now customizable, with a shorter default #52
- Some improvements to error codes #53
require_subcommand
now offers a two-argument form and negative values on the one-argument form are more useful #51- Subcommands no longer match after the max required number is obtained #51
- Unlimited options no longer prioritize over remaining/unlimited positionals #51
- Added
->transform
which modifies the string parsed #54 - Changed of API in validators to
void(std::string &)
(const for users), throwing providing nicer errors #54 - Added
CLI::ArgumentMismatch
#56 and fixed missing failure if one arg expected #55 - Support for minimum unlimited expected arguments #56
- Single internal arg parse function #56
- Allow options to be disabled from INI file, rename
add_config
toset_config
#60
app.parse
no longer returns a vector. Instead, useapp.remaining(true)
."hidden"
is no longer a special group name, instead use""
- Validators API has changed to return an error string; use
.empty()
to get the old bool back- Use
.set_help_flag
instead of accessing the help pointer directly (discouraged, but not removed yet)add_config
has been renamed toset_config
- Errors thrown in some cases are slightly more specific
This release focuses on making CLI11 behave properly in corner cases, and with config files on the command line. This includes fixes for a variety of reported issues. A few features were added to make life easier, as well; such as a new flag callback and a macro for the parse command.
- Added functional form of flag #33, automatic on C++14
- Fixed Config file search if passed on command line #30
- Added
CLI11_PARSE(app, argc, argv)
macro for simple parse commands (does not support returning arg) - The name string can now contain spaces around commas #29
set_default_str
now only sets string, andset_default_val
will evaluate the default string given #26- Required positionals now take priority over subcommands #23
- Extra requirements enforced by Travis
This release incorporates feedback from the release announcement. The examples are slowly being expanded, some corner cases improved, and some new functionality for tricky parsing situations.
- Added simple support for enumerations, allow non-printable objects #12
- Added
app.parse_order()
with original parse order (#13, #16) - Added
prefix_command()
, which is likeallow_extras
but instantly stops and returns. (#8, #17) - Removed Windows warning (#10, #20)
- Some improvements to CMake, detect Python and no dependencies on Python 2 (like Python 3) (#18, #21)
This is the first stable release for CLI11. Future releases will try to remain backward compatible and will follow semantic versioning if possible. There were a few small changes since version 0.9:
- Cleanup using
clang-tidy
andclang-format
- Small improvements to Timers, easier to subclass Error
- Move to 3-Clause BSD license
This release focused on cleaning up the most exotic compiler warnings, fixing a few oddities of the config parser, and added a more natural method to check subcommands.
- Better CMake named target (CLI11)
- More warnings added, fixed
- Ini output now includes
=false
whendefault_also
is true - Ini no longer lists the help pointer
- Added test for inclusion in multiple files and linking, fixed issues (rarely needed for CLI, but nice for tools)
- Support for complex numbers
- Subcommands now test true/false directly or with
->parsed()
, cleaner parse
This release moved the repository to the CLIUtils main organization.
- Moved to CLIUtils on GitHub
- Fixed docs build and a few links
Lots of small bugs fixed when adding code coverage, better in edge cases. Much more powerful ini support.
- Allow comments in ini files (lines starting with
;
) - Ini files support flags, vectors, subcommands
- Added CodeCov code coverage reports
- Lots of small bugfixes related to adding tests to increase coverage to 100%
- Error handling now uses scoped enum in errors
- Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added.
- Adding extra utilities in full version only,
Timer
(not needed for parsing, but useful for general CLI applications). - Better support for custom
add_options
like functions.
Lots of cleanup and docs additions made it into this release. Parsing is simpler and more robust; fall through option added and works as expected; much more consistent variable names internally.
- Simplified parsing to use
vector<string>
only - Fixed fallthrough, made it optional as well (default: off):
.fallthrough()
. - Added string versions of
->requires()
and->excludes()
for consistency. - Renamed protected members for internal consistency, grouped docs.
- Added the ability to add a number to
.require_subcommand()
.
- Allow
Hidden
options. - Throw
OptionAlreadyAdded
errors for matching subcommands or options, with ignore-case included, tests ->ignore_case()
added to subcommands, options, andadd_set_ignore_case
. Subcommands inherit setting from parent App on creation.- Subcommands now can be "chained", that is, left over arguments can now include subcommands that then get parsed. Subcommands are now a list (
get_subcommands
). Addedgot_subcommand(App_or_name)
to check for subcommands. - Added
.allow_extras()
to disable error on failure. Parse returns a vector of leftover options. Renamed error toExtrasError
, and now triggers on extra options too. - Added
require_subcommand
toApp
, to simplify forcing subcommands. Do not doadd_subcommand()->require_subcommand
, since that is the subcommand, not the mainApp
. - Added printout of ini file text given parsed options, skips flags.
- Support for quotes and spaces in ini files
- Fixes to allow support for Windows (added Appveyor) (Uses
-
, not/
syntax)
- Updates to help print
- Removed
run
, please useparse
unless you subclass and add it - Supports ini files mixed with command line, tested
- Added Range for further Plumbum compatibility
- Added function to print out ini file
- Added
->requires
,->excludes
, and->envname
from Plumbum - Supports
->mandatory
from Plumbum - More tests for help strings, improvements in formatting
- Support type and set syntax in positionals help strings
- Added help groups, with
->group("name")
syntax - Added initial support for ini file reading with
add_config
option. - Supports GCC 4.7 again
- Clang 3.5 now required for tests due to googlemock usage, 3.4 should still work otherwise
- Changes
setup
for an explicit help bool in constructor/add_subcommand
- Moved to simpler syntax, where
Option
pointers are returned and operated on - Removed
make_
style options - Simplified Validators, now only requires
->check(function)
- Removed Combiners
- Fixed pointers to Options, stored in
unique_ptr
now - Added
Option_p
andApp_p
, mostly for internal use - Startup sequence, including help flag, can be modified by subclasses
First release before major cleanup. Still has make syntax and combiners; very clever syntax but not the best or most commonly expected way to work.