Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ouser4629/CmdArgLib_MainFunction

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CmdArgLib_MainFunction

This package contains examples that use the MainFunction macro provided by the Command Argument Library.

The source code for each example has notes, suggested command line calls, and suggested code edits if you want to experiment.


Example_1_Basic

This example uses three simple types, a Flag, String and an Optional Int, and three meta-flags, help, version and authors. It uses typealiases and ShowMacros to clarify the code and enhance the help screen.

Code
import CmdArgLib
import CmdArgLibMacros

typealias Greeting = String
typealias Name = String
typealias Count = Int

@main
struct Example_1_Basic {
    
    @MainFunction(shadowGroups: ["lower upper"])
    private static func mf1Basic(
        i includeIndex: Flag,
        u upper: Flag = false,
        l lower: Flag = false,
        c__count repeats: Count? = nil,
        g__greeting greeting: Greeting = "Hello",
        _ name: Name,
        authors: MetaFlag = MetaFlag(string: "Robert Ford and Jesse James"),
        h__help help: MetaFlag = MetaFlag(helpElements: helpElements),
        v__version version: MetaFlag = MetaFlag(string: "version 0.1.0 - 2025-10-14"))
    {
        let count = repeats == nil || repeats! < 1 ? (Int.random(in: 1...3)) : repeats!
        var text = "\(greeting) \(name)"
        text = lower ? text.lowercased() : upper ? text.uppercased() : text
        for index in 1...count {
            var text = (includeIndex ? "\(index) " : "") + "\(greeting) \(name)"
            if upper { text = text.uppercased() }
            print(text)
        }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Print a greeting."),
        .synopsis("\nUSAGE:"),
        .text("\nPARAMETERS:"),
        .parameter("includeIndex", "Show index of repeated greetings"),
        .parameter("upper", "Print text in upper case"),
        .parameter("lower", "Print text in lower case"),
        .parameter("help", "Show this help message"),
        .parameter("version", "Show version information"),
        .parameter("repeats", "Repeat the greeting $E{repeats} times (the default is a random integer between 1 and 3)" ),
        .parameter("greeting", "The greeting to print"),
        .parameter("name", "Name of person to greet, if any"),
        .text("\nNOTES:\n", note1),
        .text("\n", note2),
    ]

    private static let note1 = """
        The $S{lower} and $S{upper} options shadow each other; only the last one specified 
        is applicable.
        """

    private static let note2 = """
        Bracketed parameters in the synopsis line are not required because they have
        explicit or implied default values. The other parameters are required.
        """
}
Help Screen
> ./mf1-basic --help
DESCRIPTION: Print a greeting.

USAGE: mf1-basic [-iulhv] [-c <count>] [-g <greeting>] <name>

PARAMETERS:
  -i                        Show index of repeated greetings.
  -u                        Print text in upper case.
  -l                        Print text in lower case.
  -h/--help                 Show this help message.
  -v/--version              Show version information.
  -c/--count <count>        Repeat the greeting <count> times (the default is a
                            random integer between 1 and 3).
  -g/--greeting <greeting>  The greeting to print (default: "Hello").
  <name>                    Name of person to greet, if any.

NOTES:
  The -l and -u options shadow each other; only the last one specified is
  applicable.

  Bracketed parameters in the synopsis line are not required because they have
  explicit or implied default values. The other parametets are required.
Command Calls
> ./mf1-basic -uic2 "Mary Lou, Goodbye Heart"
1 HELLO MARY LOU, GOODBYE HEART
2 HELLO MARY LOU, GOODBYE HEART
>  ./mf1-basic -uixcy --greet
Errors:
  unrecognized option: '-x', in '-uixcy'
  unrecognized option: '--greet'
  missing a '<name>'
  'y' is not a valid <count>
See 'greet --help' for more information.

Example_2_Enums

This example shows how to use simple string enums as basic parameter types in a work function.

Code
import CmdArgLib
import CmdArgLibMacros

enum Mammal: String, CaseIterable, CustomStringConvertible, BasicParameterType { case cat, dog, cow }
enum Reptile: String, CaseIterable, CustomStringConvertible, BasicParameterType { case snake, lizard, turtle }
enum Bird: String, CaseIterable, CustomStringConvertible, BasicParameterType { case dove, robin, eagle }
enum Bug: String, CaseIterable, CustomStringConvertible, BasicParameterType { case bee, ant, ladybug }

