xaizek / d2if (License: GPLv2+) (since 2018-12-07)
Simple dzen2 input formatter, which is supposed to not waste CPU time for nothing and provides a number of builtin "widgets" for displaying system information.
<root> / src / Battery.cpp (943b32b6cd9b705a632dbf1b710efc3b8a526a54) (2,923B) (mode 100644) [raw]
// d2if
// Copyright (C) 2012 xaizek.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA

#include "Battery.hpp"

#include <fstream>
#include <limits>
#include <sstream>
#include <utility>

void Battery::update()
{
    static const std::string fgBarColor {
        "^fg(" + getColor("fg-bar") + ")"
    };
    static const std::string fgGoodColor {
        "^fg(" + getColor("fg-bar-good") + ")"
    };
    static const std::string fgBadColor {
        "^fg(" + getColor("fg-bar-bad") + ")"
    };

    const std::pair<bool, int> state = getBatteryState();
    const bool charging = state.first;
    const int remaining = state.second;

    if (remaining < 0) {
        setVisible(false);
        return;
    }

    const std::string &fgColor = charging ? fgGoodColor : fgBadColor;

    std::ostringstream result;

    result << "^fg(white)BAT:"
           << "^p(2;3)"
           << fgBarColor
           << "^r(" << remaining << "x10)"
           << fgColor
           << "^r(" << (100 - remaining) << "x10)";

    Field::setText(result.str());
}

std::pair<bool, int> Battery::getBatteryState() const
{
    std::ifstream info { "/proc/acpi/battery/BAT0/info" };
    std::ifstream state { "/proc/acpi/battery/BAT0/state" };

    if (info.is_open() && state.is_open()) {
        static const auto max = std::numeric_limits<std::streamsize>::max();

        int full;
        std::string charged;
        int remaining;

        info.ignore(max, '\n')
            .ignore(max, '\n')
            .ignore(max, ':')
            >> full;

        state.ignore(max, '\n')
             .ignore(max, '\n')
             .ignore(max, ':')
             >> charged;

        state.ignore(max, ':')
            .ignore(max, ':')
            >> remaining;

        return {
            charged == "charged" || charged == "charging", (remaining*100)/full
        };
    }

    std::ifstream capacity { "/sys/class/power_supply/BAT0/capacity" };
    std::ifstream status { "/sys/class/power_supply/BAT0/status" };
    if (capacity.is_open() && status.is_open()) {
        int level;
        std::string state;

        capacity >> level;
        status >> state;

        return {
            state != "Discharging", level
        };
    }

    return { false, -1 };
}
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/d2if

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/d2if

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master