-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[shell] Reduce memory usage and boileplate code for subcommands
1. Add lightweight CommandSet class to prevent instantiating Shell::Engine, which allows for dynamic command registration, just to create a subshell with a fixed number of subcommands. This slightly reduces the RAM usage. Additionally, the command set automatically prints the help texts if no command or "help" command has been submitted. 2. Add SubShellCommand templatized command handler to remove the boilerplate associated with creating a subshell.
- Loading branch information
1 parent
f4e02d4
commit 47b8d45
Showing
15 changed files
with
297 additions
and
252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <lib/support/Span.h> | ||
|
||
namespace chip { | ||
namespace Shell { | ||
|
||
/** | ||
* Shell command descriptor structure. | ||
* | ||
* Typically a set of commands is defined as an array of this structure and registered | ||
* at the shell root using the @c Shell::Engine::Root().RegisterCommands() method, or | ||
* used to construct a @c CommandSet. | ||
* | ||
* Usage example: | ||
* | ||
* @code | ||
* static Shell::Command cmds[] = { | ||
* { &cmd_echo, "echo", "Echo back provided inputs" }, | ||
* { &cmd_exit, "exit", "Exit the shell application" }, | ||
* { &cmd_help, "help", "List out all top level commands" }, | ||
* { &cmd_version, "version", "Output the software version" }, | ||
* }; | ||
* @endcode | ||
*/ | ||
struct Command | ||
{ | ||
/** | ||
* Shell command handler function type. | ||
* | ||
* @param argc Number of arguments in argv. | ||
* @param argv Array of arguments in the tokenized command line to execute. | ||
*/ | ||
using Handler = CHIP_ERROR (*)(int argc, char * argv[]); | ||
|
||
Handler cmd_func; | ||
const char * cmd_name; | ||
const char * cmd_help; | ||
}; | ||
|
||
// DEPRECATED: | ||
// shell_command_t is used in many examples, so keep it for backwards compatibility | ||
using shell_command_t = const Command; | ||
|
||
} // namespace Shell | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <lib/shell/CommandSet.h> | ||
#include <lib/shell/streamer.h> | ||
#include <lib/support/CodeUtils.h> | ||
|
||
namespace chip { | ||
namespace Shell { | ||
|
||
CHIP_ERROR CommandSet::ExecCommand(int argc, char * argv[]) const | ||
{ | ||
if (argc == 0 || strcmp(argv[0], "help") == 0) | ||
{ | ||
ShowHelp(); | ||
return CHIP_NO_ERROR; | ||
} | ||
|
||
for (const Command & command : mCommands) | ||
{ | ||
if (strcmp(argv[0], command.cmd_name) == 0) | ||
{ | ||
return command.cmd_func(argc - 1, argv + 1); | ||
} | ||
} | ||
|
||
return CHIP_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
void CommandSet::ShowHelp() const | ||
{ | ||
for (const Command & command : mCommands) | ||
{ | ||
streamer_printf(streamer_get(), " %-15s %s\r\n", command.cmd_name, command.cmd_help); | ||
} | ||
} | ||
|
||
} // namespace Shell | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <lib/shell/Command.h> | ||
#include <lib/support/Span.h> | ||
|
||
namespace chip { | ||
namespace Shell { | ||
|
||
/** | ||
* Shell command set. | ||
* | ||
* The shell command set is a thin wrapper for the span of commands. | ||
* It facilitates executing a matching shell command for the given input arguments. | ||
*/ | ||
class CommandSet | ||
{ | ||
public: | ||
template <size_t N> | ||
constexpr CommandSet(const Command (&commands)[N]) : mCommands(commands) | ||
{} | ||
|
||
/** | ||
* Dispatch and execute the command for the given argument list. | ||
* | ||
* The first argument is used to select the command to be executed and | ||
* the remaining arguments are forwarded to the command's handler. | ||
* If no argument has been provided or the first argument is "help", then | ||
* the function prints help text for each command and returns no error. | ||
* | ||
* @param argc Number of arguments in argv. | ||
* @param argv Array of arguments in the tokenized command line to execute. | ||
*/ | ||
CHIP_ERROR ExecCommand(int argc, char * argv[]) const; | ||
|
||
private: | ||
void ShowHelp() const; | ||
|
||
Span<const Command> mCommands; | ||
}; | ||
|
||
} // namespace Shell | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <lib/shell/CommandSet.h> | ||
|
||
namespace chip { | ||
namespace Shell { | ||
|
||
/** | ||
* Templatized shell command handler that runs one of the provided subcommands. | ||
* | ||
* The array of subcommands is provided as a non-type template parameter. | ||
* | ||
* The first argument is used to select the subcommand to be executed and | ||
* the remaining arguments are forwarded to the subcommand's handler. | ||
* If no argument has been provided or the first argument is "help", then | ||
* the function prints help text for each subcommand and returns no error. | ||
* | ||
* Usage example: | ||
* @code | ||
* constexpr Command subCommands[3] = { | ||
* {handler_a, "cmd_a", "command a help text"}, | ||
* {handler_b, "cmd_b", "command b help text"}, | ||
* {handler_c, "cmd_c", "command c help text"}, | ||
* }; | ||
* | ||
* // Execute the matching subcommand | ||
* SubShellCommand<3, subCommands>(argc, argv); | ||
* @endcode | ||
* | ||
* @param argc Number of arguments in argv. | ||
* @param argv Array of arguments in the tokenized command line to execute. | ||
*/ | ||
template <size_t N, const Command (&C)[N]> | ||
inline CHIP_ERROR SubShellCommand(int argc, char ** argv) | ||
{ | ||
static constexpr CommandSet commandSet(C); | ||
|
||
return commandSet.ExecCommand(argc, argv); | ||
} | ||
|
||
} // namespace Shell | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.