extension CaseIterable where AllCases.Element: CustomStringConvertible {
    static var oneOf: String { "A \(Self.casesJoinedWith("or"))" }
}

@main
struct Example_2_Enums {
    @MainFunction
    private static func mf2Enums(
        m__mammal mammal: Mammal = .dog,
        r__reptile maybeReptile: Reptile? = nil,
        b__bird bird: Bird,
        _ bug: Bug,
         h__help help: MetaFlag = MetaFlag(helpElements: helpElements)
    ) {
        let reptile = maybeReptile ?? Reptile.allCases.randomElement()!
        let lines = #taggedValues(mammal, reptile, bird, bug)
        for line in lines { print("  \(line)") }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Select some animals."),
        .synopsis("\nUSAGE:"),
        .text("\nARGUMENT:"),
        .parameter("bug", Bug.oneOf),
        .text("\nOPTIONS:"),
        .parameter("mammal", Mammal.oneOf),
        .parameter("maybeReptile", "\(Reptile.oneOf) (default: chosen randomly)"),
        .parameter("bird",Bird.oneOf),
        .parameter("help", "Print this help screen"),
    ]
}
Help Screen
> ./mf2-enums --help
> ./mf2-enums --help
DESCRIPTION: Select some animals.

USAGE: mf2-enums [-h] [-m <mammal>] [-r <reptile>] -b <bird> <bug>

ARGUMENT:
  <bug>                   A "bee", "ant" or "ladybug".

OPTIONS:
  -m/--mammal <mammal>    A "cat", "dog" or "cow" (default: "dog").
  -r/--reptile <reptile>  A "snake", "lizard" or "turtle" (default: chosen randomly).
  -b/--bird <bird>        A "dove", "robin" or "eagle".
  -h/--help               Print this help screen.
Command Calls
> ./mf2-enums --bird robin bee
  mammal: dog
  reptile: turtle
  bird: robin
  bug: bee
> ./mf2-enums -m horse
Errors:
  missing an occurance of the '--bird' option
  missing '<bug>', a required positional argument
  'horse' is not a valid <mammal>
See 'mf2-enums --help' for more information.

Example_3_Lists

This example shows how to use arrays and variadics.

Code
import CmdArgLib
import CmdArgLibMacros

enum Mammal: String, CaseIterable, CustomStringConvertible, BasicParameterType {case cat, dog, cow}
enum Reptile: String, CaseIterable, CustomStringConvertible, BasicParameterType {case snake, lizard, turtle}
enum Bug: String, CaseIterable, CustomStringConvertible, BasicParameterType {case bee, ant, ladybug}

extension CaseIterable where AllCases.Element: CustomStringConvertible {
    static var arrayOf:  String {"A \(Self.casesJoinedWith("or")) (can be repeated)"}
    static var listOf:  String {"One or more instances of \(Self.casesJoinedWith("or"))"}
}

@main
struct Example_3_Lists {
    @MainFunction
    private static func mf3Lists(
        r__reptiles reptiles: Variadic<Reptile> = [],
        m__mammal mammals: [Mammal] = [],
        b__bugs bugs: Variadic<Bug>,
        h__help help: MetaFlag = MetaFlag(helpElements: helpElements)
    ) {
        let lines = #taggedValues(mammals, reptiles, bugs)
        for line in lines { print("  \(line)") }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Select lists of animals."),
        .synopsis("\nUSAGE:"),
        .text("\nPARAMETERS:"),
        .parameter("reptiles", "\(Reptile.listOf)"),
        .parameter("mammals", "\(Mammal.arrayOf)"),
        .parameter("bugs", "\(Bug.listOf)"),
        .parameter("help", "Print this help screen"),
    ]
}
Help Screen
> ./mf3-lists --help
DESCRIPTION: Select lists of animals.

USAGE: mf3-lists [-h] [-r <reptile>...] [-m <mammal>] -b <bug>...

PARAMETERS:
  -r/--reptiles <reptile>...  One or more instances of "snake", "lizard" or "turtle".
  -m/--mammal <mammal>        A "cat", "dog" or "cow" (can be repeated).
  -b/--bugs <bug>...          One or more instances of "bee", "ant" or "ladybug".
  -h/--help                   Print this help screen.
