MaCh3  2.6.1
Reference Guide
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
M3::MaCh3Program Class Reference

Main program class that manages modules, plugins, and command-line parsing. More...

#include <CLI/MaCh3Program.hpp>

Inheritance diagram for M3::MaCh3Program:
[legend]
Collaboration diagram for M3::MaCh3Program:
[legend]

Public Member Functions

virtual ~MaCh3Program ()
 Destructor that unloads all dynamic plugins. More...
 
void add_core_module (IModule &module)
 Add a core module to the program. More...
 
void load_dynamic_plugins ()
 Load dynamic plugins from the MACH3_PLUGINS environment variable. More...
 
void install_completions () const
 Install shell completion scripts for bash and zsh. More...
 
void completions (const std::string &prefix) const
 Generate completion suggestions for the given prefix. More...
 
void unload_dynamic_plugins ()
 Unload all dynamically loaded plugins. More...
 
int Run ()
 Run the selected subcommand. More...
 
- Public Member Functions inherited from M3::MaCh3ArgumentParser
virtual ~MaCh3ArgumentParser ()=default
 
const std::string name () const
 Get the name of this parser/subcommand. More...
 
const std::list< std::reference_wrapper< ArgumentParser > > & subparsers () const
 Get the list of registered subparsers. More...
 
const MaCh3ArgumentParserget_subcommand_used () const
 Get the subcommand that was used in parsing. More...
 

Private Member Functions

std::string detect_shell () const
 Detect the user's shell from the SHELL environment variable. More...
 
bool write_file (const fs::path &path, std::string_view content) const
 Write content to a file, creating parent directories if needed. More...
 
std::vector< std::string > expand_plugin_path (const std::string &path) const
 Expand a plugin path (file or directory) into a list of .so files. More...
 

Private Attributes

std::vector< std::string > m_subcommands
 List of registered subcommand names. More...
 
std::map< const MaCh3ArgumentParser *, IModule * > m_module_map
 Map of parsers to core modules (non-owning) More...
 
std::map< const MaCh3ArgumentParser *, std::unique_ptr< DynamicPlugin > > m_dynamic_plugin_map
 Map of parsers to dynamic plugins (owning) More...
 

Static Private Attributes

static constexpr std::string_view BASH_COMPLETION
 
static constexpr std::string_view ZSH_COMPLETION
 

Detailed Description

Main program class that manages modules, plugins, and command-line parsing.

This class extends MaCh3ArgumentParser to provide functionality for:

Author
Alexander Richards

Definition at line 26 of file MaCh3Program.hpp.

Constructor & Destructor Documentation

◆ ~MaCh3Program()

virtual M3::MaCh3Program::~MaCh3Program ( )
inlinevirtual

Destructor that unloads all dynamic plugins.

Definition at line 31 of file MaCh3Program.hpp.

31  {
32  //std::cout<<"UNLOADED"<< std::endl;
33  this->unload_dynamic_plugins();
34  }
void unload_dynamic_plugins()
Unload all dynamically loaded plugins.

Member Function Documentation

◆ add_core_module()

void M3::MaCh3Program::add_core_module ( IModule module)

Add a core module to the program.

Parameters
moduleReference to the module to be added

Definition at line 104 of file MaCh3Program.cpp.

104  {
105  MaCh3ArgumentParser* parser = module.get_parser();
106  this->add_subparser(*parser);
107  m_module_map[parser] = &module;
108  m_subcommands.push_back(parser->name());
109  }
std::vector< std::string > m_subcommands
List of registered subcommand names.
std::map< const MaCh3ArgumentParser *, IModule * > m_module_map
Map of parsers to core modules (non-owning)

◆ completions()

void M3::MaCh3Program::completions ( const std::string &  prefix) const

Generate completion suggestions for the given prefix.

Parameters
prefixThe prefix string to match against available subcommands

Definition at line 70 of file MaCh3Program.cpp.

70  {
71  for (const std::string& cmd : m_subcommands) {
72  if (cmd.rfind(prefix, 0) == 0)
73  std::cout << cmd << "\n";
74  }
75  }

◆ detect_shell()

std::string M3::MaCh3Program::detect_shell ( ) const
private

Detect the user's shell from the SHELL environment variable.

Returns
Shell name ("bash", "zsh", or empty string if not detected)

Definition at line 28 of file MaCh3Program.cpp.

28  {
29  const char* shell = std::getenv("SHELL");
30  if (!shell) return "";
31 
32  std::string s(shell);
33  if (s.find("bash") != std::string::npos) return "bash";
34  if (s.find("zsh") != std::string::npos) return "zsh";
35 
36  return "";
37  }

◆ expand_plugin_path()

std::vector< std::string > M3::MaCh3Program::expand_plugin_path ( const std::string &  path) const
private

Expand a plugin path (file or directory) into a list of .so files.

Expand a plugin path to a list of shared library files.

Parameters
pathPath to a plugin file or directory containing plugins
Returns
Vector of plugin file paths

If the path is a file, returns it directly. If it's a directory, returns all .so files found in that directory.

Parameters
pathPath to a plugin file or directory
Returns
Vector of absolute paths to .so files

Definition at line 189 of file MaCh3Program.cpp.

189  {
190  std::vector<std::string> result;
191 
192  fs::path p(path);
193 
194  if (!fs::exists(p)) {
195  std::cerr << "Plugin path does not exist: " << path << "\n";
196  return result;
197  }
198 
199  if (fs::is_regular_file(p)) {
200  // Single .so file
201  result.push_back(path);
202  }
203  else if (fs::is_directory(p)) {
204  // Load all .so files in directory
205  for (auto& entry : fs::directory_iterator(p)) {
206  if (entry.is_regular_file() && entry.path().extension() == ".so") {
207  result.push_back(entry.path().string());
208  }
209  }
210  }
211  else {
212  std::cerr << "Invalid plugin path (not file or directory): " << path << "\n";
213  }
214 
215  return result;
216  }

◆ install_completions()

void M3::MaCh3Program::install_completions ( ) const

Install shell completion scripts for bash and zsh.

Definition at line 39 of file MaCh3Program.cpp.

39  {
40  const char* home = std::getenv("HOME");
41  if (!home) {
42  std::cerr << "Cannot determine HOME directory\n";
43  return;
44  }
45 
46  std::string shell = detect_shell();
47  if (shell.empty()) {
48  std::cerr << "Could not detect your shell. Supported: bash, zsh\n";
49  return;
50  }
51 
52  fs::path home_path(home);
53 
54  if (shell == "bash") {
55  fs::path path = home_path / ".local/share/bash-completion/completions/mach3";
57  std::cout << "Installed bash completions → " << path << "\n";
58  return;
59  }
60 
61  if (shell == "zsh") {
62  fs::path path = home_path / ".local/share/zsh/site-functions/_mach3";
64  std::cout << "Installed zsh completions → " << path << "\n";
65  return;
66  }
67 
68  }
bool write_file(const fs::path &path, std::string_view content) const
Write content to a file, creating parent directories if needed.
static constexpr std::string_view ZSH_COMPLETION
static constexpr std::string_view BASH_COMPLETION
std::string detect_shell() const
Detect the user's shell from the SHELL environment variable.

◆ load_dynamic_plugins()

void M3::MaCh3Program::load_dynamic_plugins ( )

Load dynamic plugins from the MACH3_PLUGINS environment variable.

Load dynamic plugins from paths specified in MACH3_PLUGINS environment variable.

Reads the MACH3_PLUGINS environment variable (colon-separated paths), loads each .so file, and registers the plugins with the program. Each plugin must export create_plugin and destroy_plugin functions.

Definition at line 116 of file MaCh3Program.cpp.

116  {
117  const char* env = std::getenv("MACH3_PLUGINS");
118  if (!env) {
119  //std::cerr << "No plugins specified\n";
120  return;
121  }
122 
123  std::stringstream ss(env);
124  std::string path;
125 
126  while (std::getline(ss, path, ':')) {
127  for (const auto& sofile : this->expand_plugin_path(path)) {
128  try{
129  std::unique_ptr<DynamicPlugin> dlplugin = std::make_unique<DynamicPlugin>(sofile);
130  MaCh3ArgumentParser* parser = dlplugin->get_parser();
131  if (!parser) {
132  std::cerr << "Plugin " << sofile << " did not provide a valid parser.\n";
133  continue;
134  }
135 
136  this->add_subparser(*parser);
137  m_dynamic_plugin_map[parser] = std::move(dlplugin);
138  m_subcommands.push_back(parser->name());
139  }
140  catch (const std::exception& e) {
141  std::cerr << "Failed to load plugin from " << sofile << ": " << e.what() << "\n";
142  continue;
143  }
144  catch (...) {
145  std::cerr << "Failed to load plugin from " << sofile << ": unknown error\n";
146  continue;
147  }
148  }
149  }
150  }
std::map< const MaCh3ArgumentParser *, std::unique_ptr< DynamicPlugin > > m_dynamic_plugin_map
Map of parsers to dynamic plugins (owning)
std::vector< std::string > expand_plugin_path(const std::string &path) const
Expand a plugin path (file or directory) into a list of .so files.

