![]() |
VOOZH | about |
dotnet add package Feather.ConsoleApplication --version 2.0.0
NuGet\Install-Package Feather.ConsoleApplication -Version 2.0.0
<PackageReference Include="Feather.ConsoleApplication" Version="2.0.0" />
<PackageVersion Include="Feather.ConsoleApplication" Version="2.0.0" />Directory.Packages.props
<PackageReference Include="Feather.ConsoleApplication" />Project file
paket add Feather.ConsoleApplication --version 2.0.0
#r "nuget: Feather.ConsoleApplication, 2.0.0"
#:package Feather.ConsoleApplication@2.0.0
#addin nuget:?package=Feather.ConsoleApplication&version=2.0.0Install as a Cake Addin
#tool nuget:?package=Feather.ConsoleApplication&version=2.0.0Install as a Cake Tool
👁 NuGet
👁 NuGet Downloads
👁 Checks
The Console application eases the creation of beautiful and testable command line interfaces in F#.
The Console application allows you to create command-line commands. Your console commands can be used for any recurring task, such as cronjobs, imports, or other batch jobs.
This library is inspired by Symfony/Style and Symfony/Console
dotnet add package Feather.ConsoleApplication
open Feather.ConsoleApplication
[<EntryPoint>]
let main argv =
consoleApplication {
name "Example"
version "1.0.0"
info ApplicationInfo.NameAndVersion
command "my:first-command" {
Description = "This is my first command."
Help = Some "It even has some explicit help. 🎉"
Arguments = [
Argument.required "firstName" "First name of the user."
Argument.optional "lastName" "Last name" None
]
Options = [
Option.noValue "formal" None "Whether to use a formal greetings."
Option.optional "yell" (Some "y") "Whether to greet by yelling." None
]
Initialize = None
Interact = None
Execute = Execute <| fun (input, output) ->
let names =
let firstName = input |> Input.getArgumentValue "firstName"
match input with
| Input.Argument.OptionalValue "lastName" lastName -> sprintf "%s %s" firstName lastName
| _ -> firstName
let greet name =
match input with
| Input.Option.IsSet "formal" _ -> sprintf "Good morning, %s" name
| _ -> sprintf "Hello, %s" name
let (shouldYell, loudly) =
match input with
| Input.Option.Has "yell" value ->
match value |> OptionValue.stringValue with
| Some "loud" -> (true, true)
| _ -> (true, false)
| _ -> (false, false)
names
|> greet
|> fun greetings ->
let greetings = if shouldYell then greetings.ToUpper() else greetings
if loudly then greetings + "!!!" else greetings + "."
|> output.Message
ExitCode.Success
}
}
|> run argv
Command: dotnet example.dll my:first-command Mortal
Example <1.0.0>
===============
Hello, Mortal!
Command: dotnet example.dll my:first-command Mortal Flesh
Example <1.0.0>
===============
Hello, Mortal Flesh!
Command: dotnet example.dll my:first-command Mortal Flesh --formal
Example <1.0.0>
===============
Good morning, Mortal Flesh.
Command: dotnet example.dll my:first-command Mortal Flesh --yell
Example <1.0.0>
===============
HELLO, MORTAL FLESH.
Command: dotnet example.dll my:first-command Mortal Flesh --yell loud --formal
Example <1.0.0>
===============
GOOD MORNING, MORTAL FLESH!!!
Command: dotnet example.dll my:first-command --help
Example <1.0.0>
===============
Description:
This is my first command.
Usage:
my:first-command [options] [--] <firstName> [<lastName>]
Arguments:
firstName First name of the user.
lastName Last name
Options:
--formal Whether to use a formal greetings.
-y, --yell[=YELL] Whether to greet by yelling.
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
-n, --no-interaction Do not ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity of messages
Help
It even has some explicit help. 🎉
| Function | Arguments | Description |
|---|---|---|
| name | name: string |
It will set a name of the application. (This is part of ApplicationInfo.) |
| version | version: string |
It will set a version of the application. (This is part of ApplicationInfo.) |
| title | title: string |
It will set a main title of the application. (This is part of ApplicationInfo.) |
| description | description: string |
It will set a description of the application. (It is visible in about command.) |
| meta | string * string |
It will add an application meta information. (It is visible in about command.) |
(string * string) list |
It will add multiple application meta information. (It is visible in about command.) |
|
| git | repository: string option * branch: string option * commit: string option |
It will register git meta information, which is visible in about command. |
| gitRepository | repository: string |
It will register git repository meta information, which is visible in about command. |
| gitBranch | branch: string |
It will register git branch meta information, which is visible in about command. |
| gitCommit | commit: string |
It will register git commit meta information, which is visible in about command. |
| info | ApplicationInfo |
It will define, how application info will be shown in commands output. (Default is Hidden) |
| showOptions | OptionDecorationLevel |
It will define, how options will be shown in the command help output. (Default is Minimal) |
| command | commandName: string, CommandDefinition |
It will register a command to the application. |
| defaultCommand | commandName: string |
It will set a name of default command. Default command is run when no command name is pass to the arguments. (Default is list.) |
| useOutput | Output |
It will override Output in IO, which gets every command life-cycle function. (Default is implemented by ConsoleStyle) |
| useAsk | question: string -> answer: string |
It will override an Ask function, which is used in Interact life-cycle stage. (Default is implemented by ConsoleStyle) |
| updateOutput | Output -> Output |
Function which allows to change the output (set style, different outputInterface for a ConsoleStyle and more) |
| withStyle | Feather.ConsoleApplication.Style |
A style which will be set to the Output. |
| withCustomTags | Feather.ConsoleApplication.CustomTag list |
It will register custom tags to the Output Style. |
Result<Feather.ConsoleApplication.CustomTag, string> list |
It will handle results and register custom tags to the Output Style. |
NOTES:
about commandstate: Definition, but this is a current state of the application and it is passed implicitly in the background by computation expression.Commands have three life-cycle functions that are invoked when running the command:
Initialize (optional)
interact and the execute functions. Its main purpose is to initialize variables used in the rest of the command functions.Interact (optional)
initialize and before execute. Its purpose is to check if some of the options/arguments are missing and interactively ask the user for those values. This is the last place where you can ask for missing options/arguments. After this function, missing options/arguments will result in an error.--no-interaction option.Execute (required)
initialize and interact. It contains the logic you want the command to execute.ExecuteExecuteResultExecuteAsyncExecuteAsyncResultAll life-cycle functions gets an IO (Input * Output).
Both Initialize and Interact may change the IO on the way. Execute will get final result of IO.
TIP: There is a Type for every Life-cycle function.
As was mentioned before, its purpose is to check if some of the options/arguments are missing and interactively ask the user for those values.
Interact function gets an InteractiveInput, which is { Input: Input; Ask: Ask } record, where Ask is string -> string function.
Add missing argument:
Interact = Some (fun ({ Input = input; Ask = ask }, output) ->
let input =
match input with
| Input.Argument.Has "mandatoryArg" _ -> input // already has a value
| _ -> // value is missing, as user for a value
ask "Please, give a value for mandatory argument:"
|> Input.Argument.set input "mandatoryArg"
(input, output)
)
Add missing option:
Interact = Some (fun (input, output) ->
let input =
match input.Input with
| Input.Option.Has "message" value ->
output.Message <| sprintf "Message value is already given from arguments, it is: %s" (value |> OptionValue.value)
input.Input
| _ ->
input.Ask "Message:"
|> Input.Option.set input.Input "message"
(input, output)
)
The most interesting part of the commands are the arguments and options that you can make available. These arguments and options allow you to pass dynamic information from the terminal to the command.
Command name is a special type of required argument, which has a reserved name (command) and will always be there (if it is not passed by user, it will be a default command).
You do not have to type out the full command names. You can just type the shortest unambiguous name to run a command. So if there are non-clashing commands, then you can run help like this:
dotnet example.dll h
If you have commands using : to namespace commands then you only need to type the shortest unambiguous text for each part. If you have created the my:first-command as shown above then you can run it with:
dotnet example.dll m:f Mortal Flesh
If you enter a short command that's ambiguous (i.e. there are more than one command that match), then no command will be run and some suggestions of the possible commands to choose from will be output.
Arguments are the strings - separated by spaces - that come after the command name itself. They are ordered, and can be optional or required. It is also possible to let an argument take a list of values (only the last argument ca be a list).
Note: There is a more .
There are four argument variants you can use:
There are many ways how to access Arguments:
Through pattern matching
| Active Pattern | Description |
|---|---|
| Input.Argument.IsDefined | Matched when given string is defined as argument name. |
| Input.Argument.Has | Matched when given string has any value in current Input (default or from args). |
| Input.Argument.IsSet | Matched when input has argument AND that value is not empty. |
| Active Pattern | Description | Value |
|---|---|---|
| Input.Argument.Value | Matched when input has argument. (Fail with exception when value is not set or it is a list.) | string |
| Input.Argument.OptionalValue | Matched when input has argument AND it has a single value. | string |
| Input.Argument.ListValue | Matched when input has argument. | string list |
Just get a value from Input
| Function | Description |
|---|---|
| Input.Argument.tryGet | Returns an ArgumentValue option, when Input has argument. |
| Input.Argument.get | Returns an ArgumentValue, when Input has argument OR fail with exception. |
| Input.Argument.value | Returns a string value from ArgumentValue, when Input has argument OR fail with exception. |
| Input.Argument.asString | Returns a string option value from ArgumentValue, when Input has argument. |
| Input.Argument.asInt | Returns an int option value from ArgumentValue, when Input has argument. (It fails with an exception when string value is not int.) |
| Input.Argument.asList | Returns an string list value from ArgumentValue, when Input has argument. (It returns a list even for single values.) |
| Input.Argument.tryGetAsInt | Returns an int option value from ArgumentValue, when Input has argument. (It returns None when string value is not int.) |
| Input.Argument.isValueSet | Checks whether argument has a value AND that value is not empty. |
Note: All functions above will fail with an exception when given "argument" is not defined.
Unlike arguments, options are not ordered (meaning you can specify them in any order) and are specified with two dashes (e.g. --yell). Options are always optional, and can be setup to accept a value (e.g. --dir=src) or simply as a boolean flag without a value (e.g. --yell).
You can also declare a one-letter shortcut that you can call with a single dash (e.g. -y).
Note that to comply with the docopt standard, long options can specify their values after a white space or an = sign (e.g. --iterations 5 or --iterations=5), but short options can only use white spaces or no separation at all (e.g. -i 5 or -i5).
Note: There is a more .
There are five option variants you can use:
Are built-in options, which every command has. And they are parsed before other given arguments. They may even bypass other values.
--help, -h)
--help option is passed, it will show overall help for console application.--help option (this would ignore any other options).--version, -V)
Console Application)--no-interaction, -n)
--quiet, -q)
--verbose, -v|vv|vvv)
v determines a level of verbosity.There are many ways how to access Options:
Through pattern matching
| Active Pattern | Description |
|---|---|
| Input.Option.IsDefined | Matched when given string is defined as option name. |
| Input.Option.Has | Matched when given string has any value in current Input (default or from args). |
| Input.Option.IsSet | Matched when input has option AND that value is not empty. |
| Active Pattern | Description | Value |
|---|---|---|
| Input.Option.Value | Matched when input has option. (Fail with exception when value is not set or it is a list.) | string |
| Input.Option.OptionalValue | Matched when input has option AND it has a single value. | string |
| Input.Option.ListValue | Matched when input has option. | string list |
Just get a value from Input
| Function | Description |
|---|---|
| Input.Option_.tryGet | Returns an OptionValue option, when Input has option. |
| Input.Option_.get | Returns an OptionValue, when Input has option OR fail with exception. |
| Input.Option_.value | Returns a string value from OptionValue, when Input has option OR fail with exception. |
| Input.Option_.asString | Returns a string option value from OptionValue, when Input has option. |
| Input.Option_.asInt | Returns an int option value from OptionValue, when Input has option. (It fails with an exception when string value is not int.) |
| Input.Option_.asList | Returns an string list value from OptionValue, when Input has option. (It returns a list even for single values.) |
| Input.Option_.tryGetAsInt | Returns an int option value from OptionValue, when Input has option. (It returns None when string value is not int.) |
| Input.Option.isValueSet | Checks whether option has a value AND that value is not empty. |
Note: All functions above will fail with an exception when given "option" is not defined.
Output is handled by ConsoleStyle.
You can even alter an Output by using useOutput function to set your own implementation.
There are two default commands:
defaultCommand console application function), it means, when user do not specify a command in arguments, the List will be used.--help (-h) option as well.There are some different ways to display the same output:
help, help --help or help help will execute a Help command for itselflist or no-command will execute list command (when no other default command is set)list --help, help list or --help will execute Help command for List commandDisplays help for a command
dotnet path/to/console.dll help
{application info}
Description:
Displays help for a command
Usage:
help [options] [--] [<command_name>]
Arguments:
command_name The command name [default: "help"]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
-n, --no-interaction Do not ask any interactive question
--no-progress Whether to disable all progress bars
--no-ansi Whether to disable all markup with ansi formatting
-v|vv|vvv, --verbose Increase the verbosity of messages
Help
The help command displays help for a given command:
dotnet path/to/console.dll help list
To display list of available commands, please use list command.
Show list of available commands.
dotnet path/to/console.dll list
{application info}
Description:
Lists commands
Usage:
list [options] [--] [<namespace>]
Arguments:
namespace The namespace name
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
-n, --no-interaction Do not ask any interactive question
--no-progress Whether to disable all progress bars
--no-ansi Whether to disable all markup with ansi formatting
-v|vv|vvv, --verbose Increase the verbosity of messages
Help
The list command lists all commands:
dotnet path/to/console.dll list
You can also display the commands for a specific namespace:
dotnet path/to/console.dll list test
Show list of available commands.
dotnet path/to/console.dll about
{application info}
Description:
Displays information about the current project.
Usage:
about [options]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
-n, --no-interaction Do not ask any interactive question
--no-progress Whether to disable all progress bars
--no-ansi Whether to disable all markup with ansi formatting
-v|vv|vvv, --verbose Increase the verbosity of messages
Help:
The about command displays information about the current project:
dotnet bin/Debug/net6.0/example.dll about about
There are multiple sections shown in the output:
- current project details/meta information
- environment
- console application library
There are some placeholders which may help you to create a better help message.
{{command.name}} - The name of the current command.{{command.full_name}} - The name of the current command including a relative path.TIP: You can use a Help.lines utility function to format your lines.
This is a help, used in list command:
Help =
Help.lines [
"The <c:green>{{command.name}}</c> command lists all commands:"
" <c:green>dotnet {{command.full_name}}</c>"
" You can also display the commands for a specific namespace:"
" <c:green>dotnet {{command.full_name}} test</c>"
]
Add bin/console file with following content to allow a simple entry point for your application
#!/usr/bin/env bash
APP="my-console"
NET="net6.0"
CONSOLE="bin/Debug/$NET/$APP.dll"
if [ ! -f "$CONSOLE" ]; then
CONSOLE="bin/Release/$NET/$APP.dll"
fi
dotnet "$CONSOLE" "$@"
Then just go by bin/console list or other commands.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 2 NuGet packages that depend on Feather.ConsoleApplication:
| Package | Downloads |
|---|---|
|
Tuc.DomainResolver
Library for resolving a Domain types out of a F# script (.fsx) file(s). |
|
|
Tuc.Parser
A parser for TUC files. |
This package is not used by any popular GitHub repositories.