Skip to content

Commit

Permalink
Switch to new command line parser and add some improvements in commands
Browse files Browse the repository at this point in the history
  • Loading branch information
navrocky committed May 8, 2024
1 parent da80156 commit 3c72872
Show file tree
Hide file tree
Showing 20 changed files with 122 additions and 142 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 1.2.0 (2024.05.08)

* Switch to new command line parser [CLI11](https://github.com/CLIUtils/CLI11)
* Suggest workspace name in `up` command if it not provided. Name suggested if current directory matches workspace or
try to up the latest active workspace.
* Added shortcuts for all commands

# 1.1.2 (2024.04.24)

* Fix location of state yaml file to `~/.local/share/dcw/state.yml`
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ sudo sh -c 'curl -sSL https://github.com/navrocky/dcw/raw/master/install.sh | ba
## Usage

```
USAGE: dcw <command> <options>
Usage: dcw [OPTIONS] SUBCOMMAND
add <name> <compose file> Add named docker compose file as workspace
down Down current workspace
list List registered workspaces
rm <name> Remove workspace by name
up <name> Switch to the workspace with a name
Options:
-h,--help Print this help message and exit
OPTIONAL:
-h, --help <arg> Print this help.
Subcommands:
add, a Add named docker compose file as workspace
rm, r Remove workspace
list, l List registered workspaces
up, u Switch to the workspace
down, d Down current workspace
```

## Examples
Expand Down
5 changes: 2 additions & 3 deletions cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
set(TARGET dcw)

find_package(args-parser REQUIRED)
find_package(termcolor REQUIRED)
find_package(yaml-cpp REQUIRED)
find_package(CLI11 REQUIRED)

add_link_options(-static -static-libgcc -static-libstdc++)

Expand Down Expand Up @@ -35,7 +35,6 @@ set(SOURCES
commands/remove_command.h
commands/remove_command.cpp
commands/base_command.h
commands/base_command.cpp
commands/list_command.h
commands/list_command.cpp
commands/up_command.h
Expand All @@ -47,9 +46,9 @@ set(SOURCES
add_executable(${TARGET} ${SOURCES})

target_link_libraries(${TARGET}
args-parser::args-parser
termcolor::termcolor
yaml-cpp::yaml-cpp
CLI11::CLI11
)

include(GNUInstallDirs)
Expand Down
30 changes: 8 additions & 22 deletions cli/commands/add_command.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "add_command.h"

#include <filesystem>
#include <stdexcept>

using namespace std;

Expand All @@ -10,30 +9,17 @@ AddCommand::AddCommand(const WorkspaceServicePtr& service)
{
}

void AddCommand::reg(Args::CmdLine& cmdLine)
void AddCommand::reg(CLI::App& app)
{
cmdLine
.addCommand("add", Args::ValueOptions::ManyValues, false, "Add named docker compose file as workspace",
string(), string(), "name> <compose file")
.end();
auto cmd = app.add_subcommand("add", "Add named docker compose file as workspace")
->alias("a")
->callback(std::bind(&AddCommand::process, this));
cmd->add_option("name", name, "Workspace name")->required();
cmd->add_option("file", file, "Docker compose file")->required();
}

bool AddCommand::process(const Args::CmdLine& cmdLine)
void AddCommand::process()
{
if (!cmdLine.isDefined("add"))
return false;
auto vals = cmdLine.values("add");
if (vals.size() != 2)
throw runtime_error("Expected two arguments for 'add' command");
auto name = vals[0];
auto composeFile = vals[1];
if (name.empty())
throw runtime_error("Name is empty");
if (composeFile.empty())
throw runtime_error("Compose file is empty");

auto composeFilePath = std::filesystem::absolute(composeFile);

auto composeFilePath = std::filesystem::absolute(file);
service->add(name, composeFilePath);
return true;
}
7 changes: 5 additions & 2 deletions cli/commands/add_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ class AddCommand : public BaseCommand {
public:
AddCommand(const WorkspaceServicePtr& service);

void reg(Args::CmdLine& cmdLine) override;
bool process(const Args::CmdLine& cmdLine) override;
void reg(CLI::App& app) override;

private:
void process();

WorkspaceServicePtr service;
std::string name;
std::string file;
};
1 change: 0 additions & 1 deletion cli/commands/base_command.cpp

This file was deleted.

5 changes: 2 additions & 3 deletions cli/commands/base_command.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#pragma once

#include <args-parser/all.hpp>
#include <CLI/App.hpp>
#include <memory>

class BaseCommand {
public:
virtual ~BaseCommand() { }
virtual void reg(Args::CmdLine& cmdLine) = 0;
virtual bool process(const Args::CmdLine& cmdLine) = 0;
virtual void reg(CLI::App& app) = 0;
};

using CommandPtr = std::shared_ptr<BaseCommand>;
19 changes: 7 additions & 12 deletions cli/commands/down_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@

DownCommand::DownCommand(const WorkspaceServicePtr& service)
: service(service)
, purge(false)
{
}

void DownCommand::reg(Args::CmdLine& cmdLine)
void DownCommand::reg(CLI::App& app)
{
cmdLine.addCommand("down", Args::ValueOptions::NoValue, false, "Down current workspace")
.addArgWithFlagAndName('p', "purge", false, false, "Purge workspace data (docker volumes)")
.end();
auto cmd = app.add_subcommand("down", "Down current workspace")
->alias("d")
->callback(std::bind(&DownCommand::process, this));
cmd->add_flag("-p, --purge", purge, "Purge workspace data (docker volumes)");
}

bool DownCommand::process(const Args::CmdLine& cmdLine)
{
if (!cmdLine.isDefined("down"))
return false;
bool purge = cmdLine.isDefined("-p");
service->down(purge);
return true;
}
void DownCommand::process() { service->down(purge); }
5 changes: 3 additions & 2 deletions cli/commands/down_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ class DownCommand : public BaseCommand {
public:
DownCommand(const WorkspaceServicePtr& service);

void reg(Args::CmdLine& cmdLine) override;
bool process(const Args::CmdLine& cmdLine) override;
void reg(CLI::App& app) override;

private:
void process();
WorkspaceServicePtr service;
bool purge;
};
19 changes: 7 additions & 12 deletions cli/commands/list_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@

ListCommand::ListCommand(const WorkspaceServicePtr& service)
: service(service)
, namesOnly(false)
{
}

void ListCommand::reg(Args::CmdLine& cmdLine)
void ListCommand::reg(CLI::App& app)
{
cmdLine.addCommand("list", Args::ValueOptions::NoValue, false, "List registered workspaces")
.addArgWithFlagAndName('n', "names", false, false, "Show names only")
.end();
auto cmd = app.add_subcommand("list", "List registered workspaces")
->alias("l")
->callback(std::bind(&ListCommand::process, this));
cmd->add_flag("-n, --names", namesOnly, "Show names only");
}

bool ListCommand::process(const Args::CmdLine& cmdLine)
{
if (!cmdLine.isDefined("list"))
return false;
bool namesOnly = cmdLine.isDefined("-n");
service->list(namesOnly);
return true;
}
void ListCommand::process() { service->list(namesOnly); }
5 changes: 3 additions & 2 deletions cli/commands/list_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ class ListCommand : public BaseCommand {
public:
ListCommand(const WorkspaceServicePtr& service);

void reg(Args::CmdLine& cmdLine) override;
bool process(const Args::CmdLine& cmdLine) override;
void reg(CLI::App& app) override;

private:
void process();
WorkspaceServicePtr service;
bool namesOnly;
};
21 changes: 5 additions & 16 deletions cli/commands/remove_command.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
#include "remove_command.h"

#include <stdexcept>

using namespace std;

RemoveCommand::RemoveCommand(const WorkspaceServicePtr& service)
: service(service)
{
}

void RemoveCommand::reg(Args::CmdLine& cmdLine)
void RemoveCommand::reg(CLI::App& app)
{
cmdLine.addCommand("rm", Args::ValueOptions::OneValue, false, "Remove workspace by name", "", "", "name").end();
auto cmd
= app.add_subcommand("rm", "Remove workspace")->alias("r")->callback(std::bind(&RemoveCommand::process, this));
cmd->add_option("name", name, "Name of the workspace");
}

bool RemoveCommand::process(const Args::CmdLine& cmdLine)
{
if (!cmdLine.isDefined("rm"))
return false;
auto name = cmdLine.value("rm");
if (name.empty())
throw runtime_error("Name is empty");
service->remove(name);
return true;
}
void RemoveCommand::process() { service->remove(name); }
5 changes: 3 additions & 2 deletions cli/commands/remove_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ class RemoveCommand : public BaseCommand {
public:
RemoveCommand(const WorkspaceServicePtr& service);

void reg(Args::CmdLine& cmdLine) override;
bool process(const Args::CmdLine& cmdLine) override;
void reg(CLI::App& app) override;

private:
void process();
WorkspaceServicePtr service;
std::string name;
};
24 changes: 8 additions & 16 deletions cli/commands/up_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,17 @@

UpCommand::UpCommand(const WorkspaceServicePtr& service)
: service(service)
, clean(false)
{
}

void UpCommand::reg(Args::CmdLine& cmdLine)
void UpCommand::reg(CLI::App& app)
{
cmdLine
.addCommand(
"up", Args::ValueOptions::OneValue, false, "Switch to the workspace with a name", "", "default", "name")
.addArgWithFlagAndName('c', "clean", false, false, "Purge workspace data (docker volumes) before start")
.end();
auto cmd = app.add_subcommand("up", "Switch to the workspace")
->alias("u")
->callback(std::bind(&UpCommand::process, this));
cmd->add_option("name", name, "Workspace name");
cmd->add_flag("-c, --clean", clean, "Purge workspace data (docker volumes) before start");
}

bool UpCommand::process(const Args::CmdLine& cmdLine)
{
if (!cmdLine.isDefined("up"))
return false;
auto vals = cmdLine.values("up");
auto name = vals[0];
bool clean = cmdLine.isDefined("-c");
service->up(name, clean);
return true;
}
void UpCommand::process() { service->up(name, clean); }
6 changes: 4 additions & 2 deletions cli/commands/up_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ class UpCommand : public BaseCommand {
public:
UpCommand(const WorkspaceServicePtr& service);

void reg(Args::CmdLine& cmdLine) override;
bool process(const Args::CmdLine& cmdLine) override;
void reg(CLI::App& app) override;

private:
void process();
WorkspaceServicePtr service;
std::string name;
bool clean;
};
37 changes: 9 additions & 28 deletions cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <format>
#include <iostream>

#include <args-parser/all.hpp>
#include <CLI/CLI.hpp>
#include <termcolor/termcolor.hpp>

#include "yaml_workspaces_repository.h"
Expand All @@ -15,27 +15,10 @@
#include "config.h"

using namespace std;
using namespace Args;
namespace tc = termcolor;

using Commands = vector<CommandPtr>;

void regCommands(const Commands& commands, CmdLine& cmdLine)
{
for (const auto& cmd : commands) {
cmd->reg(cmdLine);
}
}

void processCommands(const Commands& commands, const CmdLine& cmdLine)
{
for (const auto& cmd : commands) {
if (cmd->process(cmdLine))
return;
}
throw runtime_error("No command processed");
}

int main(int argc, char** argv)
{
try {
Expand All @@ -57,17 +40,15 @@ int main(int argc, char** argv)
make_shared<DownCommand>(workspaceService),
};

CmdLine cmdLine(argc, argv, CmdLine::CommandIsRequired);
cmdLine.addHelp(true, argv[0], format("Docker Compose Workspace manager (v{})", APP_VERSION));
regCommands(commands, cmdLine);
cmdLine.parse();
processCommands(commands, cmdLine);
return 0;
} catch (const HelpHasBeenPrintedException& e) {
CLI::App app { format("Docker Compose Workspace manager (v{})", APP_VERSION) };
app.require_subcommand();

for (const auto& cmd : commands) {
cmd->reg(app);
}

CLI11_PARSE(app, argc, argv);
return 0;
} catch (const BaseException& e) {
cerr << tc::red << "Call error: " << e.desc() << tc::reset << endl;
return 1;
} catch (const exception& e) {
cerr << tc::red << "Error: " << e.what() << tc::reset << endl;
return 1;
Expand Down
Loading

0 comments on commit 3c72872

Please sign in to comment.