Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:brainboxdotcc/DPP
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis committed Oct 27, 2023
2 parents 8e813e8 + c90d17a commit 86cd39e
Show file tree
Hide file tree
Showing 64 changed files with 2,450 additions and 465 deletions.
4 changes: 3 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@
"cvtps",
"neww",
"STDCORO",
"NOMINMAX"
"NOMINMAX",
"sku",
"skus"
],
"flagWords": [
"hte"
Expand Down
75 changes: 11 additions & 64 deletions docpages/advanced_reference/coding_style_standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,20 @@ This covers your standard Curly Braces (commonly known as squiggly brackets), an

Curly Braces should be on the same line as the keyword, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
void foo() {
if (a == b) {
c();
} else {
d();
}

while (true) {
// ...
}

switch (a) {
case 1:
c();
break;
case 2:
d();
break;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/curly_braces.cpp

This applies to functions, `while` statements, `if` statements, lambdas, nearly anything that uses curly braces with statements!

### Lists

Lists should have a space after the comma in parameter lists, and after opening brackets and before closing brackets except when calling a function, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
std::vector<std::string> clowns = { "pennywise", "bobo" };

evaluate_clown(clowns[0], evilness(2.5, factor));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/lists.cpp

## Dot (.) Notation
When using the dot notation repeatedly (For example, creating an embed.), you should start each `.function()` on a new line, as such:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
stuff{}
.add_stuff()
.add_stuff();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/dot_notation.cpp

## Indentation

Expand All @@ -72,7 +43,11 @@ Constants and macros should be all `UPPERCASE` with `SNAKE_CASE` to separate wor

## Comments

All comments should be in `doxygen` format (similar to javadoc). Please see existing class definitions for an example. You should use doxygen style comments in a class definition inside a header file, and can use any other comment types within the .cpp file. Be liberal with comments, especially if your code makes any assumptions!
All comments should be in `doxygen` format (similar to javadoc). Please see existing class definitions for an example. You should use doxygen style comments in a class definition inside a header file. Be liberal with comments, especially if your code makes any assumptions! Comments should follow the format below:

\note Comments that contain doxygen stuff need to use two stars at the beginning (/**). This example doesn't because doxygen gets confused and doesn't show the comments.

\include{cpp} coding_style_standards/comments.cpp

## Spell Checks

Expand All @@ -82,13 +57,7 @@ To prevent typos, a GitHub-Action checks the documentation. If it fails for a wo

If you export a class which is to be accessible to users, be sure to prefix it with the `DPP_EXPORT` macro, for example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
class DPP_EXPORT my_new_class {
public:
int hats;
int clowns;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/symbol_exporting.cpp

The `DPP_EXPORT` macro ensures that on certain platforms (notably Windows) the symbol is exported to be available to the library user.

Expand Down Expand Up @@ -132,33 +101,11 @@ If a value will only hold values up to 255, use `uint8_t`. If a value cannot hol

Where possible, if you are adding methods to a class you should consider fluent design. Fluent design is the use of class methods that return a reference to self (via `return *this`), so that you can chain object method calls together (in the way dpp::message and dpp::embed do). For example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
class DPP_EXPORT my_new_class {
public:
int hats;
int clowns;
my_new_class& set_hats(int new_hats);
my_new_class& set_clowns(int new_clowns);
};
my_new_class& my_new_class::set_hats(int new_hats) {
hats = new_hats;
return *this;
}
my_new_class& my_new_class::set_clowns(int new_clowns) {
clowns = new_clowns;
return *this;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/fluent_design.cpp

This would allow the user to do this:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cpp
dpp::my_new_class nc;
nc.set_hats(3).set_clowns(9001);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\include{cpp} coding_style_standards/fluent_design2.cpp

## Keep All D++ Related Types in the dpp Namespace

Expand Down
27 changes: 27 additions & 0 deletions docpages/example_code/coding_style_standards/comments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* @brief This is a function that does some cool stuff.
* More stuff here will still go in brief!
* @warning This does nothing!
*/
func_name();

/*
* @brief This turns a name into a meme name!
*
* @param name The name of the user that you want to meme-ify.
* @return a meme name!
*/
std::string name_to_meme(const std::string& name) const;

/* -------------------- .cpp file -------------------- */

int main() {
/* We are now going to do some cool stuff. */
func_name();

/* Going to turn brain into a meme name.
* Why?
* Because why not. That's why.
*/
std::cout << name_to_meme("Brain") << "\n";
}
20 changes: 20 additions & 0 deletions docpages/example_code/coding_style_standards/curly_braces.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
void foo() {
if (a == b) {
c();
} else {
d();
}

while (true) {
// ...
}

switch (a) {
case 1:
c();
break;
case 2:
d();
break;
}
}
5 changes: 5 additions & 0 deletions docpages/example_code/coding_style_standards/dot_notation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
stuff{}
.add_stuff()
.add_stuff();

event.reply("This reply function isn't indented!");
18 changes: 18 additions & 0 deletions docpages/example_code/coding_style_standards/fluent_design.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class DPP_EXPORT my_new_class {
public:
int hats;
int clowns;

my_new_class& set_hats(int new_hats);
my_new_class& set_clowns(int new_clowns);
};

my_new_class& my_new_class::set_hats(int new_hats) {
hats = new_hats;
return *this;
}

my_new_class& my_new_class::set_clowns(int new_clowns) {
clowns = new_clowns;
return *this;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dpp::my_new_class nc;
nc.set_hats(3).set_clowns(9001);
3 changes: 3 additions & 0 deletions docpages/example_code/coding_style_standards/lists.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
std::vector<std::string> clowns = { "pennywise", "bobo" };

evaluate_clown(clowns[0], evilness(2.5, factor));
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class DPP_EXPORT my_new_class {
public:
int hats;
int clowns;
};
4 changes: 2 additions & 2 deletions docpages/example_code/coro_awaiting_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int main() {

bot.on_log(dpp::utility::cout_logger());

bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task<void> {
if (event.command.get_command_name() == "test") {
// Make a message and add a button with its custom ID set to the command interaction's ID so we can identify it
dpp::message m{"Test"};
Expand All @@ -32,7 +32,7 @@ int main() {
}
});

bot.on_ready([&bot](const dpp::ready_t & event) {
bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {
dpp::slashcommand command{"test", "Test awaiting for an event", bot.me.id};

Expand Down
4 changes: 2 additions & 2 deletions docpages/example_code/coro_expiring_buttons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int main() {

bot.on_log(dpp::utility::cout_logger());

bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task<void> {
if (event.command.get_command_name() == "test") {
// Make a message and add a button with its custom ID set to the command interaction's ID so we can identify it
dpp::message m{"Test"};
Expand Down Expand Up @@ -38,7 +38,7 @@ int main() {
}
});

bot.on_ready([&bot](const dpp::ready_t & event) {
bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {
dpp::slashcommand command{"test", "Test awaiting for an event", bot.me.id};

Expand Down
3 changes: 1 addition & 2 deletions docpages/example_code/coro_intro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ int main() {
bot.on_log(dpp::utility::cout_logger());

/* The event is fired when someone issues your commands */
/* Make note of passing the event by value, this is important (explained below) */
bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task<void> {
if (event.command.get_command_name() == "file") {
/* Request the image from the URL specified and co_await the response */
dpp::http_request_completion_t result = co_await event.from->creator->co_request("https://dpp.dev/DPP-Logo.png", dpp::m_get);
Expand Down
4 changes: 2 additions & 2 deletions docpages/example_code/coro_simple_commands1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int main() {

bot.on_log(dpp::utility::cout_logger());

bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task<void> {
if (event.command.get_command_name() == "addemoji") {
dpp::cluster *cluster = event.from->creator;
// Retrieve parameter values
Expand Down Expand Up @@ -48,7 +48,7 @@ int main() {
}
});

bot.on_ready([&bot](const dpp::ready_t & event) {
bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {
dpp::slashcommand command("addemoji", "Add an emoji", bot.me.id);
// Add file and name as required parameters
Expand Down
4 changes: 2 additions & 2 deletions docpages/example_code/coro_simple_commands2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int main() {

bot.on_log(dpp::utility::cout_logger());

bot.on_slashcommand([](dpp::slashcommand_t event) -> dpp::job {
bot.on_slashcommand([](const dpp::slashcommand_t& event) -> dpp::task<void> {
if (event.command.get_command_name() == "avatar") {
// Make a nested coroutine to fetch the guild member requested, that returns it as an optional
constexpr auto resolve_member = [](const dpp::slashcommand_t &event) -> dpp::task<std::optional<dpp::guild_member>> {
Expand Down Expand Up @@ -70,7 +70,7 @@ int main() {
});


bot.on_ready([&bot](const dpp::ready_t & event) {
bot.on_ready([&bot](const dpp::ready_t& event) {
if (dpp::run_once<struct register_bot_commands>()) {
dpp::slashcommand command("avatar", "Get your or another user's avatar image", bot.me.id);
command.add_option(dpp::command_option(dpp::co_user, "user", "User to fetch the avatar from"));
Expand Down
2 changes: 2 additions & 0 deletions docpages/example_programs/misc/setting_status.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A bot status is pretty cool, and it'd be cooler if you knew how to do it! This tutorial will cover how to set the bot status to say `Playing games!`, as well as covering how to set the status to the amount of guilds every two minutes.

\note dpp::get_guild_cache requires the bot to have the guild cache enabled, if your bot has this disabled then you can't use that. Instead, you should look to use dpp::cluster::current_application_get and get the `approximate_guild_count` from dpp::application in the callback.

First, we'll cover setting the bot status to `Playing games!`.

\include{cpp} setting_status1.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Let's revisit \ref attach-file "attaching a downloaded file", but this time with

Coroutines can make commands simpler by eliminating callbacks, which can be very handy in the case of complex commands that rely on a lot of different data or steps.

In order to be a coroutine, a function has to return a special type with special functions; D++ offers dpp::job, dpp::task, and dpp::coroutine, which are designed to work seamlessly with asynchronous calls through dpp::async, which all the functions starting with `co_` such as dpp::cluster::co_message_create return. Event routers can have a dpp::job attached to them, as this object allows to create coroutines that can execute on their own, asynchronously. More on that and the difference between it and the other two types later. To turn a function into a coroutine, simply make it return dpp::job as seen in the example at line 10, then use `co_await` on awaitable types or `co_return`. The moment the execution encounters one of these two keywords, the function is transformed into a coroutine. Coroutines that use dpp::job can be used for event handlers, they can be attached to an event router just the same way as regular event handlers.
In order to be a coroutine, a function has to return a special type with special functions; D++ offers dpp::job, dpp::task, and dpp::coroutine, which are designed to work seamlessly with asynchronous calls through dpp::async, which all the functions starting with `co_` such as dpp::cluster::co_message_create return. Event routers can have a dpp::task coroutine attached to them, as this object allows to create coroutines that can execute on their own, asynchronously. More on that and the difference between it and the other two types later. To turn a function into a coroutine, simply make it return dpp::task<void> as seen in the example at line 10, then use `co_await` on awaitable types or `co_return`. The moment the execution encounters one of these two keywords, the function is transformed into a coroutine. Coroutines that use dpp::task<void> can be used for event handlers, they can be attached to an event router just the same way as regular event handlers.

When using a `co_*` function such as `co_message_create`, the request is sent immediately and the returned dpp::async can be `co_await`-ed, at which point the coroutine suspends (pauses) and returns back to its caller; in other words, the program is free to go and do other things while the data is being retrieved and D++ will resume your coroutine when it has the data you need, which will be returned from the `co_await` expression.

Expand Down
Loading

0 comments on commit 86cd39e

Please sign in to comment.