use format_placeholder for battery
This commit is contained in:
parent
eccd4a7618
commit
b5a804d1af
@ -50,6 +50,7 @@ i3status_SOURCES = \
|
|||||||
i3status.c \
|
i3status.c \
|
||||||
src/auto_detect_format.c \
|
src/auto_detect_format.c \
|
||||||
src/first_network_device.c \
|
src/first_network_device.c \
|
||||||
|
src/format_placeholders.c \
|
||||||
src/general.c \
|
src/general.c \
|
||||||
src/output.c \
|
src/output.c \
|
||||||
src/print_battery_info.c \
|
src/print_battery_info.c \
|
||||||
|
@ -198,6 +198,20 @@ char *endcolor() __attribute__((pure));
|
|||||||
void reset_cursor(void);
|
void reset_cursor(void);
|
||||||
void maybe_escape_markup(char *text, char **buffer);
|
void maybe_escape_markup(char *text, char **buffer);
|
||||||
|
|
||||||
|
char *rtrim(const char *s);
|
||||||
|
char *ltrim(const char *s);
|
||||||
|
char *trim(const char *s);
|
||||||
|
|
||||||
|
// copied from i3:libi3/format_placeholders.c
|
||||||
|
/* src/format_placeholders.c */
|
||||||
|
typedef struct {
|
||||||
|
/* The placeholder to be replaced, e.g., "%title". */
|
||||||
|
char *name;
|
||||||
|
/* The value this placeholder should be replaced with. */
|
||||||
|
char *value;
|
||||||
|
} placeholder_t;
|
||||||
|
char *format_placeholders(const char *format, placeholder_t *placeholders, int num);
|
||||||
|
|
||||||
/* src/auto_detect_format.c */
|
/* src/auto_detect_format.c */
|
||||||
char *auto_detect_format();
|
char *auto_detect_format();
|
||||||
|
|
||||||
|
70
src/format_placeholders.c
Normal file
70
src/format_placeholders.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* vim:ts=4:sw=4:expandtab
|
||||||
|
*
|
||||||
|
* i3 - an improved dynamic tiling window manager
|
||||||
|
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// copied from i3:libi3/format_placeholders.c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "i3status.h"
|
||||||
|
|
||||||
|
#ifndef CS_STARTS_WITH
|
||||||
|
#define CS_STARTS_WITH(string, needle) (strncmp((string), (needle), strlen((needle))) == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replaces occurrences of the defined placeholders in the format string.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *format_placeholders(const char *format, placeholder_t *placeholders, int num) {
|
||||||
|
if (format == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* We have to first iterate over the string to see how much buffer space
|
||||||
|
* we need to allocate. */
|
||||||
|
int buffer_len = strlen(format) + 1;
|
||||||
|
for (const char *walk = format; *walk != '\0'; walk++) {
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
if (!CS_STARTS_WITH(walk, placeholders[i].name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer_len = buffer_len - strlen(placeholders[i].name) + strlen(placeholders[i].value);
|
||||||
|
walk += strlen(placeholders[i].name) - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we can parse the format string. */
|
||||||
|
char buffer[buffer_len];
|
||||||
|
char *outwalk = buffer;
|
||||||
|
for (const char *walk = format; *walk != '\0'; walk++) {
|
||||||
|
if (*walk != '%') {
|
||||||
|
*(outwalk++) = *walk;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matched = false;
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
if (!CS_STARTS_WITH(walk, placeholders[i].name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
matched = true;
|
||||||
|
outwalk += sprintf(outwalk, "%s", placeholders[i].value);
|
||||||
|
walk += strlen(placeholders[i].name) - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matched)
|
||||||
|
*(outwalk++) = *walk;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outwalk = '\0';
|
||||||
|
return sstrdup(buffer);
|
||||||
|
}
|
34
src/output.c
34
src/output.c
@ -8,6 +8,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "i3status.h"
|
#include "i3status.h"
|
||||||
|
|
||||||
@ -121,3 +122,36 @@ void maybe_escape_markup(char *text, char **buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove leading spaces
|
||||||
|
*/
|
||||||
|
char *ltrim(const char *s) {
|
||||||
|
while (isspace(*s))
|
||||||
|
++s;
|
||||||
|
return sstrdup(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove trailing spaces
|
||||||
|
*/
|
||||||
|
char *rtrim(const char *s) {
|
||||||
|
char *r = sstrdup(s);
|
||||||
|
if (r != NULL) {
|
||||||
|
char *fr = r + strlen(s) - 1;
|
||||||
|
while ((isspace(*fr) || *fr == 0) && fr >= r)
|
||||||
|
--fr;
|
||||||
|
*++fr = 0;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove leading & trailing spaces
|
||||||
|
*/
|
||||||
|
char *trim(const char *s) {
|
||||||
|
char *r = rtrim(s);
|
||||||
|
char *f = ltrim(r);
|
||||||
|
free(r);
|
||||||
|
return f;
|
||||||
|
}
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "i3status.h"
|
#include "i3status.h"
|
||||||
|
|
||||||
|
#define STRING_SIZE 10
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
@ -571,7 +573,6 @@ static bool slurp_all_batteries(struct battery_info *batt_info, yajl_gen json_ge
|
|||||||
}
|
}
|
||||||
|
|
||||||
void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, const char *format_down, const char *status_chr, const char *status_bat, const char *status_unk, const char *status_full, int low_threshold, char *threshold_type, bool last_full_capacity, const char *format_percentage, bool hide_seconds) {
|
void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, const char *format_down, const char *status_chr, const char *status_bat, const char *status_unk, const char *status_full, int low_threshold, char *threshold_type, bool last_full_capacity, const char *format_percentage, bool hide_seconds) {
|
||||||
const char *walk;
|
|
||||||
char *outwalk = buffer;
|
char *outwalk = buffer;
|
||||||
struct battery_info batt_info = {
|
struct battery_info batt_info = {
|
||||||
.full_design = -1,
|
.full_design = -1,
|
||||||
@ -653,94 +654,70 @@ void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT() \
|
char string_status[STRING_SIZE];
|
||||||
do { \
|
char string_percentage[STRING_SIZE];
|
||||||
if (outwalk == prevoutwalk) { \
|
// following variables are not alwasy set. If they are not set they should be empty.
|
||||||
if (outwalk > buffer && isspace((int)outwalk[-1])) \
|
char string_remaining[STRING_SIZE] = "";
|
||||||
outwalk--; \
|
char string_emptytime[STRING_SIZE] = "";
|
||||||
else if (isspace((int)*(walk + 1))) \
|
char string_consumption[STRING_SIZE] = "";
|
||||||
walk++; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
for (walk = format; *walk != '\0'; walk++) {
|
const char *statusstr;
|
||||||
char *prevoutwalk = outwalk;
|
switch (batt_info.status) {
|
||||||
|
case CS_CHARGING:
|
||||||
if (*walk != '%') {
|
statusstr = status_chr;
|
||||||
*(outwalk++) = *walk;
|
break;
|
||||||
|
case CS_DISCHARGING:
|
||||||
} else if (BEGINS_WITH(walk + 1, "status")) {
|
statusstr = status_bat;
|
||||||
const char *statusstr;
|
break;
|
||||||
switch (batt_info.status) {
|
case CS_FULL:
|
||||||
case CS_CHARGING:
|
statusstr = status_full;
|
||||||
statusstr = status_chr;
|
break;
|
||||||
break;
|
default:
|
||||||
case CS_DISCHARGING:
|
statusstr = status_unk;
|
||||||
statusstr = status_bat;
|
|
||||||
break;
|
|
||||||
case CS_FULL:
|
|
||||||
statusstr = status_full;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
statusstr = status_unk;
|
|
||||||
}
|
|
||||||
|
|
||||||
outwalk += sprintf(outwalk, "%s", statusstr);
|
|
||||||
walk += strlen("status");
|
|
||||||
|
|
||||||
} else if (BEGINS_WITH(walk + 1, "percentage")) {
|
|
||||||
outwalk += sprintf(outwalk, format_percentage, batt_info.percentage_remaining, pct_mark);
|
|
||||||
walk += strlen("percentage");
|
|
||||||
|
|
||||||
} else if (BEGINS_WITH(walk + 1, "remaining")) {
|
|
||||||
if (batt_info.seconds_remaining >= 0) {
|
|
||||||
int seconds, hours, minutes;
|
|
||||||
|
|
||||||
hours = batt_info.seconds_remaining / 3600;
|
|
||||||
seconds = batt_info.seconds_remaining - (hours * 3600);
|
|
||||||
minutes = seconds / 60;
|
|
||||||
seconds -= (minutes * 60);
|
|
||||||
|
|
||||||
if (hide_seconds)
|
|
||||||
outwalk += sprintf(outwalk, "%02d:%02d",
|
|
||||||
max(hours, 0), max(minutes, 0));
|
|
||||||
else
|
|
||||||
outwalk += sprintf(outwalk, "%02d:%02d:%02d",
|
|
||||||
max(hours, 0), max(minutes, 0), max(seconds, 0));
|
|
||||||
}
|
|
||||||
walk += strlen("remaining");
|
|
||||||
EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT();
|
|
||||||
|
|
||||||
} else if (BEGINS_WITH(walk + 1, "emptytime")) {
|
|
||||||
if (batt_info.seconds_remaining >= 0) {
|
|
||||||
time_t empty_time = time(NULL) + batt_info.seconds_remaining;
|
|
||||||
set_timezone(NULL); /* Use local time. */
|
|
||||||
struct tm *empty_tm = localtime(&empty_time);
|
|
||||||
|
|
||||||
if (hide_seconds)
|
|
||||||
outwalk += sprintf(outwalk, "%02d:%02d",
|
|
||||||
max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0));
|
|
||||||
else
|
|
||||||
outwalk += sprintf(outwalk, "%02d:%02d:%02d",
|
|
||||||
max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0), max(empty_tm->tm_sec, 0));
|
|
||||||
}
|
|
||||||
walk += strlen("emptytime");
|
|
||||||
EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT();
|
|
||||||
|
|
||||||
} else if (BEGINS_WITH(walk + 1, "consumption")) {
|
|
||||||
if (batt_info.present_rate >= 0)
|
|
||||||
outwalk += sprintf(outwalk, "%1.2fW", batt_info.present_rate / 1e6);
|
|
||||||
|
|
||||||
walk += strlen("consumption");
|
|
||||||
EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*(outwalk++) = '%';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
snprintf(string_status, STRING_SIZE, "%s", statusstr);
|
||||||
|
snprintf(string_percentage, STRING_SIZE, format_percentage, batt_info.percentage_remaining, pct_mark);
|
||||||
|
|
||||||
|
if (batt_info.seconds_remaining >= 0) {
|
||||||
|
int seconds, hours, minutes;
|
||||||
|
hours = batt_info.seconds_remaining / 3600;
|
||||||
|
seconds = batt_info.seconds_remaining - (hours * 3600);
|
||||||
|
minutes = seconds / 60;
|
||||||
|
seconds -= (minutes * 60);
|
||||||
|
if (hide_seconds)
|
||||||
|
snprintf(string_remaining, STRING_SIZE, "%02d:%02d", max(hours, 0), max(minutes, 0));
|
||||||
|
else
|
||||||
|
snprintf(string_remaining, STRING_SIZE, "%02d:%02d:%02d", max(hours, 0), max(minutes, 0), max(seconds, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batt_info.seconds_remaining >= 0) {
|
||||||
|
time_t empty_time = time(NULL) + batt_info.seconds_remaining;
|
||||||
|
set_timezone(NULL); /* Use local time. */
|
||||||
|
struct tm *empty_tm = localtime(&empty_time);
|
||||||
|
if (hide_seconds)
|
||||||
|
snprintf(string_emptytime, STRING_SIZE, "%02d:%02d", max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0));
|
||||||
|
else
|
||||||
|
snprintf(string_emptytime, STRING_SIZE, "%02d:%02d:%02d", max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0), max(empty_tm->tm_sec, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batt_info.present_rate >= 0)
|
||||||
|
snprintf(string_consumption, STRING_SIZE, "%1.2fW", batt_info.present_rate / 1e6);
|
||||||
|
|
||||||
|
placeholder_t placeholders[] = {
|
||||||
|
{.name = "%status", .value = string_status},
|
||||||
|
{.name = "%percentage", .value = string_percentage},
|
||||||
|
{.name = "%remaining", .value = string_remaining},
|
||||||
|
{.name = "%emptytime", .value = string_emptytime},
|
||||||
|
{.name = "%consumption", .value = string_consumption}};
|
||||||
|
|
||||||
|
const size_t num = sizeof(placeholders) / sizeof(placeholder_t);
|
||||||
|
char *untrimmed = format_placeholders(format, &placeholders[0], num);
|
||||||
|
buffer = trim(untrimmed);
|
||||||
|
free(untrimmed);
|
||||||
|
|
||||||
if (colorful_output)
|
if (colorful_output)
|
||||||
END_COLOR;
|
END_COLOR;
|
||||||
|
|
||||||
OUTPUT_FULL_TEXT(buffer);
|
OUTPUT_FULL_TEXT(buffer);
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
4
testcases/020-percentliteral-battery/BAT0_uevent
Normal file
4
testcases/020-percentliteral-battery/BAT0_uevent
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
POWER_SUPPLY_STATUS=Discharging
|
||||||
|
POWER_SUPPLY_CURRENT_NOW=1107000
|
||||||
|
POWER_SUPPLY_CHARGE_FULL_DESIGN=7800000
|
||||||
|
POWER_SUPPLY_CHARGE_NOW=2390000
|
1
testcases/020-percentliteral-battery/expected_output.txt
Normal file
1
testcases/020-percentliteral-battery/expected_output.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
I can %haz literal% % ?
|
10
testcases/020-percentliteral-battery/i3status.conf
Normal file
10
testcases/020-percentliteral-battery/i3status.conf
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
general {
|
||||||
|
output_format = "none"
|
||||||
|
}
|
||||||
|
|
||||||
|
order += "battery all"
|
||||||
|
|
||||||
|
battery all {
|
||||||
|
format = "I can %haz literal% % ?"
|
||||||
|
path = "testcases/020-percentliteral-battery/BAT%d_uevent"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user