Skip to content

ouser4629/CmdArgLib_MainFunction

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 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),
    ]

    private static let note1 = """
        The $S{lower} and $S{upper} options shadow each other; only the last one specified 
        is applicable.
        
        Bracketed parameters in the usage 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 usage line are not required because they have
  explicit or implied default values. The other parameters 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, BasicParameterEnum { case cat, dog, cow }
enum Reptile: String, BasicParameterEnum { case snake, lizard, turtle }
enum Bird: String, BasicParameterEnum { case dove, robin, eagle }
enum Bug: String, BasicParameterEnum { case bee, ant, ladybug }

@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", Bird.orCases("One of")),
        .text("\nOPTIONS:"),
        .parameter("mammal", "A mammal"),
        .parameter("maybeReptile", "A reptile (default: chosen randomly)"),
        .parameter("bird", Bird.orCases("One of")),
        .parameter("help", "Print this help screen"),
        .text("\nMAMMALS:"),
        .rawValueLines(mammalDict),
        .text("\nREPTILES:"),
        .rawValueLines(reptileDict),
    ]

    private static let mammalDict: [(String, String)] = [
        ("cat", "A domesticated carnivorous mammal."),
        ("dog", "A domesticated carnivorous mammal."),
        ("cow", "A large, domesticated bovine mammal."),
    ]

    private static let reptileDict = [
        ("snake", "A long, slender, limbless reptile that moves by slithering."),
        ("lizard", "A reptile with four legs, a long tail, and movable eyelids."),
        ("turtle", "A reptile with a hard, bony shell that protects its body."),
    ]
}
Help Screen
> ./mf2-enums -h
DESCRIPTION: Select some animals.

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

ARGUMENT:
  <bug>                   One of "dove", "robin" or "eagle".

OPTIONS:
  -m/--mammal <mammal>    A mammal (default: "dog").
  -r/--reptile <reptile>  A reptile (default: chosen randomly).
  -b/--bird <bird>        One of "dove", "robin" or "eagle".
  -h/--help               Print this help screen.

MAMMALS:
  cat                     A domesticated carnivorous mammal.
  dog                     A domesticated carnivorous mammal.
  cow                     A large, domesticated bovine mammal.

REPTILES:
  snake                   A long, slender, limbless reptile that moves by
                          slithering.
  lizard                  A reptile with four legs, a long tail, and movable
                          eyelids.
  turtle                  A reptile with a hard, bony shell that protects its
                          body.
Command Calls
> ./mf2-enums --bird robin bee
  mammal: dog
  reptile: turtle
  bird: robin
  bug: bee
> ./mf2-enums -m velociraptor
Errors:
  missing an occurance of the "-b/--bird" option
  missing a "<bug>"
  "velociraptor" 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
iimport CmdArgLib
import CmdArgLibMacros

typealias Word = String

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

@main
struct Example_3_Lists {
    @MainFunction
    private static func mf3Lists(
        r__reptiles reptiles: Variadic<Reptile> = [],
        b__bugs bugs: Variadic<Bug>,
        m__mammal mammals: [Mammal],
        h__help help: MetaFlag = MetaFlag(helpElements: helpElements),
        tail: Rest<Word> = []
    ) {
        let lines = #taggedValues(mammals, reptiles, bugs, tail)
        for line in lines { print("  \(line)") }
    }
    
    private static let helpElements: [ShowElement] = [
        .text("DESCRIPTION:", "Select lists of animals."),
        .synopsis("\nUSAGE:"),
        .text("\nPARAMETERS:"),
        .parameter("reptiles", "\(Reptile.andCases("One or more of",""))"),
        .parameter("bugs", "\(Bug.andCases("One or more of",""))"),
        .parameter("mammals", "\(Mammal.orCases("Either","")) (can be repeated)"),
        .parameter("tail", "Any remaining \"shell words\", including labels and meta-flags"),
        .parameter("help", "Print this help screen"),
    ]
}
Help Screen
> ./mf3-lists --help
DESCRIPTION: Select lists of animals.

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

PARAMETERS:
  -r/--reptiles <reptile>...  One or more of "snake", "lizard" and "turtle".
  -b/--bugs <bug>...          One or more of "bee", "ant" and "ladybug".
  -m/--mammal <mammal>        Either "cat", "dog" or "cow" (can be repeated).
  --tail <word>...            Any remaining "shell words", including labels and
                              meta-flags.
  -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]
  tail: []
> ./mf3-lists -m dog -m cat -b ladybug --tail -b ant -- --help
  mammals: [dog, cat]
  reptiles: []
  bugs: [ladybug]
  tail: ["-b", "ant", "--", "--help"]
> ./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

Example_4_Errors

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

Code
iimport 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.errors(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.
## Multiple I/O errors
> ./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, BasicParameterEnum { case cat, dog, cow}
enum Reptile: String, BasicParameterEnum {case snake, lizard, turtle}
enum Bug: String, BasicParameterEnum {case bee, ant, ladybug}

@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.orCases("A")),
        .parameter("reptiles", Reptile.orCases("One or more of")),
        .parameter("bugs", Bug.orCases("A", "(can be repeated)")),
        .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 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 reptiles.
  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
Errors:
  missing a "<mammal>"
  missing a "<reptile>"
  missing a "<bug>"
See 'mf5-positionals --help' for more information.
> ./mf5-positionals dog snake turtle ant bee
Errors:
  missing a "<bug>"
  "ant" and "bee" are invalid <reptile>s
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
mport CmdArgLib
import CmdArgLibMacros
import Foundation

enum Color: String, BasicParameterEnum { case red, blue, yellow }
enum Animal: String, BasicParameterEnum { 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.casesJoinedWith("and")), and the $E{animals}s 
        are \(Animal.casesJoinedWith("and")).
        """

    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}"
        * the joined labels of the "greeting" parameter is "$J{greeting}"
        * the joined labels of the "name" parameter is "$J{maybeName}"
        * the joined labels of the "color" parameter is "$J{colors}"
        * the joined labels of the "help" parameter is "$J{help}"
        """

    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"
  * the joined labels of the "greeting" parameter is "-g"
  * the joined labels of the "name" parameter is "--name"
  * the joined labels of the "color" parameter is "-c/--color"
  * the joined labels of the "help" parameter is "-h/-help/--help"

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

enum Mammal: String, BasicParameterEnum { case cat, dog, cow }

@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,
        generateManpage: MetaFlag = MetaFlag(manPageElements: manPageElements),
        v__version version: MetaFlag = MetaFlag(string: "version 0.1.0 - 2025-10-14"),
        h__help help: MetaFlag = MetaFlag(string: "Run man mf7-man for help.")
    ) {
        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}, $E{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("generateManpage", "Generate a manual page"),
        .parameter("version", "Show version information"),
        .lines("", note1),
        .lines("", note2),
        .lines("MAMMALS"),
        .rawValueLines(mammalInfo),
        .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 mammalInfo: [(String, String)] = [
        ("cat", "A domesticated carnivorous mammal."),
        ("dog", "A domesticated carnivorous mammal."),
        ("cow", "A large, domesticated bovine mammal."),
    ]

    private static let authors = """
        .Sh AUTHORS
        The mf2-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

 
 
 

Contributors

Languages