Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to new command line parser and add some improvements in commands #6

Merged
merged 2 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 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
* `dcw` without args shows a list of all workspaces

# 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;
};
43 changes: 15 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 @@ -49,6 +32,13 @@ int main(int argc, char** argv)
auto processExecutor = make_shared<ProcessExecutor>();
auto composeExecutor = make_shared<ComposeExecutorImpl>(processExecutor);
auto workspaceService = make_shared<WorkspaceService>(workspacesRepo, stateRepo, composeExecutor);

if (argc == 1) {
// if no args provided then print workspaces list
workspaceService->list(false);
return 0;
}

Commands commands = {
make_shared<AddCommand>(workspaceService),
make_shared<RemoveCommand>(workspaceService),
Expand All @@ -57,17 +47,14 @@ 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) };
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
Loading