Command Calls
> ./mf3-lists -m dog -m cat -r snake lizard -m cow -b bee ant
  mammals: [dog, cat, cow]
  reptiles: [snake, lizard]
  bugs: [bee, ant]
 ./mf3-lists -m cow -b bee ant -m cat -r snake lizard -m dog
  mammals: [cow, cat, dog]
  reptiles: [snake, lizard]
  bugs: [bee, ant]
> ./mf3-lists -m dog -m cat -r lizard -r turtle
Errors:
  duplicate occurances of the '-r' option
  missing an occurance of the '-b/--bugs' option
> ./mf3-lists
Error:
  missing an occurance of the '-b/--bugs' option
See 'mf4-lists --help' for more information.

Example_4_Errors

This example shows how to validate input data and handle i/o errors.

Code
import CmdArgLib
import CmdArgLibMacros
import Foundation

typealias File = String
typealias Factor = Double

@main
struct Example_4_Errors {

    @MainFunction
    private static func mf4Errors(
        w__weightFactor weight: Factor = 1.0,
        _ fileNames: Variadic<File>,
        h__help help: MetaFlag = MetaFlag(helpElements: helpElements)
    ) async throws {
        var errors: [String] = []
        
        // Validate input
        if weight < 0 || weight > 1 { errors.append("The weight must be between 0 and 1.") }
        if fileNames.count > 2 { errors.append("At most two file names can be provided.") }
        
        if errors.isEmpty {
            print("Value of weight:\n   \(weight)")
            for fileName in fileNames {
                try await Task.sleep(nanoseconds: 1_000_000)
                do {
                    let contents = try String(contentsOfFile: fileName, encoding: .utf8).trimmingCharacters(in: .whitespacesAndNewlines)
                    print("Contents of \(fileName):\n   \(contents)")
                }
                catch {
                    // throw error
                    var message = showError(error)
                    if !message.contains(fileName) { message = "Error reading \(fileName): \(message)" }
                    errors.append(message)
                }
            }
        }
        
        if !errors.isEmpty { throw Exception(handledErrors: errors) }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Print a weight and the contents of some files."),
        .synopsis("\nUSAGE:"),
        .text("\nPARAMETERS:"),
        .parameter("help", "Print this help screen"),
        .parameter("weight", "A weight factor, which must be between 0 and 1"),
        .parameter("fileNames", "One or two files to be processed"),
    ]
}
Help Screen
> ./mf4-errors --help
DESCRIPTION: Print a weight and the contents of some files.

USAGE: mf4-errors [-h] [-w <factor>] <file>...

PARAMETERS:
  -h/--help                    Print this help screen.
  -w/--weight-factor <factor>  A weight factor, which must be between 0 and 1
                               (default: 1.0).
  <file>...                    One or two files to be processed.
Command Calls
## Valid input
echo This is the content of goodFileName.txt > goodFileName.txt

> ./mf4-errors goodFileName.txt
Value of weight:
   1.0
Contents of goodFileName.txt:
   This is the content of goodFileName.txt
## Command argument syntax error
> ./mf4-errors
Error:
  missing a '<file>'
See 'mf4-errors --help' for more information.
## Validation error
> ./mf4-errors -w2.0 goodFileName.txt foo baz
Errors:
  The weight must be between 0 and 1.
  At most two file names can be provided.
See 'mf4-errors --help' for more information.
## I/O error
> ./mf4-errors veryLongBadFileName
Value of weight:
   1.0
Error:
  The file “veryLongBadFileName” couldn’t be opened because there is no such
    file.
See 'mf4-errors --help' for more information.
> ./mf4-errors veryLongBadFileName CmdArgLibMacrosModule-tool
Value of weight:
   1.0
Errors:
  The file “veryLongBadFileName” couldn’t be opened because there is no such
    file.
  Error reading CmdArgLibMacrosModule-tool: The file couldn’t be opened because
    it isn’t in the correct format.
See 'mf4-errors --help' for more information.

Example_5_Positionals

This example shows the use of postional parameters in a work function.

Code
import CmdArgLib
import CmdArgLibMacros

enum Mammal: String, CaseIterable, CustomStringConvertible, BasicParameterType {case cat, dog, cow}
enum Reptile: String, CaseIterable, CustomStringConvertible, BasicParameterType {case snake, lizard, turtle}
enum Bug: String, CaseIterable, CustomStringConvertible, BasicParameterType {case bee, ant, ladybug}