◆ Run()

int M3::MaCh3Program::Run ( )

Run the selected subcommand.

Execute the selected subcommand.

Returns
Exit code from the executed module

Determines which subcommand was invoked and runs the corresponding module or plugin.

Returns
Exit code from the executed module (0 on success)

Definition at line 164 of file MaCh3Program.cpp.

164  {
165 
166  const MaCh3ArgumentParser& sub_parser = this->get_subcommand_used();
167 
168  if (sub_parser){
169  auto plugin_itr = m_module_map.find(&sub_parser);
170  if (plugin_itr != m_module_map.end()){
171  return plugin_itr->second->Run();
172  }
173  auto dplugin_itr = m_dynamic_plugin_map.find(&sub_parser);
174  if (dplugin_itr != m_dynamic_plugin_map.end()){
175  return dplugin_itr->second->Run();
176  }
177  }
178  return 0;
179  }
const MaCh3ArgumentParser & get_subcommand_used() const
Get the subcommand that was used in parsing.
Definition: m3argparse.hpp:40

◆ unload_dynamic_plugins()

void M3::MaCh3Program::unload_dynamic_plugins ( )

Unload all dynamically loaded plugins.

Unload all dynamic plugins and clean up resources.

Clears the plugin map. Smart pointers automatically handle cleanup.

Definition at line 155 of file MaCh3Program.cpp.

155  {
156  m_dynamic_plugin_map.clear();
157  }

◆ write_file()

bool M3::MaCh3Program::write_file ( const fs::path &  path,
std::string_view  content 
) const
private

Write content to a file, creating parent directories if needed.

Parameters
pathFilesystem path to write to
contentContent to write to the file
Returns
true if successful, false otherwise

Definition at line 16 of file MaCh3Program.cpp.

16  {
17  try {
18  fs::create_directories(path.parent_path());
19  std::ofstream out(path);
20  if (!out) return false;
21  out << content;
22  return true;
23  } catch (...) {
24  return false;
25  }
26  }

Member Data Documentation

◆ BASH_COMPLETION

constexpr std::string_view M3::MaCh3Program::BASH_COMPLETION
staticconstexprprivate
Initial value:
= R"(
_mach3_complete() {
local cur prev words cword
_init_completion || return
COMPREPLY=( $(mach3 --complete "$cur" "${words[@]:1:$cword}") )
}
complete -F _mach3_complete mach3
)"

Definition at line 78 of file MaCh3Program.hpp.

◆ m_dynamic_plugin_map

std::map<const MaCh3ArgumentParser*, std::unique_ptr<DynamicPlugin> > M3::MaCh3Program::m_dynamic_plugin_map
private

Map of parsers to dynamic plugins (owning)

Definition at line 76 of file MaCh3Program.hpp.

◆ m_module_map

std::map<const MaCh3ArgumentParser*, IModule*> M3::MaCh3Program::m_module_map
private

Map of parsers to core modules (non-owning)

Definition at line 75 of file MaCh3Program.hpp.

◆ m_subcommands

std::vector<std::string> M3::MaCh3Program::m_subcommands
private

List of registered subcommand names.

Definition at line 74 of file MaCh3Program.hpp.

◆ ZSH_COMPLETION

constexpr std::string_view M3::MaCh3Program::ZSH_COMPLETION
staticconstexprprivate
Initial value:
= R"(
#compdef mach3
local -a completions
local cur="$words[-1]"
completions=("${(@f)$(mach3 --complete "$cur" "${words[@]:1}")}")
compadd -a completions
)"

Definition at line 86 of file MaCh3Program.hpp.


The documentation for this class was generated from the following files: