CLI::Framework(3pm)

πŸ“¦
version 0.05 Β· 2 versions
  • 0.05 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking (latest)
  • 0.05 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’… CLI::Framework

hi bestie!! welcome to CLI::Framework(3pm) β€” straight out of the User Contributed Perl Documentation collection. This is the whole vibe of a framework for building command-line apps, and honestly? she ate. Let's get into it 🫢


✨ NAME ✨

CLI::Framework β€” build standardized, flexible, testable command-line applications. that's it, that's the whole job description πŸ’…


🌸 OVERVIEW 🌸

CLI::Framework (we call her "CLIF", iykyk) hands you a framework and a whole conceptual pattern for building full-featured command line applications. The goal is to make that process simple and consistent. CLIF takes on the responsibility of implementing all the details that every command-line app has in common, so brand-new apps that follow well-defined conventions can be built without you having to rewrite the same command-line interface code over and over like a lil clown 🀑

Like, for instance β€” a complete application supporting commands and subcommands, with options and arguments for the app itself and for its commands, can be built by writing concise, understandable code in packages that are easy to test and maintain. The classes get to focus on implementing the unique aspects that are actually essential to the command's purpose, instead of being weighed down by all the details involved in building an interface around those commands. And bonus: this whole methodology for building command-line applications also establishes a valuable standard for an organization (or just one individual developer, we love a solo main character πŸ‘‘).


πŸ¦‹ LEARNING CLIF: RECOMMENDATIONS πŸ¦‹

CLIF has a rich set of features and offers so many alternative approaches to building applications, but if you're new here, you might want something short and sweet first. That's why CLI::Framework::Tutorial exists, and it's the recommended starting point. πŸ’–

Once you've got the basic understanding down, the other documents can be used as references.


πŸ”₯ MOTIVATION πŸ”₯

There are a few other distributions on CPAN intended to simplify building modular command line applications. I have not found any that meet my requirements β€” and those requirements are documented in DESIGN GOALS AND FEATURES. periodt.


⭐ DESIGN GOALS AND FEATURES ⭐

CLIF was designed to offer the following features... and bestie, it's a lot, and every single one is iconic:

  • A clear conceptual pattern for creating command-line applications
  • Guiding documentation and examples
  • Convenience for simple cases, flexibility for complex cases
  • Support for both non-interactive and interactive modes (with almost no additional work β€” define the necessary hooks and both modes will be supported)
  • A design that naturally encourages MVC applications: decouple data model, control flow, and presentation
  • Commands that can be shared between applications (and uploaded to CPAN)
  • The possibility to share some components with MVC web applications
  • Validation of application options
  • Validation of command options and arguments
  • A model that encourages easily-testable applications
  • A flexible means to provide usage/help information for the application as a whole and for individual commands
  • Support for subcommands that can be added as a natural extension to commands
  • Support for recursively-defined subcommands (sub-sub-...commands to any level of depth)
  • Support for aliases to commands and subcommands
  • Allow Application and [sub]commands to be defined inline (some or all packages involved may be defined in the same file) or split across multiple files
  • Support the concept of a default command for the application
  • Exception handling that allows individual applications to define custom exception handlers
  • Performance. Core framework code should load as quickly as a simple script; individual commands should be initialized only when invoked.

🧚 CONCEPTS AND DEFINITIONS 🧚

  • Application Script β€” The wrapper program that invokes the CLIF Application's run method. The file it is defined in may or may not also contain the definition of Application or Command packages.
  • Metacommand β€” An application-aware command. Metacommands are subclasses of CLI::Framework::Command::Meta. They are identical to regular commands except they hold a reference to the application within which they are running. This means they are able to "know about" and affect the application. For example, the built-in command Menu is a Metacommand because it needs to produce a list of the other commands in its application.

In general, your commands should be designed to operate independently of the application, so they should simply inherit from CLI::Framework::Command. This encourages looser coupling. However, in exceptional cases, the use of Metacommands is warranted (For an example, see the built-in Menu command).

  • Non-interactive Command β€” In interactive mode, some commands need to be disabled. For instance, the built-in console command (which is used to start interactive mode, presenting a command menu and responding to user selections) should not be presented as a menu option in interactive mode because it is already running. You can designate which commands are non-interactive by overriding the noninteractive_commands method.
  • Registration of commands β€” Each CLIF application defines the commands it will support. These may be built-in CLIF commands or custom CLIF commands. These commands are lazily "registered" as they are called upon for use.

πŸ‘‘ APPLICATION RUN SEQUENCE πŸ‘‘

When a command of the form:

$ app [app-opts] <cmd> [cmd-opts] { <cmd> [cmd-opts] {...} } [cmd-args]

examples:

        app      |             [app-opts]            { <cmd>       |   [cmd-opts]    } [cmd-args]

$ examples/queue |--qin=/tmp/qfile --qout=/tmp/qfile | enqueue | --tag=x --tag=y | 'item'

$ gen-report     |              --html               | stats       |  --role=admin   |
                 |                                   | usage       |   --time='2d'   | '/tmp/stats.html'

...causes your application script, `<app>`, to invoke the `run` method in your application class, `CLI::Framework::Application` performs the following actions:

1. Parse the command request
2. Validate application options
3. Initialize application
4. Prepare command
5. Invoke command pre-dispatch hook
6. Dispatch command

These steps are explained in more detail below...

## πŸ’« Request parsing πŸ’«

Parse the application options `[app-opts]`, command name `<cmd>`, command options `[cmd-opts]`, and the remaining part of the command line, which includes command arguments `[cmd-args]` for the last command and may include multiple subcommands. Everything between the inner brackets (`{ ... }`) represents recursive subcommand processing β€” the `...` represents another string of `<cmd> [cmd-opts] {...}`.

The second example above shows a command request that requires recursive subcommand processing. The command might cause an HTML report to be generated with usage statistics for admin users (of some application) for the past two days, writing the report to a file. In one line, it would look like this:

$ gen-report --html stats --role=admin usage --time='2d' '/tmp/stats.html'


This fictional `gen-report` application could be designed with such an interface because it could offer various types of reports (as opposed to the statistics report). There might be other statistics reports (as opposed to `'usage'`). The stats might be available for users with other roles. The usage report might need to accept custom time frames.

CLIF allows you to choose whether various parts of your data should be supplied as options or as arguments β€” these interface decisions are left to your discretion. CLIF also makes it easy to validate command requests and to provide usage information so users know what to change if a command request fails validation.

In general, if a command request is not well-formed, it is replaced with the default command and any arguments present are ignored. The default command prints a help or usage message (you may change this behavior if desired).

## 🌈 Validation of application options 🌈

Your application class can optionally define the `validate_options` method.

If your application class does not override this method, validation is skipped β€” any received options are considered to be valid. <pink>(no thoughts, head empty, everything is fine πŸ’…)</pink>

## πŸ“ Application initialization πŸ“

Your application class can optionally override the `init` method. This is a hook that can be used to perform any application-wide initialization that needs to be done independent of individual commands. For example, your application may use the `init` method to connect to a database and store a connection handle which may be needed by some or all of the commands in your application.

## πŸ’œ Preparing the command πŸ’œ

The requested command is now loaded (if not already done). The command's cache is set (using a reference to the same cache object used by the application).

## 🌸 Command pre-dispatch 🌸

Your application class can optionally have a `pre_dispatch` method that is called with one parameter: the Command object that is about to be dispatched.

## ⭐ Dispatching the command ⭐

CLIF uses the `dispatch` method to actually dispatch a specific command. That method is responsible for running the command or delegating responsibility to a subcommand, if applicable.

---

# πŸŽ€ INTERACTIVITY πŸŽ€

After building your CLIF application, in addition to basic non-interactive functionality, you will <rainbow>instantly</rainbow> benefit from the ability to (optionally) run your application in interactive mode. A readline-enabled application command console with an event loop, a command menu, and built-in debugging commands is provided by default. she's giving main character energy and she didn't even ask for it πŸ‘‘

Inside interactive mode, only steps <yellow>4</yellow>, <yellow>5</yellow>, and <yellow>6</yellow> above (<cyan>APPLICATION RUN SEQUENCE</cyan>) are performed for each command request.

Supporting interactivity in your application is as simple as adding the built-in command `CLI::Framework::Command::Console` to your `command_map`. that's it. that's the whole thing. slay 🫢

# πŸŽ€ BUILT-IN COMMANDS INCLUDED IN THIS DISTRIBUTION πŸŽ€

okay so this distro ships with some default built-in commands, and bestie, more CLIF built-ins can be installed as they show up on CPAN πŸ’–

Using the built-ins is optional in most cases, but like… certain features **require** specific built-in commands (for example, the <cyan>Help</cyan> command is a fundamental feature of all applications, and the <cyan>Menu</cyan> command is required in interactive mode). Also you can override **any** of the built-ins. Slay, it's your app πŸ‘‘

A new application that doesn't override the `command_map` hook will include all of the built-ins listed below.

The existing built-ins and their corresponding packages are as follows:

- **`help`** β€” Print application or command-specific usage messages
  - `CLI::Framework::Command::Help`
  - > Note: This command is registered automatically. All CLIF applications **must** have the `"help"` command defined (though this built-in can be replaced by your subclass to change the `"help"` command behavior, or to do nothing if you specifically do not want a help command). πŸ™ˆ

- **`list`** β€” Print a list of commands available to the running application
  - `CLI::Framework::Command::List`

- **`dump`** β€” Show the internal state of a running application
  - `CLI::Framework::Command::Dump`

- **`tree`** β€” Display a tree representation of the commands that are currently registered with the running application
  - `CLI::Framework::Command::Tree`

- **`alias`** β€” Display the command aliases that are in effect for the running application and its commands
  - `CLI::Framework::Command::Alias`

- **`console`** β€” Invoke CLIF's interactive mode
  - `CLI::Framework::Command::Console`

- **`menu`** β€” Show a command menu including the commands that are available to the running application
  - `CLI::Framework::Command::Menu`
  - > Note: This command is registered automatically when an application runs in interactive mode. This built-in may be replaced by a user-defined `"menu"` command, but any command class to be used for the `"menu"` command **MUST** be a subclass of this one. πŸ’…

---

# ✨ CLIF ARCHITECTURE AT A GLANCE ✨

The class diagram below shows the relationships of the major classes of CLI Framework, including some of their methods. This is not intended to be a comprehensive diagram, only an aid to understanding CLIF at a glance. πŸ¦‹

> <lavender>just a lil visual map of the whole vibe, no cap β€” think of it as the group photo of all the classes πŸ“Έ</lavender>

---

# πŸ‘€ SEE ALSO πŸ‘€

- `CLI::Framework::Application`
- `CLI::Framework::Command`
- `CLI::Framework::Tutorial`

---

# πŸ“œ LICENSE AND COPYRIGHT πŸ“œ

Copyright (c) 2009 Karl Erisman (`kerisman@cpan.org`). All rights reserved.

This is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See `perlartistic`. 🌸

---

# πŸ’– AUTHOR πŸ’–

Karl Erisman (`kerisman@cpan.org`)

---

<purple>and that's the whole page, bestie β€” you officially know CLIF now, no cap 🧚 this was `perl v5.34.0`, dated `2022-06-11`, from `CLI::Framework(3pm)`. go build something iconic with it, mwah πŸ’…βœ¨</purple>
πŸ“¦ where this page comes from