extension CaseIterable where AllCases.Element: CustomStringConvertible {
    static var oneOf: String { "A \(Self.casesJoinedWith("or"))" }
    static var arrayOf: String {"A \(Self.casesJoinedWith("or")) (can be repeated)"}
    static var listOf: String {"One or more instances of \(Self.casesJoinedWith("or"))"}
}

@main
struct Example_5_Positionals {

    @MainFunction
    private static func mf5Positionals(
        s separator: Flag,
        _ mammal: Mammal,
        _ reptiles: Variadic<Reptile>,
        _ bugs: [Bug],
        h__help help: MetaFlag = MetaFlag(helpElements: helpElements)
    ) {
        let lines = #taggedValues(mammal, reptiles, bugs)
        for line in lines { print("  \(line)") }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Select a mammal, a list of reptiles and a list of bugs."),
        .synopsis("\nUSAGE:"),
        .text("\nARGUMENTS:"),
        .parameter("mammal", Mammal.oneOf),
        .parameter("reptiles", Reptile.listOf),
        .parameter("bugs", Bug.arrayOf),
        .text("\nFLAGS:"),
        .parameter("separator","Does nothing except terminate a variadic list"),
        .parameter("help", "Print this help screen"),
        .lines("\nNOTE:\n", lines),
    ]

    private static let lines = """
        The first argument must be a mammal.
        This must be followed by one or more reptiles.
        The list of reptiles must be termimanted by "-s".
        The "-s" must be followed by one or more bugs.
        """
}
Help Screen
> ./mf5-positionals --help
DESCRIPTION: Select a mammal, a list of reptiles and a list of bugs.

USAGE: mf5-positionals [-sh] <mammal> <reptile>... <bug>

ARGUMENTS:
  <mammal>              A "cat", "dog" or "cow".
  <reptile>...          One or more instances of "snake", "lizard" or "turtle".
  <bug>                 A "bee", "ant" or "ladybug" (can be repeated).

FLAGS:
  -s                    Does nothing except terminate a variadic list.
  -h/--help             Print this help screen.

NOTE:
  The first argument must be a mammal.
  This must be followed by one or more reptiless.
  The list of reptiles must be termimanted by "-s".
  The "-s" must be followed by one or more bugs.
Command Calls
> ./mf5-positionals dog snake turtle -s ant bee
  mammal: dog
  reptiles: [snake, turtle]
  bugs: [ant, bee]
> ./mf5-positionals cow turtle snake -s ant -s bee
  mammal: cow
  reptiles: [turtle, snake]
  bugs: [ant, bee]
 ./mf5-positionals dog snake turtle ant bee
Errors:
  missing a '<bug>'
  none of 'ant' and 'bee' is a valid '<reptile>'
See 'mf5-positionals --help' for more information.
./mf5-positionals
Errors:
  missing a '<mammal>'
  missing a '<reptile>'
  missing a '<bug>'
See 'mf5-positionals --help' for more information.

Example_6_ShowMacros

This example shows the use of show macros, which can be used to insert formatted label and type names in meta services text.

Code
import CmdArgLib
import CmdArgLibMacros
import Foundation

enum Color: String, CaseIterable, CustomStringConvertible, BasicParameterType {
    case red, blue, yellow
}

enum Animal: String, CaseIterable, CustomStringConvertible, BasicParameterType {
    case cat, dog, cow
}

typealias Greeting = String
typealias Name = String
typealias File = String

@main
struct Example_6_ShowMacros {
    @MainFunction
    private static func mf6ShowMacros(
        g greeting: Greeting = "Hello",
        name maybeName: Name?,
        c__color colors: [Color],
        a__animals animals: Variadic<Animal>,
        h_help_help help: MetaFlag = MetaFlag(helpElements: helpElements)
    ) {
        let name = maybeName ?? "nil"
        let lines = #taggedValues(greeting, name, colors, animals)
        for line in lines { print("  \(line)") }
    }

    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:\n", "Print parsed values of command line arguments."),
        .synopsis("\nUSAGE:\n"),
        .text("\nPARAMETERS:"),
        .parameter("greeting", "The greeting to print"),
        .parameter("maybeName", "If specified, the name of the person to greet"),
        .parameter("colors", "Append $E{colors} to the array of colors (can be repeated)"),
        .parameter("animals", "One or more animals (if specified)"),
        .text("\nNOTE:\n", note),
        .lines("\nLABEL MACROS:\n", labelNate),
        .lines("\nTYPE MACROS:\n", typesNote),
    ]

    private static let note = """
        The $E{colors}s are \(Color.casesJoined()), and the $E{animals}s 
        are \(Animal.casesJoined()).
        """

    private static let labelNate = """
        * the shortest label of the "greeting" parameter is "$S{greeting}"
        * the shortest label of the "name" parameter is "$S{maybeName}"
        * the shortest label of the "color" parameter is "$S{colors}"
        * the longest label of the "greeting" parameter is "$L{greeting}"
        * the longest label of the "name" parameter is "$L{maybeName}"
        * the longest label of the "color" parameter is "$L{colors}"
        """

    private static let typesNote = """
      * the type of the "greeting" parameter is "$T{greeting}"
      * the type of the "name" parameter is "$T{maybeName}"
      * the type of the "colors" parameter is "$T{colors}"
      * the type of the "animals" parameter is "$T{animals}"
      * the type of the wrapped element of the "maybeName" parameter is "$E{maybeName}"
      * the type of an element of the "colors" parameter is "$E{colors}" 
      * the type of an element of the "animals" parameter is "$E{animals}"
      """
}
Help Screen
> ./mf6-show-macros --help
DESCRIPTION:
  Print parsed values of command line arguments.

USAGE:
  mf6-show-macros [-h] [-g <greeting>] [--name <name>] -c <color> -a <animal>...

PARAMETERS:
  -g <greeting>             The greeting to print (default: "Hello").
  --name <name>             If specified, the name of the person to greet.
  -c/--color <color>        Append <color> to the array of colors (can be repeated).
  -a/--animals <animal>...  One or more animals (if specified).

NOTE:
  The <color>s are "red", "blue" and "yellow", and the <animal>s are "cat", "dog" and "cow".

LABEL MACROS:
  * the shortest label of the "greeting" parameter is "-g"
  * the shortest label of the "name" parameter is "--name"
  * the shortest label of the "color" parameter is "-c"
  * the longest label of the "greeting" parameter is "-g"
  * the longest label of the "name" parameter is "--name"
  * the longest label of the "color" parameter is "--color"

TYPE MACROS:
  * the type of the "greeting" parameter is "<greeting>"
  * the type of the "name" parameter is "<name>?"
  * the type of the "colors" parameter is "[<color>]"
  * the type of the "animals" parameter is "<animal>..."
  * the type of the wrapped element of the "maybeName" parameter is "<name>"
  * the type of an element of the "colors" parameter is "<color>" 
  * the type of an element of the "animals" parameter is "<animal>"

Example_7_ManPage

This example is the same as Example_1_Basic, except that it provides a manual page instead of a help screen.

Code
import CmdArgLib
import CmdArgLibMacros
import Foundation

typealias Greeting = String
typealias Name = String
typealias Count = Int

@main
struct Example_7_ManPage {
    
    @MainFunction(shadowGroups: ["lower upper"])
    private static func mf7Man(
        i includeIndex: Flag,
        u upper: Flag,
        l lower: Flag,
        c__count repeats: Count?,
        g__greeting greeting: Greeting = "Hello",
        _ name: Name,
        manpage: MetaFlag = MetaFlag(manPageElements: manPageElements),
        v__version version: MetaFlag = MetaFlag(string: "version 0.1.0 - 2025-10-14"))
    {
        let count = repeats == nil || repeats! < 1 ? (Int.random(in: 1...3)) : repeats!
        var text = "\(greeting) \(name)"
        text = lower ? text.lowercased() : upper ? text.uppercased() : text
        for index in 1...count {
            var text = (includeIndex ? "\(index) " : "") + "\(greeting) \(name)"
            if upper { text = text.uppercased() }
            print(text)
        }
    }

    private static let manPageElements: [ShowElement] = [
        .prologue(description: "print a greeting."),
        .synopsis(),
        .lines("DESCRIPTION", "Print $T{greeting}, followed by $E{name}, $T{repeats} times."),
        .lines("", "The following options are available:"),
        .parameter("greeting", "The greeting to print"),
        .parameter("includeIndex", "Show index of repeated greetings"),
        .parameter("lower", "Print text in lower case"),
        .parameter("repeats", "Repeat the greeting $E{repeats} times (the default is a random integer between 1 and 3)" ),
        .parameter("upper", "Print text in upper case"),
        .parameter("version", "Show version information"),
        .lines("", note1),
        .lines("", note2),
        .lines("", authors),
    ]

     private static let note1 = """
        The $S{lower} and $S{upper} options shadow each other; only the last one specified 
        is applicable.
        """

    private static let note2 = """
        Bracketed parameters in the synopsis line are not required because they have
        explicit or implied default values. The other parameters are required.
        """

    private static let authors = """
        .Sh AUTHORS
        The mf7-man utility was written by
        .%A Robert Ford and Jesse James .
        """
}
Manual Page
> ./mf7-man --manpage > mf7-man.1 && man ./mf7-man.1

ManPageInLess


Example_8_Sed

This example wraps sed. The code is more complex than usual because sed has two ways of being called, and the two calls use postional parameters differently. Another complication is that the order of option arguments in a command argument list affects how the program runs.

Help Screen
> ./mf8-sed --help
DESCRIPTION
  A sed wrapper.

USAGE
  mf8-sed [-np] [-i <extension>] <command> [<file>...]
  mf8-sed [-np] [-i <extension>] [-e <command>] [-f <command_file>] [<file>...]

OPTIONS
  -n/--quiet                        By default, each line of input is echoed to the
                                    standard output after all of the commands have been
                                    applied to it. The -n option suppresses this
                                    behavior.
  -p/--preview                      Print the genrated sed command without executing it.
  -i/--inplace <extension>          Edit the <file>s in-place, saving backups with the
                                    specified <extension>. If a zero-length extension is
                                    given (""), no backup will be saved.
  -e/--expression <command>         Append <command> to the list of editing <command>s
                                    (may be repeated).
  -f/--command-file <command_file>  Append the editing <command>s found in the file
                                    <command_file> to the list of editing <command>s (may
                                    be repeated). The editing commands should each be
                                    listed on a separate line. The <command>s are read
                                    from the standard input if  <command_file> is “-”.
NOTES
  The mf8-sed utility reads the specified <file>s, or the standard input if no <file>s
  are specified, modifying the input as specified by a list of <command>s. The input is
  then written to the standard output.

  A single <command> may be specified as the first argument to mf8-sed, in which case no
  -e or -f options are allowed. Multiple <command>s may be specified by using the -e or
  -f options, in which case all arguments are <file>s. All <command>s are applied to the
  input in the order they are specified regardless of their origin.

  Regular expressions are always interpreted as extended (modern) regular expressions.
Manual Page

ManPageInLess

Command Calls
> echo FOO > foo.text
> ./mf8-sed s/FOO/BAR/ foo.text
BAR
#### --- ⚠️ Something is wrong with sed (or its manual page's first synopsis) --- ###
> echo FOO > foo.text
> sed s/FOO/BAR/ -i~ foo.text
sed: -i~: No such file or directory
BAR
> cat foo.text
FOO
> cat foo.text~
cat: foo.text~: No such file or directory
#### --- 👍 mf8-sed to to the rescue --- ###
> echo FOO > foo.text
> ./mf8-sed s/FOO/BAR/ -i~ foo.text
> cat foo.text; cat foo.text~
BAR
FOO

Setup

Clone and Build
> mkdir Temp
> cd Temp
> git clone https://github.com/ouser4629/CmdArgLib_MainFunction.git
cd CmdArgLib_MainFunction
> swift build -c release

You might get: warning: 'input verification failed'. No worries.

Run

Press command T to set up a new "release" tab in the terminal.

In the release tab:

> cd .build/release/
> ls -1F | grep '*'
CmdArgLibMacrosModule-tool*
mf1-basic*
mf2-man*
mf2-enums*
mf4-lists*
mf5-positionals*
mf6-show-macros*
mf4-errors*
mf8-sed*
> ./mf1-basic --version
  version 0.1.0 - 2025-10-14
Tip

If you want to experiment with these examples, it is recomended that you use the following cycle:

  • Edit the package in Xcode (which flags most MainFunction related errors, like duplicate flag names, as you edit)
  • Go to the "build" terminal tab at ~/Temp/CmdArgLib_MainFunction
  • Rebuild: > swift build -c release
  • Go to the "release" terminal tab at ~/Temp/CmdArgLib_MainFunction/.build/release
  • Run the programs > ./mf...

Occasionally you might want to run rm -rf .build .swiftpm in the build tab. If you do, be sure to close the current release tab, and set up a new one after the build completes.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published