cyclecmd

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2025 License: Apache-2.0 Imports: 6 Imported by: 0

README

cyclecmd

Description

cyclecmd helps you to write console applications based on events that are triggered by user input. It is an unopinionated library, thus you can define events in any way that you need.

How to get it

You can get cyclecmd with the following command:

go get github.com/RaphSku/cyclecmd@latest

How to use it

First, define a default event that will be triggered whenever user input doesn't match any other registered event. In this example, the default event will simply print the user's input (referred to as the "token").

type DefaultEvent struct{}

func (de *DefaultEvent) Handle(token string) (error, *cyclecmd.ControlEvent) {
	fmt.Print(token)
	return nil
}

Note, that all events have to comply with the following interface:

type Event interface {
    Handle(token string) (error, *ControlEvent)
}

Additionally, every Handle function returns an error and a ControlEvent, which can be used to instruct cyclecmd to trigger a specific event that may alter the application's flow. In the current version, however, the only available control event is for terminating the application (via the constant CYCLE_TERMINATE). The default event is the only required event, as it serves to initialize the event registry and ensure there's always a fallback handler for unrecognized input:

defaultEventInformation := cyclecmd.EventInformation{
    EventName: "Default",
    Event:     &DefaultEvent{},
}
eventRegistry := cyclecmd.NewEventRegistry(defaultEventInformation)

For demonstration purposes, let us register another event, the backspace event that will print a backspace for us.

type BackspaceEvent struct{}

func (be *BackspaceEvent) Handle(token string) (error, *cyclecmd.ControlEvent) {
	fmt.Print("\b \b")
	return nil
}

backspaceEventInformation := cyclecmd.EventInformation{
    EventName: "Backspace",
    Event:     &BackspaceEvent{},
}
eventRegistry.RegisterEvent("\x7f", backspaceEventInformation)

Next, we need to initialize the event history, this is relatively simple:

eventHistory := cyclecmd.NewEventHistory()

And with the event registry and event history we can finally initialise our console app and let it run and handle our custom events.

consoleApp := cyclecmd.NewConsoleApp(
    "Test",
    "v0.1.0",
    "Example description...",
    eventRegistry,
    eventHistory,
)
consoleApp.SetLineDelimiter("\n\r>>> ", "\x7f")
consoleApp.Start()

Note that you can also set a line delimiter—for example, "\n\r>>> " in this case. If you want each new line to begin with >>>, be sure to include "\n\r" in the delimiter. This design is intentional, allowing you to customize the delimiter freely, even omitting new lines if needed. Finally, calling the Start() method begins the event loop.

Example Projects

If you want to see a complete example on how to leverage cyclecmd, please have a look at the following projects that use cyclecmd:

Documentation

Overview

Package cyclecmd is an unopinionated library for building your own console applications.

Index

Constants

