Skip to content

Repository files navigation

TinyCLI

TinyCLI is a command line interface for embedded systems that is intended to be very easy to use. Typical applications include providing a simple CLI over a serial line or a Telnet connection.

Sample

Features

  • No dynamic allocations.
  • Configurable prompt(s).
  • Output buffering.
  • Command history in a ring buffer.
  • Backwards history search.
  • Tab-completion.
  • Custom SIGINT handler.
  • Functions for printing log data without disturbing the prompt.

History and output buffering can be disabled to reduce memory usage on smaller systems.

Wrapper Extensions (tclie)

  • Extension functions for automatic handling of users, commands and tab-completion.
  • Optional pattern matching system:
    • Automatic validation of command syntax and command options.
    • Context-sensitive tab-completion.
  • Default commands (help, clear, login, and logout).

Users can be registered so that only certain commands are available to certain users. Login is possible with either password only or with usernames and optional passwords. Only users with a level matching the minimum required level for a command can execute the command.

Each command is registered with a name, the minimum user level required (if users are enabled), a description, and optionally a pattern with some options (if pattern matching is enabled). The description, along with any pattern and options (if used), is automatically printed when the built-in help command is called.

Pattern Matching

The following syntax can be used in patterns:

PatternDescription
abcMatches abc.
"a b" or 'a b'Matches a b including whitespace.
[abc]Optionally matches abc.
a|b|cdMatches a, b or cd.
<abc>Wildcard; matches any word.
[<abc>]Optional wildcard; optionally matches any word.
a|(b c) or a|{b c}Matches a or b c.
...Matches none or all remaining tokens.
  • The pattern matching system currently only supports matching word-tokens (i.e. no matches inside words).
  • The pattern matcher is recursive and stack requirements will increase with pattern complexity.

Usage

  1. Define output function and initialize:
#include"tclie.h"voidout(void*arg, constchar*str)
{
printf("%s", str); // Or send through serial interface
}
tclie_tt;
tclie_init(&t, out, NULL);
  1. Register user table (if needed):
staticconsttclie_user_tusers[] = {
{ .name="debug", .password=NULL, .level=1 }, // No password required
{ .name="admin", .password="12345", .level=2 },
};
tclie_reg_users(&t, users, sizeof(users) / sizeof(*users));
  1. Register command table:
intcmd_echo(void*arg, intargc, constchar**argv)
{
for (inti=1; i<argc; i++)
printf("%s%s", argv[i], i+1<argc ? " " : "\r\n");
return0;
}
staticconsttclie_cmd_tcmds[] = {
{ .name="echo", .fn=cmd_echo, .min_user_level=1, .desc="Echo input." },
};
tclie_reg_cmds(&t, cmds, sizeof(cmds) / sizeof(*cmds));
  1. Feed input characters:
intc;
while ((c=getchar()) !=EOF) // Read e.g. serial inputtclie_in_char(&t, (char) c);

See the examples directory for more details.

Logging

The log functions print without disturbing the prompt:

tclie_log(&t, "Some message...\r\n");
charbuf[64];
tclie_log_printf(&t, buf, sizeof(buf), "Hello %s\r\n", "world!");

Supported Keyboard Shortcuts

ShortcutDescription
Ctrl+aMove cursor to line start.
Ctrl+bMove cursor back one character.
Ctrl+cSends SIGINT to registered handler.
Ctrl+dDelete current character.
Ctrl+eMove cursor to line end.
Ctrl+fMove cursor forward one character.
Ctrl+gExit reverse search mode.
Ctrl+hDelete previous character.
Ctrl+iEquivalent to the tab key.
Ctrl+jEquivalent to the enter key.
Ctrl+kClear line after cursor.
Ctrl+lClear screen content.
Ctrl+nRecall next command.
Ctrl+pRecall previous command.
Ctrl+rReverse search through command history.
Ctrl+uClear line before cursor.
Ctrl+wClear word before cursor.
Alt+bMove cursor backward one word.
Alt+dDelete word after cursor.
Alt+fMove cursor forward one word.
Alt+rCancel changes to history line.
TabTab-complete at cursor or select from multiple matches.
EscExit tab-completion or reverse search mode.

Note

Esc needs to be pressed twice since it is impossible to differentiate from an escape sequence otherwise.

Miscellaneous

Telnet

Telnet newlines (<CR><NUL>) are automatically handled, but it may be necessary to tell connecting clients (e.g. PuTTY) how to behave. This can be done by sending the following sequences to the client:

  • IAC DO ECHO: Tell client to echo received characters from server.
  • IAC WILL ECHO: Tell client that the server will echo back received characters.
  • IAC DO SUPPRESS-GO-AHEAD: Tell client to not send GO AHEAD when transmitting.
  • IAC WILL SUPPRESS-GO-AHEAD: Tell client that the server won't send GO AHEAD when transmitting.
constunsigned charoptions[] = {255, 253, 1, // IAC DO ECHO255, 251, 1, // IAC WILL ECHO255, 253, 3, // IAC DO SUPPRESS-GO-AHEAD255, 251, 3}; // IAC WILL SUPPRESS-GO-AHEAD

About

Tiny command line interface for embedded systems

Topics

Resources

Stars

11 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages