Creating a simple CLI application with glaze

Documentation index for Glazed v1.3.5, with 77 sections.

Sections

Terminology & Glossary
📖 Documentation
Navigation
77 sectionsv0.1
📄 Creating a simple CLI application with glaze — glaze help a-simple-table-cli
a-simple-table-cli

Creating a simple CLI application with glaze

Tutorialglaze

The goal is to create a command called ExampleCommand that generates a specified number of rows of data. Each row will have an id and name field, and optionally a test field if a flag is set. The rows are then added to a Processor for output.

2. APIs Used

  • CommandDescription: This struct is used to describe the command. It includes the name of the command, a short description, and any flags or arguments the command takes.
  • Definition: This struct is used to define the fields (flags or arguments) that the command takes. It includes the name of the field, the type, and any default value.
  • Command and GlazeCommand: These interfaces define the methods that a command must implement. The Run method is where the main functionality of the command is implemented.
  • Row: This struct represents a row of data. It can have any number of fields, each with a name and value.

3. Creating the Command

First, we create a new struct that embeds the Command interface. We also add a description field of type *CommandDescription.

type ExampleCommand struct {
	*cmds.CommandDescription
}

Next, we create a constructor function for ExampleCommand. In this function, we initialize the description field using the NewCommandDescription function, passing in the name of the command, a short description, and any flags or arguments the command takes.

func NewExampleCommand() (*ExampleCommand, error) {
	return &ExampleCommand{
		CommandDescription: cmds.NewCommandDescription(
			"example",
			cmds.WithShort("Example command"),
			cmds.WithFlags(
				fields.New(
					"count",
					fields.TypeInteger,
					fields.WithHelp("Number of rows to output"),
					fields.WithDefault(10),
				),
				fields.New(
					"test",
					fields.TypeBool,
					fields.WithHelp("Whether to add a test column"),
					fields.WithDefault(false),
				),
			),
		),
	}, nil
}

4. Implementing the Run Method

The Run method is where the main functionality of the command is implemented. In this method, we first retrieve the values of the count and test flags. Then, we generate count number of rows, each with an id and name field. If test is true, we also add a test field with a random integer between 1 and 100. Finally, we add the rows to the Processor for output.

func (c *ExampleCommand) Run(
	ctx context.Context,
	parsedSections map[string]*sections.ParsedSection,
	ps map[string]interface{},
	gp middlewares.Processor,
) error {
	count := ps["count"].(int)
	test := ps["test"].(bool)

	for i := 0; i < count; i++ {
		row := types.NewRow(
			types.MRP("id", i),
			types.MRP("name", "foobar-"+strconv.Itoa(i)),
		)

		if test {
			row.Set("test", rand.Intn(100)+1)
		}

		if err := gp.AddRow(ctx, row); err != nil {
			return err
		}
	}

	return nil
}

5. Extending the Command

There are many ways you could extend this command. Here are a few ideas:

  • Add more flags to customize the output, such as a flag to set the prefix of the name field.
  • Add error handling to ensure the count flag is a positive integer.
  • Add a flag to specify the range of the random integer for the test field.
  • Instead of generating random data, read data from a file (see the types StringFromFile and StringListFromFile)