View Source
const (
	// CYCLE_TERMINATE is a flag indicating the termination event.
	// It has the integer value 1.
	CYCLE_TERMINATE int = 1
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ConsoleApp

type ConsoleApp struct {

	// Name of the console application
	Name string
	// Version of the console application
	Version string
	// Description of the console application. Should be relatively short.
	Description string
	// Delimiter can be used to visibly separate lines in your console application.
	// But the usage is flexible.
	Delimiter string
	// DelimiterEventTrigger defines when a Delimiter will be printed.
	DelimiterEventTrigger string
	// contains filtered or unexported fields
}

ConsoleApp handles all the events in an event loop and serves as an entry point for your console.

func NewConsoleApp

func NewConsoleApp(
	name string,
	version string,
	description string,
	eventRegistry *EventRegistry,
	eventHistory *EventHistory,
) *ConsoleApp

NewConsoleApp initializes a new Console App instance that will be the main entry point to your console application or to be more specific, to the event loop that will handle the custom events.

Parameters:

  • `name` : Name of the Console App
  • `version` : Version of the Console App
  • `description` : Description of the Console App. Should be relatively short
  • `eventRegistry` : The single source of truth for custom events that were registered
  • `eventHistory` : Records events that were processed

Returns:

  • `*ConsoleApp` : An instance of a Console Application

func (*ConsoleApp) ChangeToDebugMode

func (ca *ConsoleApp) ChangeToDebugMode()

ChangeToDebugMode allows you to switch to debug mode for logging. Don't forget to switch off debug mode once you want to ship your console app to production since all logs will be otherwise shown.

func (*ConsoleApp) SetLineDelimiter

func (ca *ConsoleApp) SetLineDelimiter(delimiter string, eventTrigger string)

SetLineDelimiter allows the User to define a custom delimiter that will be printed after each event that is defined by eventTrigger.

Parameters:

  • `delimiter` : Delimiter should be fairly short
  • `eventTrigger` : Delimiter will be printed after each event that is triggered by eventTrigger

func (*ConsoleApp) Start

func (ca *ConsoleApp) Start()

Start will save the terminal state, handle terminating signals and kick off the event loop. Note, events are recorded in the event history before the event handling happens. They are recorded as they occur.

type ControlEvent added in v0.2.0

type ControlEvent struct {
	Terminate bool
}

ControlEvent represents control signals with boolean flags.

Currently, it contains a single flag:

  • Terminate: true if the termination flag is set.

func NewControlEvent added in v0.2.0

func NewControlEvent(flags int) *ControlEvent

NewControlEvent creates a new ControlEvent from the given flags integer.

It checks if the TERMINATE bit is set in the flags and sets the Terminate field accordingly.

Parameters:

  • `flags` : A number of control events whose bit should be set

Returns:

  • `*ControlEvent` : A ControlEvent structure that captures all the control events that are activated or deactivated

type Event

type Event interface {
	Handle(token string) (error, *ControlEvent)
}

Event is an interface that defines the behavior of the custom events that the User can define themselves.

Event expects the following method to be implemented by all events:

Behavior:

  • `Handle(token string) (error, *ControlEvent)` : it expects the token that is associated with the event

type EventHistory

type EventHistory struct {
	// contains filtered or unexported fields
}

EventHistory records events and offers behavior to manipulate the history and to read events from history.

func NewEventHistory

func NewEventHistory() *EventHistory

NewEventHistory initialises an event history instance that can be used to record past events.

Returns:

  • `*EventHistory` : Returns an instance of EventHistory

func (*EventHistory) AddEvent

func (eh *EventHistory) AddEvent(eventEntry EventHistoryEntry)

AddEvent will add an event to the history.

Parameters:

  • `eventEntry` : Entry that will be recorded and contains all information related to an event.

func (*EventHistory) GetLastEventsFromHistoryToEventReference

func (eh *EventHistory) GetLastEventsFromHistoryToEventReference(eventName string) []string

GetLastEventsFromHistoryToEventReference will return all event names that followed after a specific event happened.

Parameters:

  • `eventName` : The name of the event that serves as a reference

Returns:

  • `[]string` : Returns a series of event names that happened after the reference event

func (*EventHistory) Len

func (eh *EventHistory) Len() int

Len returns the number of events that has been recorded.

Returns:

  • `int` : Number of events

func (*EventHistory) MostRecentSpliceEventsOfHistory

func (eh *EventHistory) MostRecentSpliceEventsOfHistory(eventName string) []EventHistoryEntry

MostRecentSpliceEventsOfHistory will return a range of events that occured between some event that is specified by eventName.

Parameters:

  • `eventName` : Name of the reference event

Returns:

  • `[]EventHistoryEntry` : Sequence of event history entries

func (*EventHistory) PrintLastEventHistoryEntries

func (eh *EventHistory) PrintLastEventHistoryEntries(n int)

PrintLastEventHistoryEntries will print information related to the last n events that were recorded.

Parameters:

  • `n` : Number of events

func (*EventHistory) RemoveNthEventFromHistory

func (eh *EventHistory) RemoveNthEventFromHistory(n int)

RemoveNthEventFromHistory removes the nth event from the history. If the nth element does not exist, nothing will happen.

Parameters:

  • `n` : nth event that should be removed from history

func (*EventHistory) RetrieveEventEntryByIndex

func (eh *EventHistory) RetrieveEventEntryByIndex(index int) (EventHistoryEntry, error)

RetrieveEventEntryByIndex will return the event entry at index position

Parameters:

  • `index` : Position in the event history that you want to access

Returns:

  • `EventHistoryEntry` : The event history entry at index position
  • `error` : Returns an error when there is no event history entry at position index

type EventHistoryEntry

type EventHistoryEntry struct {
	// Token is the same as event trigger
	Token string
	// The name of the event
	EventName string
	// The event instance itself
	Event Event
}

EventHistoryEntry stores the event and the event name but also the token that triggered the event. This is especially useful for the DefaultEvent since that event gets triggered by every token that is not already registered with another event.

type EventInformation

type EventInformation struct {
	// Name of the event
	EventName string
	// The event instance itself
	Event Event
}

EventInformation stores the event itself but also the event name that was given to the custom event.

type EventRegistry

type EventRegistry struct {

	// DefaultEventInformation contains information related to the default event that is triggered whenever
	// a token does not match with any other event that is registered.
	DefaultEventInformation EventInformation
	// contains filtered or unexported fields
}

EventRegistry contains all related information with custom events that are registered with this registry.

func NewEventRegistry

func NewEventRegistry(defaultEventInformation EventInformation) *EventRegistry

NewEventRegistry initialises the event registry.

Parameters:

  • `defaultEventInformation` : Information related to the default event

Returns:

  • `*EventRegistry` : Returns an instance of the event registry

func (*EventRegistry) GetMatchingEventInformation

func (er *EventRegistry) GetMatchingEventInformation(eventTrigger string) (EventInformation, error)

GetMatchingEventInformation retrieves the information related to the event that gets triggered by `eventTrigger`. The default event is returned when the event trigger matches no event registered in the event registry.

Parameters:

  • `eventTrigger` : Trigger for the event that should be returned

Returns:

  • `EventInformation` : Information related to the event triggered by `eventTrigger`
  • `error` : An error is only returned when no default event is defined

func (*EventRegistry) RegisterEvent

func (er *EventRegistry) RegisterEvent(eventTrigger string, eventInformation EventInformation) error

RegisterEvent registers an event with an event trigger.

Parameters:

  • `eventTrigger` : Trigger that will kick off the event
  • `eventInformation` : Information related to the event that will be triggered by `eventTrigger`

Returns:

  • `error` : Returns an error when the event is already registered

func (*EventRegistry) ResetEventRegistry

func (er *EventRegistry) ResetEventRegistry()

ResetEventRegistry resets the event registry, so all registered events are deleted from the registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL