Created
April 22, 2019 19:56
-
-
Save karolba/07d95f361e92405eb611a6c2d75382ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <memory> | |
#include <json/value.h> | |
#include <json/reader.h> | |
#include <json/writer.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <stdio.h> | |
#include <ext/stdio_filebuf.h> | |
#define CHILD_STDOUT_READ pipefds[0] | |
#define CHILD_STDOUT_WRITE pipefds[1] | |
static std::string change_battery_full_text(const std::string &text) { | |
std::string ret; | |
bool pass = true; | |
for(char c : text) { | |
if(c == ',') | |
pass = false; | |
if(c == '%') | |
pass = true; | |
if(pass) | |
ret += c; | |
} | |
return ret; | |
} | |
static void err(const char *desc) { | |
std::cerr << "modify_status_on_the_fly error: " << desc << " fail: " | |
<< strerror(errno) << "\n"; | |
exit(1); | |
} | |
/* | |
* reads a JSON stream from i3status_out_stream, substitutes "12,34%" with "12%" in the battery section | |
* in JSON and outputs all input to stdout | |
*/ | |
static void main_modifier_thread(std::istream &i3status_out_stream) { | |
std::string line; | |
Json::StreamWriterBuilder writerBuilder; | |
writerBuilder["commentStyle"] = "None"; | |
writerBuilder["indentation"] = ""; // The JSON document will be written in a single line | |
std::unique_ptr<Json::StreamWriter> writer(writerBuilder.newStreamWriter()); | |
Json::CharReaderBuilder readerBuilder; | |
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader()); | |
while(std::getline(i3status_out_stream, line)) { | |
int front_offset = 0; // 1 if line begins in ',', as we are dealing with a JSON array stream | |
if(line.size() >= 1 && line[0] == ',') { | |
front_offset = 1; | |
} | |
Json::Value v; | |
if(! reader->parse(line.c_str() + front_offset, line.c_str() + line.size(), &v, NULL) | |
|| ! v.isArray()) { | |
// not a message we are interested in, pass it on | |
std::cout << line << std::endl; // intended flush | |
continue; | |
} | |
for(decltype(v.size()) i = 0; i < v.size(); ++i) { | |
const Json::Value &name = v[i]["name"]; | |
const Json::Value &full_text = v[i]["full_text"]; | |
if(name.isString() && name.asString() == "battery" && full_text.isString()) { | |
v[i]["full_text"] = change_battery_full_text(full_text.asString()); | |
} | |
} | |
if(front_offset == 1) { | |
std::cout << ','; | |
} | |
writer->write(v, &std::cout); | |
std::cout << std::endl; // intended flush | |
} | |
} | |
int main() { | |
std::ios::sync_with_stdio(true); | |
int pipefds[2]; | |
if(pipe(pipefds) == -1) | |
err("pipe()"); | |
pid_t pid; | |
switch(pid = fork()) { | |
case 0: | |
// child | |
dup2(CHILD_STDOUT_WRITE, STDOUT_FILENO); | |
close(CHILD_STDOUT_READ); // don't need this in child | |
execlp("i3status", "i3status", (char *) NULL); | |
close(CHILD_STDOUT_READ); | |
err("execlp()"); | |
case -1: | |
err("fork()"); | |
default: | |
(void) 0; | |
// parent | |
} | |
close(CHILD_STDOUT_WRITE); // we won't be writing to child's stdout | |
__gnu_cxx::stdio_filebuf<char> filebuf(CHILD_STDOUT_READ, std::ios::in); // libstdc++ extension | |
std::istream i3status_out_stream(&filebuf); | |
main_modifier_thread(i3status_out_stream); | |
close(CHILD_STDOUT_READ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment