Skip to content

Commit

Permalink
0.2.1: fix icon lookup bug and add devices_separator option
Browse files Browse the repository at this point in the history
  • Loading branch information
Pato05 committed Dec 24, 2022
1 parent a5ae61a commit 5cc66df
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 63 deletions.
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
cmake_minimum_required(VERSION 3.24)

option(NO_CLANG "Don't prefer clang for compilation" OFF)

if (NOT NO_CLANG)
# Prefer clang++ for compilation if available
find_program(CLANG clang)
find_program(CLANGXX clang++)

if (CLANG)
set(CMAKE_C_COMPILER ${CLANG})
endif()

if (CLANGXX)
set(CMAKE_CXX_COMPILER ${CLANGXX})
endif()
endif()

project(cppbtbl)

set(SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
Expand All @@ -24,6 +41,11 @@ set_target_properties(${PROJECT_NAME}

add_compile_options(-Wall -Wextra -Wshadow -Wpedantic -Wno-c++98-compat -Wfloat-conversion -Wno-unused-parameter -Wimplicit-fallthrough -Wconversion)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_options(-fsanitize=address,undefined)
target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined)
endif()

install(
TARGETS ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
Expand Down
29 changes: 17 additions & 12 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
#include "config.h"
#include "utils.h"

#define get_config_file(config_home) config_home / "cppbtbl" / "config"

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"format", required_argument, NULL, 'f'},
{"output", required_argument, NULL, 'o'},
{"dont-follow", no_argument, NULL, 'e'},
{"icons", required_argument, NULL, 'i'}
{"help", no_argument, NULL, 'h'},
{"format", required_argument, NULL, 'f'},
{"output", required_argument, NULL, 'o'},
{"icons", required_argument, NULL, 'i'},
{"devices-separator", required_argument, NULL, 's'},
{"dont-follow", no_argument, NULL, 'e'},
};


Expand Down Expand Up @@ -50,7 +53,7 @@ int parse_config(ProgramOptions *opts) {
auto config_home = get_config_home();
if (!config_home) return -1;

std::filesystem::path config_file = *config_home / "cppbtbl" / "config";
std::filesystem::path config_file = get_config_file(*config_home);

// std::cerr << "[DEBUG] config_file_path = " << config_file << std::endl;

Expand Down Expand Up @@ -101,6 +104,9 @@ int parse_config(ProgramOptions *opts) {
if (!opts->icons.empty()) break;
opts->icons = split(optarg, ',');
break;
case 's':
if (opts->devices_separator != nullptr) break;
opts->devices_separator = strdup(optarg);
default:
return 1;
}
Expand All @@ -110,18 +116,15 @@ int parse_config(ProgramOptions *opts) {
std::for_each(
++_argv.begin(),
_argv.end(),
[opts](const char* ptr) {
// std::cerr << (void *)ptr << ": " << ptr << std::endl;
[](const char *ptr) {
std::free((void *)ptr);
//std::cerr << "opts->custom_format: " << opts->custom_format << std::endl;
}
}
);

return -1;
}

int parse_opts(int argc, char *const argv[], ProgramOptions *opts) {

// reset getopt
optind = 1;
int opt;
Expand All @@ -143,13 +146,15 @@ int parse_opts(int argc, char *const argv[], ProgramOptions *opts) {
case 'i':
opts->icons = split(optarg, ',');
break;
case 's':
opts->devices_separator = std::move(optarg);
default:
return 1;
}
}
if (int e = parse_config(opts); e != -1) {
std::cerr << "Error occurred while parsing config." << std::endl;
return 1;
return e;
}

if (opts->output_format == format_custom and
Expand Down
7 changes: 5 additions & 2 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ enum OutputFormat {
};

struct ProgramOptions {
std::vector<std::string> icons;
OutputFormat output_format = format_raw_default;
char *custom_format;
// for custom format
std::vector<std::string> icons;
const char *custom_format;
const char *devices_separator;

bool dont_follow;
};

Expand Down
98 changes: 61 additions & 37 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#include <iostream>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <sys/eventfd.h>
#include <bits/stdc++.h>
#include <getopt.h>
#include <string>
#include <sstream>
#include <poll.h>
#include <getopt.h>
#include <sys/eventfd.h>
#include <sdbus-c++/sdbus-c++.h>

#include "config.h"
Expand All @@ -27,14 +26,56 @@ std::set<sdbus::ObjectPath> watch_list;
// runtime options
struct ProgramOptions opts;

std::string get_icon(int percentage) {
int icon_idx = (percentage * opts.icons.size() / 100) + 0.5;
const std::string get_icon(int percentage) {
int icon_idx = (percentage * (opts.icons.size() - 1) / 100) + 0.5;
return opts.icons[icon_idx];
}

void _output(std::optional<std::string> tooltip_str, int percentage, std::string device_name, OutputFormat output_format, const char* end = nullptr) {
switch (output_format) {
case format_waybar:
if (!tooltip_str) {
throw new std::runtime_error("illegal state! tooltip_str was not passed.");
}
replace_all(*tooltip_str, "\n", "\\n");
replace_all(*tooltip_str, "\"", "\\\"");
// lazy af solution, but should work
std::cout << "{\"percentage\":" << percentage << ",\"tooltip\":\"" << *tooltip_str << "\"}";
break;
case format_custom:
{
// make an std::string copy of the char*
std::string output(opts.custom_format);
const std::string icon = get_icon(percentage);
// replace all variables
replace(output, "{icon}", icon);
replace(output, "{percentage}", std::to_string(percentage));
replace(output, "{name}", device_name);

std::cout << output;
}
break;
case format_raw_default:
case format_raw:
if (!tooltip_str) {
throw new std::runtime_error("illegal state! tooltip_str was not passed.");
}
std::cout << *tooltip_str;
break;
}

if (end != nullptr) {
std::cout << end;
} else {
std::cout << std::endl;
}
}

void _get_battery_infos() {
if (watch_list.empty()) return;

bool should_use_separator = opts.output_format == format_custom and opts.devices_separator != nullptr;

int least_percentage = 100;
std::string least_device_name;
std::stringstream tooltip;
Expand All @@ -54,6 +95,11 @@ void _get_battery_infos() {
double percentage = device_obj->getProperty("Percentage")
.onInterface(UPOWER_DEVICE_IFACE)
.get<double>();

if (should_use_separator) {
_output(std::nullopt, percentage, device_name, opts.output_format, opts.devices_separator);
continue;
}
tooltip << device_name << ": " << percentage << "%\n";

if (percentage < least_percentage) {
Expand All @@ -62,34 +108,13 @@ void _get_battery_infos() {
}
}

if (should_use_separator) {
std::cout << std::endl;
}

std::string tooltip_str = tooltip.str();
tooltip_str.erase(tooltip_str.length() - 1);

switch (opts.output_format) {
case format_waybar:
replace_all(tooltip_str, "\n", "\\n");
replace_all(tooltip_str, "\"", "\\\"");
// lazy af solution, but should work
std::cout << "{\"percentage\":" << least_percentage << ",\"tooltip\":\"" << tooltip_str << "\"}" << std::endl;
break;
case format_custom:
{
// make an std::string copy of the char*
std::string output(opts.custom_format);
std::string icon = get_icon(least_percentage);
// replace all variables
replace(output, "{icon}", icon);
replace(output, "{percentage}", std::to_string(least_percentage));
replace(output, "{name}", least_device_name);

std::cout << output << std::endl;
}
break;
case format_raw_default:
case format_raw:
std::cout << tooltip_str << std::endl;
break;
}
_output(tooltip_str, least_percentage, least_device_name, opts.output_format);
}

void _device_added(sdbus::ObjectPath &path) {
Expand All @@ -111,8 +136,8 @@ void _device_added(sdbus::ObjectPath &path) {

void _device_removed(sdbus::ObjectPath &path) {
watch_list.erase(path);
if (watch_list.empty()) {

if (watch_list.empty()) {
std::cout << std::endl;
}
}
Expand Down Expand Up @@ -165,8 +190,7 @@ int main(int argc, char *const *argv) {
auto connection = &proxy->getConnection();

// `poll` event loop + timer for polling connected devices' battery
while (true)
{
while (true) {
bool processed = connection->processPendingRequest();
if (processed)
continue; // Process next one
Expand Down
27 changes: 15 additions & 12 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,21 @@ void replace_all(std::string &s, const std::string &search, const std::string &r
void help(char *name) {
std::cout
<< "Usage: " << name << " -f [format] [-o [format]] [-e]\n"
<< "-f/--format [format] valid options: waybar, custom, raw (default: raw)\n"
<< "-o/--output [format] the custom format to be used if -f is 'custom',\n"
<< " this must be a string, and you can include use the following variables:\n"
<< " {icon}, {percentage}, {name}.\n"
<< " please note that the 'icon' variable will be taken from the predefined\n"
<< " list of fontawesome icons.\n"
<< "-i/--icons [list] comma-separated list of icons, one of which will be used\n"
<< " in proportion to the device's percentage as the {icon}\n"
<< " parameter in '--output'\n"
<< " example: ',,,,'\n"
<< "-h/--help show this help screen\n"
<< "-e/--dont-follow output info and exit" << std::endl;
<< "-f/--format [format] valid options: waybar, custom, raw (default: raw)\n"
<< "-o/--output [format] the custom format to be used if -f is 'custom',\n"
<< " this must be a string, and you can include use these\n"
<< " variables: {icon}, {percentage}, {name}.\n"
<< "-i/--icons [list] comma-separated list of icons, one of which will be used\n"
<< " in proportion to the device's percentage as the {icon}\n"
<< " parameter in '--output'\n"
<< " example: --icons='1,2,3,4,5'\n"
<< " where 1,2,3,4,5 are the icons that indicate the battery\n"
<< " level, in ascending order.\n"
<< "-s/--device-separator [sep] by setting this, the scriptwill separate devices"
<< " with the given string; the --output parameter is repeated"
<< " for each connected device and devices are ordered by charge."
<< "-h/--help show this help screen\n"
<< "-e/--dont-follow output info and exit" << std::endl;
}

void incorrect_format_usage(char *name) {
Expand Down

0 comments on commit 5cc66df

Please sign in to comment.