pax_global_header 0000666 0000000 0000000 00000000064 13601636755 0014526 g ustar 00root root 0000000 0000000 52 comment=35d806b8017bcd3d2059d36175660bf92a88df15
waybar-0.9.0/ 0000775 0000000 0000000 00000000000 13601636755 0013021 5 ustar 00root root 0000000 0000000 waybar-0.9.0/.clang-format 0000664 0000000 0000000 00000000151 13601636755 0015371 0 ustar 00root root 0000000 0000000 ---
BasedOnStyle: Google
AlignConsecutiveDeclarations: true
BinPackArguments: false
ColumnLimit: 100
...
waybar-0.9.0/.editorconfig 0000664 0000000 0000000 00000000470 13601636755 0015477 0 ustar 00root root 0000000 0000000 # EditorConfig configuration for Waybar
# http://EditorConfig.org
# Top-most EditorConfig file
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[*.{build,css}]
indent_style = space
indent_size = 4
[*.{hpp,cpp}]
indent_style = space
indent_size = 2
waybar-0.9.0/.github/ 0000775 0000000 0000000 00000000000 13601636755 0014361 5 ustar 00root root 0000000 0000000 waybar-0.9.0/.github/FUNDING.yml 0000664 0000000 0000000 00000000124 13601636755 0016173 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
custom: https://paypal.me/ARouillard
waybar-0.9.0/.gitignore 0000664 0000000 0000000 00000000560 13601636755 0015012 0 ustar 00root root 0000000 0000000 .DS_Store
*~
vgcore.*
/.vscode
*.swp
packagecache
/subprojects/**/
/build*
/dist
/meson.egg-info
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
waybar-0.9.0/.gitmodules 0000664 0000000 0000000 00000000152 13601636755 0015174 0 ustar 00root root 0000000 0000000 [submodule "package/archlinux"]
path = package/archlinux
url = https://aur.archlinux.org/waybar-git.git
waybar-0.9.0/.travis.yml 0000664 0000000 0000000 00000001033 13601636755 0015127 0 ustar 00root root 0000000 0000000 sudo: false
services:
- docker
git:
submodules: false
env:
- distro: debian
- distro: archlinux
- distro: fedora
- distro: alpine
before_install:
- docker pull alexays/waybar:${distro}
- find . -type f \( -name '*.cpp' -o -name '*.h' \) -print0 | xargs -r0 clang-format -i
script:
- echo FROM alexays/waybar:${distro} > Dockerfile
- echo ADD . /root >> Dockerfile
- docker build -t waybar .
- docker run waybar /bin/sh -c "cd /root && meson build -Dman-pages=enabled && ninja -C build"
waybar-0.9.0/Dockerfiles/ 0000775 0000000 0000000 00000000000 13601636755 0015253 5 ustar 00root root 0000000 0000000 waybar-0.9.0/Dockerfiles/alpine 0000664 0000000 0000000 00000000370 13601636755 0016446 0 ustar 00root root 0000000 0000000 # vim: ft=Dockerfile
FROM alpine:latest
RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev libnl3-dev pulseaudio-dev libmpdclient-dev scdoc
waybar-0.9.0/Dockerfiles/archlinux 0000664 0000000 0000000 00000000323 13601636755 0017171 0 ustar 00root root 0000000 0000000 # vim: ft=Dockerfile
FROM archlinux/base:latest
RUN pacman -Syu --noconfirm && \
pacman -S git meson base-devel libinput wayland wayland-protocols pixman libxkbcommon mesa gtkmm3 jsoncpp scdoc --noconfirm
waybar-0.9.0/Dockerfiles/debian 0000664 0000000 0000000 00000000576 13601636755 0016430 0 ustar 00root root 0000000 0000000 # vim: ft=Dockerfile
FROM debian:sid
RUN apt-get update && \
apt-get install -y build-essential meson ninja-build git pkg-config libinput10 libinput-dev wayland-protocols libwayland-client0 libwayland-cursor0 libwayland-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libxkbcommon-dev libudev-dev libpixman-1-dev libgtkmm-3.0-dev libjsoncpp-dev scdoc && \
apt-get clean
waybar-0.9.0/Dockerfiles/fedora 0000664 0000000 0000000 00000000562 13601636755 0016441 0 ustar 00root root 0000000 0000000 # vim: ft=Dockerfile
FROM fedora:30
RUN dnf install sway meson git libinput-devel wayland-devel wayland-protocols-devel egl-wayland-devel mesa-libEGL-devel mesa-libGLES-devel mesa-libgbm-devel libxkbcommon-devel libudev-devel pixman-devel gtkmm30-devel jsoncpp-devel scdoc -y && \
dnf group install "C Development Tools and Libraries" -y && \
dnf clean all -y
waybar-0.9.0/Dockerfiles/opensuse 0000664 0000000 0000000 00000000625 13601636755 0017042 0 ustar 00root root 0000000 0000000 # vim: ft=Dockerfile
FROM opensuse/tumbleweed:latest
RUN zypper -n up && \
zypper -n install -t pattern devel_C_C++ && \
zypper -n install git meson clang libinput10 libinput-devel libwayland-client0 libwayland-cursor0 wayland-protocols-devel wayland-devel Mesa-libEGL-devel Mesa-libGLESv2-devel libgbm-devel libxkbcommon-devel libudev-devel libpixman-1-0-devel gtkmm3-devel jsoncpp-devel scdoc
waybar-0.9.0/LICENSE 0000664 0000000 0000000 00000002045 13601636755 0014027 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2018 Alex
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
waybar-0.9.0/Makefile 0000664 0000000 0000000 00000000376 13601636755 0014467 0 ustar 00root root 0000000 0000000 .PHONY: build build-debug run clean default install
default: run
build:
meson build
ninja -C build
build-debug:
meson build --buildtype=debug
ninja -C build
install: build
ninja -C build install
run: build
./build/waybar
clean:
rm -rf build
waybar-0.9.0/README.md 0000664 0000000 0000000 00000004243 13601636755 0014303 0 ustar 00root root 0000000 0000000 # Waybar [](https://travis-ci.org/Alexays/Waybar) [](LICENSE) [](https://paypal.me/ARouillard)

> Highly customizable Wayland bar for Sway and Wlroots based compositors.
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or
[AUR](https://aur.archlinux.org/packages/waybar-git/), [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar), and [Alpine Linux](https://pkgs.alpinelinux.org/packages?name=waybar)
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
**Current features**
- Sway (Workspaces, Binding mode, Focused window name)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time
- Battery
- Network
- Pulseaudio
- Disk
- Memory
- Cpu load average
- Temperature
- MPD
- Custom scripts
- Multiple output configuration
- And much more customizations
**Configuration and Styling**
[See the wiki for more details](https://github.com/Alexays/Waybar/wiki).
**How to build**
```bash
$ git clone https://github.com/Alexays/Waybar
$ cd Waybar
$ meson build
$ ninja -C build
$ ./build/waybar
# If you want to install it
$ ninja -C build install
$ waybar
```
**Dependencies**
```
gtkmm3
jsoncpp
libinput
libsigc++
fmt
wayland
wlroots
libpulse [Pulseaudio module]
libnl [Network module]
sway [Sway modules]
libdbusmenu-gtk3 [Tray module]
libmpdclient [MPD module]
```
On Ubuntu 19.10 you can install all the relevant dependencies using this command:
```
sudo apt install libgtkmm-3.0-dev libjsoncpp-dev libinput-dev libsigc++-2.0-dev libpulse-dev libnl-3-dev libdbusmenu-gtk3-dev libnl-genl-3-dev libfmt-dev clang-tidy scdoc libmpdclient-dev
```
Contributions welcome! - have fun :)
The style guidelines is [Google's](https://google.github.io/styleguide/cppguide.html)
## License
Waybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/Alexays/Waybar/blob/master/LICENSE).
waybar-0.9.0/include/ 0000775 0000000 0000000 00000000000 13601636755 0014444 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/ALabel.hpp 0000664 0000000 0000000 00000001612 13601636755 0016275 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include "AModule.hpp"
namespace waybar {
class ALabel : public AModule {
public:
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
uint16_t interval = 0, bool ellipsize = false);
virtual ~ALabel() = default;
virtual auto update() -> void;
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
protected:
Gtk::Label label_;
std::string format_;
std::string click_param;
const std::chrono::seconds interval_;
bool alt_ = false;
std::string default_format_;
virtual bool handleToggle(GdkEventButton *const &e);
virtual std::string getState(uint8_t value, bool lesser = false);
};
} // namespace waybar
waybar-0.9.0/include/AModule.hpp 0000664 0000000 0000000 00000001633 13601636755 0016506 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include "IModule.hpp"
namespace waybar {
class AModule : public IModule {
public:
AModule(const Json::Value &, const std::string &, const std::string &,
bool enable_click = false, bool enable_scroll = false);
virtual ~AModule();
virtual auto update() -> void;
virtual operator Gtk::Widget &();
Glib::Dispatcher dp;
protected:
enum SCROLL_DIR { NONE, UP, DOWN, LEFT, RIGHT };
SCROLL_DIR getScrollDir(GdkEventScroll *e);
bool tooltipEnabled();
const Json::Value &config_;
Gtk::EventBox event_box_;
virtual bool handleToggle(GdkEventButton *const &ev);
virtual bool handleScroll(GdkEventScroll *);
private:
std::vector pid_;
gdouble distance_scrolled_y_;
gdouble distance_scrolled_x_;
};
} // namespace waybar
waybar-0.9.0/include/IModule.hpp 0000664 0000000 0000000 00000000353 13601636755 0016514 0 ustar 00root root 0000000 0000000 #pragma once
#include
namespace waybar {
class IModule {
public:
virtual ~IModule() = default;
virtual auto update() -> void = 0;
virtual operator Gtk::Widget &() = 0;
};
} // namespace waybar
waybar-0.9.0/include/bar.hpp 0000664 0000000 0000000 00000006163 13601636755 0015727 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include
#include "AModule.hpp"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar {
class Factory;
struct waybar_output {
Glib::RefPtr monitor;
std::string name;
std::unique_ptr xdg_output = {
nullptr, &zxdg_output_v1_destroy};
};
class Bar {
public:
Bar(struct waybar_output *w_output, const Json::Value &);
Bar(const Bar &) = delete;
~Bar() = default;
auto toggle() -> void;
void handleSignal(int);
struct waybar_output *output;
Json::Value config;
Gtk::Window window;
struct wl_surface * surface;
bool visible = true;
bool vertical = false;
private:
static constexpr const char *MIN_HEIGHT_MSG =
"Requested height: {} exceeds the minimum height: {} required by the modules";
static constexpr const char *MIN_WIDTH_MSG =
"Requested width: {} exceeds the minimum width: {} required by the modules";
static constexpr const char *BAR_SIZE_MSG =
"Bar configured (width: {}, height: {}) for output: {}";
static constexpr const char *SIZE_DEFINED =
"{} size is defined in the config file so it will stay like that";
static void layerSurfaceHandleConfigure(void *, struct zwlr_layer_surface_v1 *, uint32_t,
uint32_t, uint32_t);
static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *);
#ifdef HAVE_GTK_LAYER_SHELL
void initGtkLayerShell();
#endif
void onConfigure(GdkEventConfigure *ev);
void onRealize();
void onMap(GdkEventAny *ev);
void setExclusiveZone(uint32_t width, uint32_t height);
void setSurfaceSize(uint32_t width, uint32_t height);
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &);
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
struct margins {
int top = 0;
int right = 0;
int bottom = 0;
int left = 0;
} margins_;
struct zwlr_layer_surface_v1 *layer_surface_;
// use gtk-layer-shell instead of handling layer surfaces directly
bool use_gls_ = false;
uint32_t width_ = 0;
uint32_t height_ = 1;
uint8_t anchor_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
Gtk::Box box_;
std::vector> modules_left_;
std::vector> modules_center_;
std::vector> modules_right_;
};
} // namespace waybar
waybar-0.9.0/include/client.hpp 0000664 0000000 0000000 00000004414 13601636755 0016436 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include "bar.hpp"
namespace waybar {
class Client {
public:
static Client *inst();
int main(int argc, char *argv[]);
Glib::RefPtr gtk_app;
Glib::RefPtr gdk_display;
struct wl_display * wl_display = nullptr;
struct wl_registry * registry = nullptr;
struct zwlr_layer_shell_v1 * layer_shell = nullptr;
struct zxdg_output_manager_v1 * xdg_output_manager = nullptr;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager = nullptr;
std::vector> bars;
private:
Client() = default;
std::tuple getConfigs(const std::string &config,
const std::string &style) const;
void bindInterfaces();
const std::string getValidPath(const std::vector &paths) const;
void handleOutput(std::unique_ptr &output);
bool isValidOutput(const Json::Value &config, std::unique_ptr &output);
auto setupConfig(const std::string &config_file) -> void;
auto setupCss(const std::string &css_file) -> void;
std::unique_ptr &getOutput(void *);
std::vector getOutputConfigs(std::unique_ptr &output);
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
void handleMonitorAdded(Glib::RefPtr monitor);
void handleMonitorRemoved(Glib::RefPtr monitor);
Json::Value config_;
Glib::RefPtr style_context_;
Glib::RefPtr css_provider_;
std::vector> outputs_;
};
} // namespace waybar
waybar-0.9.0/include/factory.hpp 0000664 0000000 0000000 00000002023 13601636755 0016621 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include "modules/clock.hpp"
#ifdef HAVE_SWAY
#include "modules/sway/mode.hpp"
#include "modules/sway/window.hpp"
#include "modules/sway/workspaces.hpp"
#endif
#ifndef NO_FILESYSTEM
#include "modules/battery.hpp"
#endif
#include "modules/cpu.hpp"
#include "modules/idle_inhibitor.hpp"
#include "modules/memory.hpp"
#include "modules/disk.hpp"
#if defined(HAVE_DBUSMENU) && !defined(NO_FILESYSTEM)
#include "modules/sni/tray.hpp"
#endif
#ifdef HAVE_LIBNL
#include "modules/network.hpp"
#endif
#ifdef HAVE_LIBUDEV
#include "modules/backlight.hpp"
#endif
#ifdef HAVE_LIBPULSE
#include "modules/pulseaudio.hpp"
#endif
#ifdef HAVE_LIBMPDCLIENT
#include "modules/mpd.hpp"
#endif
#include "bar.hpp"
#include "modules/custom.hpp"
#include "modules/temperature.hpp"
namespace waybar {
class Factory {
public:
Factory(const Bar& bar, const Json::Value& config);
AModule* makeModule(const std::string& name) const;
private:
const Bar& bar_;
const Json::Value& config_;
};
} // namespace waybar
waybar-0.9.0/include/modules/ 0000775 0000000 0000000 00000000000 13601636755 0016114 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/modules/backlight.hpp 0000664 0000000 0000000 00000003402 13601636755 0020554 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include "ALabel.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
struct udev;
struct udev_device;
namespace waybar::modules {
class Backlight : public ALabel {
class BacklightDev {
public:
BacklightDev() = default;
BacklightDev(std::string name, int actual, int max);
std::string_view name() const;
int get_actual() const;
void set_actual(int actual);
int get_max() const;
void set_max(int max);
friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) {
return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_;
}
private:
std::string name_;
int actual_ = 1;
int max_ = 1;
};
public:
Backlight(const std::string &, const Json::Value &);
~Backlight();
auto update() -> void;
private:
template
static const BacklightDev *best_device(ForwardIt first, ForwardIt last, std::string_view);
template
static void upsert_device(ForwardIt first, ForwardIt last, Inserter inserter, udev_device *dev);
template
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
const std::string preferred_device_;
static constexpr int EPOLL_MAX_EVENTS = 16;
std::optional previous_best_;
std::string previous_format_;
std::mutex udev_thread_mutex_;
std::vector devices_;
// thread must destruct before shared data
util::SleeperThread udev_thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/battery.hpp 0000664 0000000 0000000 00000002435 13601636755 0020303 0 ustar 00root root 0000000 0000000 #pragma once
#ifdef FILESYSTEM_EXPERIMENTAL
#include
#else
#include
#endif
#include
#include
#include
#include
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
#ifdef FILESYSTEM_EXPERIMENTAL
namespace fs = std::experimental::filesystem;
#else
namespace fs = std::filesystem;
#endif
class Battery : public ALabel {
public:
Battery(const std::string&, const Json::Value&);
~Battery();
auto update() -> void;
private:
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
void getBatteries();
void worker();
const std::string getAdapterStatus(uint8_t capacity) const;
const std::tuple getInfos() const;
const std::string formatTimeRemaining(float hoursRemaining);
std::vector batteries_;
fs::path adapter_;
int fd_;
std::vector wds_;
std::string old_status_;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/clock.hpp 0000664 0000000 0000000 00000000645 13601636755 0017725 0 ustar 00root root 0000000 0000000 #pragma once
#include
#if FMT_VERSION < 60000
#include
#else
#include
#endif
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Clock : public ALabel {
public:
Clock(const std::string&, const Json::Value&);
~Clock() = default;
auto update() -> void;
private:
util::SleeperThread thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/cpu.hpp 0000664 0000000 0000000 00000001375 13601636755 0017422 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Cpu : public ALabel {
public:
Cpu(const std::string&, const Json::Value&);
~Cpu() = default;
auto update() -> void;
private:
static inline const std::string data_dir_ = "/proc/stat";
uint16_t getCpuLoad();
std::tuple getCpuUsage();
std::vector> parseCpuinfo();
std::vector> prev_times_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/custom.hpp 0000664 0000000 0000000 00000001764 13601636755 0020147 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include "ALabel.hpp"
#include "util/command.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Custom : public ALabel {
public:
Custom(const std::string&, const std::string&, const Json::Value&);
~Custom();
auto update() -> void;
void refresh(int /*signal*/);
private:
void delayWorker();
void continuousWorker();
void parseOutputRaw();
void parseOutputJson();
bool handleScroll(GdkEventScroll* e);
bool handleToggle(GdkEventButton* const& e);
const std::string name_;
std::string text_;
std::string alt_;
std::string tooltip_;
std::vector class_;
int percentage_;
FILE* fp_;
int pid_;
util::command::res output_;
util::JsonParser parser_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/disk.hpp 0000664 0000000 0000000 00000000653 13601636755 0017563 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
#include "util/format.hpp"
namespace waybar::modules {
class Disk : public ALabel {
public:
Disk(const std::string&, const Json::Value&);
~Disk() = default;
auto update() -> void;
private:
util::SleeperThread thread_;
std::string path_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/idle_inhibitor.hpp 0000664 0000000 0000000 00000001061 13601636755 0021607 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
namespace waybar::modules {
class IdleInhibitor : public ALabel {
public:
IdleInhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
~IdleInhibitor();
auto update() -> void;
private:
bool handleToggle(GdkEventButton* const& e);
const Bar& bar_;
std::string status_;
struct zwp_idle_inhibitor_v1* idle_inhibitor_;
int pid_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/memory.hpp 0000664 0000000 0000000 00000001020 13601636755 0020126 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Memory : public ALabel {
public:
Memory(const std::string&, const Json::Value&);
~Memory() = default;
auto update() -> void;
private:
static inline const std::string data_dir_ = "/proc/meminfo";
void parseMeminfo();
unsigned long memtotal_;
unsigned long memfree_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/mpd.hpp 0000664 0000000 0000000 00000004214 13601636755 0017406 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include "ALabel.hpp"
namespace waybar::modules {
class MPD : public ALabel {
public:
MPD(const std::string&, const Json::Value&);
auto update() -> void;
private:
std::thread periodic_updater();
std::string getTag(mpd_tag_type type, unsigned idx = 0);
void setLabel();
std::string getStateIcon();
std::string getOptionIcon(std::string optionName, bool activated);
std::thread event_listener();
// Assumes `connection_lock_` is locked
void tryConnect();
// If checking errors on the main connection, make sure to lock it using
// `connection_lock_` before calling checkErrors
void checkErrors(mpd_connection* conn);
// Assumes `connection_lock_` is locked
void fetchState();
void waitForEvent();
bool handlePlayPause(GdkEventButton* const&);
bool stopped();
bool playing();
const std::string module_name_;
using unique_connection = std::unique_ptr;
using unique_status = std::unique_ptr;
using unique_song = std::unique_ptr;
// Not using unique_ptr since we don't manage the pointer
// (It's either nullptr, or from the config)
const char* server_;
const unsigned port_;
unsigned timeout_;
// We need a mutex here because we can trigger updates from multiple thread:
// the event based updates, the periodic updates needed for the elapsed time,
// and the click play/pause feature
std::mutex connection_lock_;
unique_connection connection_;
// The alternate connection will be used to wait for events: since it will
// be blocking (idle) we can't send commands via this connection
//
// No lock since only used in the event listener thread
unique_connection alternate_connection_;
// Protect them using the `connection_lock_`
unique_status status_;
mpd_state state_;
unique_song song_;
// To make sure the previous periodic_updater stops before creating a new one
std::mutex periodic_lock_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/network.hpp 0000664 0000000 0000000 00000004522 13601636755 0020321 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Network : public ALabel {
public:
Network(const std::string&, const Json::Value&);
~Network();
auto update() -> void;
private:
static const uint8_t MAX_RETRY = 5;
static const uint8_t EPOLL_MAX = 200;
static int handleEvents(struct nl_msg*, void*);
static int handleScan(struct nl_msg*, void*);
void worker();
void createInfoSocket();
void createEventSocket();
int getExternalInterface(int skip_idx = -1) const;
void getInterfaceAddress();
int netlinkRequest(void*, uint32_t, uint32_t groups = 0) const;
int netlinkResponse(void*, uint32_t, uint32_t groups = 0) const;
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
bool checkInterface(struct ifinfomsg* rtif, std::string name);
int getPreferredIface(int skip_idx = -1, bool wait = true) const;
auto getInfo() -> void;
void checkNewInterface(struct ifinfomsg* rtif);
const std::string getNetworkState() const;
void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
int ifid_;
sa_family_t family_;
struct sockaddr_nl nladdr_ = {0};
struct nl_sock* sock_ = nullptr;
struct nl_sock* ev_sock_ = nullptr;
int efd_;
int ev_fd_;
int nl80211_id_;
std::mutex mutex_;
unsigned long long bandwidth_down_total_;
unsigned long long bandwidth_up_total_;
std::string state_;
std::string essid_;
std::string ifname_;
std::string ipaddr_;
std::string netmask_;
int cidr_;
int32_t signal_strength_dbm_;
uint8_t signal_strength_;
uint32_t frequency_;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/pulseaudio.hpp 0000664 0000000 0000000 00000002446 13601636755 0021005 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include "ALabel.hpp"
namespace waybar::modules {
class Pulseaudio : public ALabel {
public:
Pulseaudio(const std::string&, const Json::Value&);
~Pulseaudio();
auto update() -> void;
private:
static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*);
static void contextStateCb(pa_context*, void*);
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
static void volumeModifyCb(pa_context*, int, void*);
bool handleScroll(GdkEventScroll* e);
const std::string getPortIcon() const;
pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_;
pa_context* context_;
// SINK
uint32_t sink_idx_{0};
uint16_t volume_;
pa_cvolume pa_volume_;
bool muted_;
std::string port_name_;
std::string desc_;
std::string monitor_;
// SOURCE
uint32_t source_idx_{0};
uint16_t source_volume_;
bool source_muted_;
std::string source_port_name_;
std::string source_desc_;
};
} // namespace waybar::modules
waybar-0.9.0/include/modules/sni/ 0000775 0000000 0000000 00000000000 13601636755 0016705 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/modules/sni/host.hpp 0000664 0000000 0000000 00000003460 13601636755 0020376 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include "modules/sni/item.hpp"
namespace waybar::modules::SNI {
class Host {
public:
Host(const std::size_t id, const Json::Value&, const std::function&)>&,
const std::function&)>&);
~Host();
private:
void busAcquired(const Glib::RefPtr&, Glib::ustring);
void nameAppeared(const Glib::RefPtr&, Glib::ustring,
const Glib::ustring&);
void nameVanished(const Glib::RefPtr&, Glib::ustring);
static void proxyReady(GObject*, GAsyncResult*, gpointer);
static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
std::tuple getBusNameAndObjectPath(const std::string);
void addRegisteredItem(std::string service);
std::vector> items_;
const std::string bus_name_;
const std::string object_path_;
std::size_t bus_name_id_;
std::size_t watcher_id_;
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
const Json::Value& config_;
const std::function&)> on_add_;
const std::function&)> on_remove_;
};
} // namespace waybar::modules::SNI
waybar-0.9.0/include/modules/sni/item.hpp 0000664 0000000 0000000 00000005077 13601636755 0020365 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef FILESYSTEM_EXPERIMENTAL
#include
#else
#include
#endif
namespace waybar::modules::SNI {
class Item : public sigc::trackable {
public:
Item(const std::string&, const std::string&, const Json::Value&);
~Item() = default;
std::string bus_name;
std::string object_path;
int icon_size;
int effective_icon_size;
Gtk::Image image;
Gtk::EventBox event_box;
std::string category;
std::string id;
std::string status;
std::string title;
int32_t window_id;
std::string icon_name;
Glib::RefPtr icon_pixmap;
Glib::RefPtr icon_theme;
std::string overlay_icon_name;
std::string attention_icon_name;
std::string attention_movie_name;
std::string icon_theme_path;
std::string menu;
DbusmenuGtkMenu* dbus_menu = nullptr;
Gtk::Menu* gtk_menu = nullptr;
/**
* ItemIsMenu flag means that the item only supports the context menu.
* Default value is true because libappindicator supports neither ItemIsMenu nor Activate method
* while compliant SNI implementation would always reset the flag to desired value.
*/
bool item_is_menu = true;
private:
void proxyReady(Glib::RefPtr& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
const Glib::VariantContainerBase& arguments);
void updateImage();
Glib::RefPtr extractPixBuf(GVariant* variant);
Glib::RefPtr getIconByName(const std::string& name, int size);
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
void makeMenu();
bool handleClick(GdkEventButton* const& /*ev*/);
Glib::RefPtr proxy_;
Glib::RefPtr cancellable_;
bool update_pending_;
};
} // namespace waybar::modules::SNI
waybar-0.9.0/include/modules/sni/tray.hpp 0000664 0000000 0000000 00000001204 13601636755 0020372 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/sni/host.hpp"
#include "modules/sni/watcher.hpp"
#include "util/json.hpp"
namespace waybar::modules::SNI {
class Tray : public AModule {
public:
Tray(const std::string&, const Bar&, const Json::Value&);
~Tray() = default;
auto update() -> void;
private:
void onAdd(std::unique_ptr- & item);
void onRemove(std::unique_ptr
- & item);
static inline std::size_t nb_hosts_ = 0;
Gtk::Box box_;
SNI::Watcher watcher_;
SNI::Host host_;
};
} // namespace waybar::modules::SNI
waybar-0.9.0/include/modules/sni/watcher.hpp 0000664 0000000 0000000 00000002437 13601636755 0021061 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
namespace waybar::modules::SNI {
class Watcher {
public:
Watcher(std::size_t id);
~Watcher();
private:
typedef enum { GF_WATCH_TYPE_HOST, GF_WATCH_TYPE_ITEM } GfWatchType;
typedef struct {
GfWatchType type;
Watcher * watcher;
gchar * service;
gchar * bus_name;
gchar * object_path;
guint watch_id;
} GfWatch;
void busAcquired(const Glib::RefPtr &, Glib::ustring);
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, const gchar *);
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, const gchar *);
static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, const gchar *object_path);
static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, const gchar *, Watcher *);
static void nameVanished(GDBusConnection *connection, const char *name, gpointer data);
static void gfWatchFree(gpointer data);
void updateRegisteredItems(SnWatcher *obj);
uint32_t bus_name_id_;
uint32_t watcher_id_;
GSList * hosts_ = nullptr;
GSList * items_ = nullptr;
SnWatcher *watcher_ = nullptr;
};
} // namespace waybar::modules::SNI
waybar-0.9.0/include/modules/sway/ 0000775 0000000 0000000 00000000000 13601636755 0017077 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/modules/sway/ipc/ 0000775 0000000 0000000 00000000000 13601636755 0017652 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/modules/sway/ipc/client.hpp 0000664 0000000 0000000 00000002076 13601636755 0021646 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include
#include
#include
#include
#include "ipc.hpp"
namespace waybar::modules::sway {
class Ipc {
public:
Ipc();
~Ipc();
struct ipc_response {
uint32_t size;
uint32_t type;
std::string payload;
};
sigc::signal signal_event;
sigc::signal signal_cmd;
void sendCmd(uint32_t type, const std::string &payload = "");
void subscribe(const std::string &payload);
void handleEvent();
protected:
static inline const std::string ipc_magic_ = "i3-ipc";
static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8;
const std::string getSocketPath() const;
int open(const std::string &) const;
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
struct ipc_response recv(int fd);
int fd_;
int fd_event_;
std::mutex mutex_;
};
} // namespace waybar::modules::sway
waybar-0.9.0/include/modules/sway/ipc/ipc.hpp 0000664 0000000 0000000 00000001541 13601636755 0021137 0 ustar 00root root 0000000 0000000 #pragma once
#define event_mask(ev) (1u << (ev & 0x7F))
enum ipc_command_type {
// i3 command types - see i3's I3_REPLY_TYPE constants
IPC_COMMAND = 0,
IPC_GET_WORKSPACES = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_OUTPUTS = 3,
IPC_GET_TREE = 4,
IPC_GET_MARKS = 5,
IPC_GET_BAR_CONFIG = 6,
IPC_GET_VERSION = 7,
IPC_GET_BINDING_MODES = 8,
IPC_GET_CONFIG = 9,
IPC_SEND_TICK = 10,
// sway-specific command types
IPC_GET_INPUTS = 100,
IPC_GET_SEATS = 101,
// Events sent from sway to clients. Events have the highest bits set.
IPC_EVENT_WORKSPACE = ((1 << 31) | 0),
IPC_EVENT_OUTPUT = ((1 << 31) | 1),
IPC_EVENT_MODE = ((1 << 31) | 2),
IPC_EVENT_WINDOW = ((1 << 31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1 << 31) | 4),
IPC_EVENT_BINDING = ((1 << 31) | 5),
IPC_EVENT_SHUTDOWN = ((1 << 31) | 6),
IPC_EVENT_TICK = ((1 << 31) | 7),
};
waybar-0.9.0/include/modules/sway/mode.hpp 0000664 0000000 0000000 00000001215 13601636755 0020533 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
class Mode : public ALabel, public sigc::trackable {
public:
Mode(const std::string&, const Json::Value&);
~Mode() = default;
auto update() -> void;
private:
void onEvent(const struct Ipc::ipc_response&);
void worker();
std::string mode_;
util::JsonParser parser_;
std::mutex mutex_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway
waybar-0.9.0/include/modules/sway/window.hpp 0000664 0000000 0000000 00000002430 13601636755 0021116 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include "ALabel.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
class Window : public ALabel, public sigc::trackable {
public:
Window(const std::string&, const waybar::Bar&, const Json::Value&);
~Window() = default;
auto update() -> void;
private:
void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
void worker();
std::tuple getFocusedNode(const Json::Value& nodes,
std::string& output);
void getTree();
const Bar& bar_;
std::string window_;
int windowId_;
std::string app_id_;
std::string old_app_id_;
std::size_t app_nb_;
util::JsonParser parser_;
std::mutex mutex_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway
waybar-0.9.0/include/modules/sway/workspaces.hpp 0000664 0000000 0000000 00000003150 13601636755 0021770 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include
#include "AModule.hpp"
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
class Workspaces : public AModule, public sigc::trackable {
public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
~Workspaces() = default;
auto update() -> void;
private:
void onCmd(const struct Ipc::ipc_response&);
void onEvent(const struct Ipc::ipc_response&);
void worker();
bool filterButtons();
Gtk::Button& addButton(const Json::Value&);
void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&);
const std::string getCycleWorkspace(std::vector::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const;
std::string trimWorkspaceName(std::string);
bool handleScroll(GdkEventScroll*);
const Bar& bar_;
std::vector workspaces_;
std::vector workspaces_order_;
Gtk::Box box_;
util::JsonParser parser_;
std::unordered_map buttons_;
std::mutex mutex_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway
waybar-0.9.0/include/modules/temperature.hpp 0000664 0000000 0000000 00000001004 13601636755 0021155 0 ustar 00root root 0000000 0000000 #pragma once
#include
#include
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules {
class Temperature : public ALabel {
public:
Temperature(const std::string&, const Json::Value&);
~Temperature() = default;
auto update() -> void;
private:
std::tuple getTemperature();
bool isCritical(uint16_t);
std::string file_path_;
util::SleeperThread thread_;
};
} // namespace waybar::modules
waybar-0.9.0/include/util/ 0000775 0000000 0000000 00000000000 13601636755 0015421 5 ustar 00root root 0000000 0000000 waybar-0.9.0/include/util/clara.hpp 0000664 0000000 0000000 00000124673 13601636755 0017231 0 ustar 00root root 0000000 0000000 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.5
#ifndef CLARA_HPP_INCLUDED
#define CLARA_HPP_INCLUDED
#ifndef CLARA_CONFIG_CONSOLE_WIDTH
#define CLARA_CONFIG_CONSOLE_WIDTH 80
#endif
#ifndef CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
#endif
#ifndef CLARA_CONFIG_OPTIONAL_TYPE
#ifdef __has_include
#if __has_include() && __cplusplus >= 201703L
#include
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
#endif
#endif
#endif
// ----------- #included from clara_textflow.hpp -----------
// TextFlowCpp
//
// A single-header library for wrapping and laying out basic text, by Phil Nash
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This project is hosted at https://github.com/philsquared/textflowcpp
#ifndef CLARA_TEXTFLOW_HPP_INCLUDED
#define CLARA_TEXTFLOW_HPP_INCLUDED
#include
#include
#include
#include
#ifndef CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
#endif
namespace clara { namespace TextFlow {
inline auto isWhitespace( char c ) -> bool {
static std::string chars = " \t\n\r";
return chars.find( c ) != std::string::npos;
}
inline auto isBreakableBefore( char c ) -> bool {
static std::string chars = "[({<|";
return chars.find( c ) != std::string::npos;
}
inline auto isBreakableAfter( char c ) -> bool {
static std::string chars = "])}>.,:;*+-=&/\\";
return chars.find( c ) != std::string::npos;
}
class Columns;
class Column {
std::vector m_strings;
size_t m_width = CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
size_t m_indent = 0;
size_t m_initialIndent = std::string::npos;
public:
class iterator {
friend Column;
Column const& m_column;
size_t m_stringIndex = 0;
size_t m_pos = 0;
size_t m_len = 0;
size_t m_end = 0;
bool m_suffix = false;
iterator( Column const& column, size_t stringIndex )
: m_column( column ),
m_stringIndex( stringIndex )
{}
auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto isBoundary( size_t at ) const -> bool {
assert( at > 0 );
assert( at <= line().size() );
return at == line().size() ||
( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
isBreakableBefore( line()[at] ) ||
isBreakableAfter( line()[at-1] );
}
void calcLength() {
assert( m_stringIndex < m_column.m_strings.size() );
m_suffix = false;
auto width = m_column.m_width-indent();
m_end = m_pos;
while( m_end < line().size() && line()[m_end] != '\n' )
++m_end;
if( m_end < m_pos + width ) {
m_len = m_end - m_pos;
}
else {
size_t len = width;
while (len > 0 && !isBoundary(m_pos + len))
--len;
while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
--len;
if (len > 0) {
m_len = len;
} else {
m_suffix = true;
m_len = width - 1;
}
}
}
auto indent() const -> size_t {
auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
return initial == std::string::npos ? m_column.m_indent : initial;
}
auto addIndentAndSuffix(std::string const &plain) const -> std::string {
return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain);
}
public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
explicit iterator( Column const& column ) : m_column( column ) {
assert( m_column.m_width > m_column.m_indent );
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
calcLength();
if( m_len == 0 )
m_stringIndex++; // Empty string
}
auto operator *() const -> std::string {
assert( m_stringIndex < m_column.m_strings.size() );
assert( m_pos <= m_end );
return addIndentAndSuffix(line().substr(m_pos, m_len));
}
auto operator ++() -> iterator& {
m_pos += m_len;
if( m_pos < line().size() && line()[m_pos] == '\n' )
m_pos += 1;
else
while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
++m_pos;
if( m_pos == line().size() ) {
m_pos = 0;
++m_stringIndex;
}
if( m_stringIndex < m_column.m_strings.size() )
calcLength();
return *this;
}
auto operator ++(int) -> iterator {
iterator prev( *this );
operator++();
return prev;
}
auto operator ==( iterator const& other ) const -> bool {
return
m_pos == other.m_pos &&
m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column;
}
auto operator !=( iterator const& other ) const -> bool {
return !operator==( other );
}
};
using const_iterator = iterator;
explicit Column( std::string const& text ) { m_strings.push_back( text ); }
auto width( size_t newWidth ) -> Column& {
assert( newWidth > 0 );
m_width = newWidth;
return *this;
}
auto indent( size_t newIndent ) -> Column& {
m_indent = newIndent;
return *this;
}
auto initialIndent( size_t newIndent ) -> Column& {
m_initialIndent = newIndent;
return *this;
}
auto width() const -> size_t { return m_width; }
auto begin() const -> iterator { return iterator( *this ); }
auto end() const -> iterator { return { *this, m_strings.size() }; }
inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) {
bool first = true;
for( auto line : col ) {
if( first )
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto operator + ( Column const& other ) -> Columns;
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
class Spacer : public Column {
public:
explicit Spacer( size_t spaceWidth ) : Column( "" ) {
width( spaceWidth );
}
};
class Columns {
std::vector m_columns;
public:
class iterator {
friend Columns;
struct EndTag {};
std::vector const& m_columns;
std::vector m_iterators;
size_t m_activeIterators;
iterator( Columns const& columns, EndTag )
: m_columns( columns.m_columns ),
m_activeIterators( 0 )
{
m_iterators.reserve( m_columns.size() );
for( auto const& col : m_columns )
m_iterators.push_back( col.end() );
}
public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
explicit iterator( Columns const& columns )
: m_columns( columns.m_columns ),
m_activeIterators( m_columns.size() )
{
m_iterators.reserve( m_columns.size() );
for( auto const& col : m_columns )
m_iterators.push_back( col.begin() );
}
auto operator ==( iterator const& other ) const -> bool {
return m_iterators == other.m_iterators;
}
auto operator !=( iterator const& other ) const -> bool {
return m_iterators != other.m_iterators;
}
auto operator *() const -> std::string {
std::string row, padding;
for( size_t i = 0; i < m_columns.size(); ++i ) {
auto width = m_columns[i].width();
if( m_iterators[i] != m_columns[i].end() ) {
std::string col = *m_iterators[i];
row += padding + col;
if( col.size() < width )
padding = std::string( width - col.size(), ' ' );
else
padding = "";
}
else {
padding += std::string( width, ' ' );
}
}
return row;
}
auto operator ++() -> iterator& {
for( size_t i = 0; i < m_columns.size(); ++i ) {
if (m_iterators[i] != m_columns[i].end())
++m_iterators[i];
}
return *this;
}
auto operator ++(int) -> iterator {
iterator prev( *this );
operator++();
return prev;
}
};
using const_iterator = iterator;
auto begin() const -> iterator { return iterator( *this ); }
auto end() const -> iterator { return { *this, iterator::EndTag() }; }
auto operator += ( Column const& col ) -> Columns& {
m_columns.push_back( col );
return *this;
}
auto operator + ( Column const& col ) -> Columns {
Columns combined = *this;
combined += col;
return combined;
}
inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) {
bool first = true;
for( auto line : cols ) {
if( first )
first = false;
else
os << "\n";
os << line;
}
return os;
}
auto toString() const -> std::string {
std::ostringstream oss;
oss << *this;
return oss.str();
}
};
inline auto Column::operator + ( Column const& other ) -> Columns {
Columns cols;
cols += *this;
cols += other;
return cols;
}
}}
#endif // CLARA_TEXTFLOW_HPP_INCLUDED
// ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp
#include
#include
#include
#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
#define CLARA_PLATFORM_WINDOWS
#endif
namespace clara {
namespace detail {
// Traits for extracting arg and return type of lambdas (for single argument lambdas)
template
struct UnaryLambdaTraits : UnaryLambdaTraits {};
template
struct UnaryLambdaTraits {
static const bool isValid = false;
};
template
struct UnaryLambdaTraits {
static const bool isValid = true;
using ArgType = typename std::remove_const::type>::type;
using ReturnType = ReturnT;
};
class TokenStream;
// Transport for raw args (copied from main args, or supplied via init list for testing)
class Args {
friend TokenStream;
std::string m_exeName;
std::vector m_args;
public:
Args( int argc, char const* const* argv )
: m_exeName(argv[0]),
m_args(argv + 1, argv + argc) {}
Args( std::initializer_list args )
: m_exeName( *args.begin() ),
m_args( args.begin()+1, args.end() )
{}
auto exeName() const -> std::string {
return m_exeName;
}
};
// Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
// may encode an option + its argument if the : or = form is used
enum class TokenType {
Option, Argument
};
struct Token {
TokenType type;
std::string token;
};
inline auto isOptPrefix( char c ) -> bool {
return c == '-'
#ifdef CLARA_PLATFORM_WINDOWS
|| c == '/'
#endif
;
}
// Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
class TokenStream {
using Iterator = std::vector::const_iterator;
Iterator it;
Iterator itEnd;
std::vector m_tokenBuffer;
void loadBuffer() {
m_tokenBuffer.resize( 0 );
// Skip any empty strings
while( it != itEnd && it->empty() )
++it;
if( it != itEnd ) {
auto const &next = *it;
if( isOptPrefix( next[0] ) ) {
auto delimiterPos = next.find_first_of( " :=" );
if( delimiterPos != std::string::npos ) {
m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
} else {
if( next[1] != '-' && next.size() > 2 ) {
std::string opt = "- ";
for( size_t i = 1; i < next.size(); ++i ) {
opt[1] = next[i];
m_tokenBuffer.push_back( { TokenType::Option, opt } );
}
} else {
m_tokenBuffer.push_back( { TokenType::Option, next } );
}
}
} else {
m_tokenBuffer.push_back( { TokenType::Argument, next } );
}
}
}
public:
explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
loadBuffer();
}
explicit operator bool() const {
return !m_tokenBuffer.empty() || it != itEnd;
}
auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
auto operator*() const -> Token {
assert( !m_tokenBuffer.empty() );
return m_tokenBuffer.front();
}
auto operator->() const -> Token const * {
assert( !m_tokenBuffer.empty() );
return &m_tokenBuffer.front();
}
auto operator++() -> TokenStream & {
if( m_tokenBuffer.size() >= 2 ) {
m_tokenBuffer.erase( m_tokenBuffer.begin() );
} else {
if( it != itEnd )
++it;
loadBuffer();
}
return *this;
}
};
class ResultBase {
public:
enum Type {
Ok, LogicError, RuntimeError
};
protected:
ResultBase( Type type ) : m_type( type ) {}
virtual ~ResultBase() = default;
virtual void enforceOk() const = 0;
Type m_type;
};
template
class ResultValueBase : public ResultBase {
public:
auto value() const -> T const & {
enforceOk();
return m_value;
}
protected:
ResultValueBase( Type type ) : ResultBase( type ) {}
ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
if( m_type == ResultBase::Ok )
new( &m_value ) T( other.m_value );
}
ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
new( &m_value ) T( value );
}
auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
if( m_type == ResultBase::Ok )
m_value.~T();
ResultBase::operator=(other);
if( m_type == ResultBase::Ok )
new( &m_value ) T( other.m_value );
return *this;
}
~ResultValueBase() override {
if( m_type == Ok )
m_value.~T();
}
union {
T m_value;
};
};
template<>
class ResultValueBase : public ResultBase {
protected:
using ResultBase::ResultBase;
};
template
class BasicResult : public ResultValueBase {
public:
template
explicit BasicResult( BasicResult const &other )
: ResultValueBase( other.type() ),
m_errorMessage( other.errorMessage() )
{
assert( type() != ResultBase::Ok );
}
template
static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
static auto ok() -> BasicResult { return { ResultBase::Ok }; }
static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
explicit operator bool() const { return m_type == ResultBase::Ok; }
auto type() const -> ResultBase::Type { return m_type; }
auto errorMessage() const -> std::string { return m_errorMessage; }
protected:
void enforceOk() const override {
// Errors shouldn't reach this point, but if they do
// the actual error message will be in m_errorMessage
assert( m_type != ResultBase::LogicError );
assert( m_type != ResultBase::RuntimeError );
if( m_type != ResultBase::Ok )
std::abort();
}
std::string m_errorMessage; // Only populated if resultType is an error
BasicResult( ResultBase::Type type, std::string const &message )
: ResultValueBase(type),
m_errorMessage(message)
{
assert( m_type != ResultBase::Ok );
}
using ResultValueBase::ResultValueBase;
using ResultBase::m_type;
};
enum class ParseResultType {
Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
};
class ParseState {
public:
ParseState( ParseResultType type, TokenStream const &remainingTokens )
: m_type(type),
m_remainingTokens( remainingTokens )
{}
auto type() const -> ParseResultType { return m_type; }
auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
private:
ParseResultType m_type;
TokenStream m_remainingTokens;
};
using Result = BasicResult;
using ParserResult = BasicResult;
using InternalParseResult = BasicResult;
struct HelpColumns {
std::string left;
std::string right;
};
template
inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
std::stringstream ss;
ss << source;
ss >> target;
if( ss.fail() )
return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
else
return ParserResult::ok( ParseResultType::Matched );
}
inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
target = source;
return ParserResult::ok( ParseResultType::Matched );
}
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
std::string srcLC = source;
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } );
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
target = true;
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
target = false;
else
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
return ParserResult::ok( ParseResultType::Matched );
}
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
template
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE& target ) -> ParserResult {
T temp;
auto result = convertInto( source, temp );
if( result )
target = std::move(temp);
return result;
}
#endif // CLARA_CONFIG_OPTIONAL_TYPE
struct NonCopyable {
NonCopyable() = default;
NonCopyable( NonCopyable const & ) = delete;
NonCopyable( NonCopyable && ) = delete;
NonCopyable &operator=( NonCopyable const & ) = delete;
NonCopyable &operator=( NonCopyable && ) = delete;
};
struct BoundRef : NonCopyable {
virtual ~BoundRef() = default;
virtual auto isContainer() const -> bool { return false; }
virtual auto isFlag() const -> bool { return false; }
};
struct BoundValueRefBase : BoundRef {
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
};
struct BoundFlagRefBase : BoundRef {
virtual auto setFlag( bool flag ) -> ParserResult = 0;
virtual auto isFlag() const -> bool { return true; }
};
template
struct BoundValueRef : BoundValueRefBase {
T &m_ref;
explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
auto setValue( std::string const &arg ) -> ParserResult override {
return convertInto( arg, m_ref );
}
};
template
struct BoundValueRef> : BoundValueRefBase {
std::vector &m_ref;
explicit BoundValueRef( std::vector &ref ) : m_ref( ref ) {}
auto isContainer() const -> bool override { return true; }
auto setValue( std::string const &arg ) -> ParserResult override {
T temp;
auto result = convertInto( arg, temp );
if( result )
m_ref.push_back( temp );
return result;
}
};
struct BoundFlagRef : BoundFlagRefBase {
bool &m_ref;
explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
auto setFlag( bool flag ) -> ParserResult override {
m_ref = flag;
return ParserResult::ok( ParseResultType::Matched );
}
};
template
struct LambdaInvoker {
static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" );
template
static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
return lambda( arg );
}
};
template<>
struct LambdaInvoker {
template
static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
lambda( arg );
return ParserResult::ok( ParseResultType::Matched );
}
};
template
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
ArgType temp{};
auto result = convertInto( arg, temp );
return !result
? result
: LambdaInvoker::ReturnType>::invoke( lambda, temp );
}
template
struct BoundLambda : BoundValueRefBase {
L m_lambda;
static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" );
explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
auto setValue( std::string const &arg ) -> ParserResult override {
return invokeLambda::ArgType>( m_lambda, arg );
}
};
template
struct BoundFlagLambda : BoundFlagRefBase {
L m_lambda;
static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" );
static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" );
explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
auto setFlag( bool flag ) -> ParserResult override {
return LambdaInvoker::ReturnType>::invoke( m_lambda, flag );
}
};
enum class Optionality { Optional, Required };
struct Parser;
class ParserBase {
public:
virtual ~ParserBase() = default;
virtual auto validate() const -> Result { return Result::ok(); }
virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0;
virtual auto cardinality() const -> size_t { return 1; }
auto parse( Args const &args ) const -> InternalParseResult {
return parse( args.exeName(), TokenStream( args ) );
}
};
template
class ComposableParserImpl : public ParserBase {
public:
template
auto operator|( T const &other ) const -> Parser;
template
auto operator+( T const &other ) const -> Parser;
};
// Common code and state for Args and Opts
template
class ParserRefImpl : public ComposableParserImpl {
protected:
Optionality m_optionality = Optionality::Optional;
std::shared_ptr m_ref;
std::string m_hint;
std::string m_description;
explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {}
public:
template
ParserRefImpl( T &ref, std::string const &hint )
: m_ref( std::make_shared>( ref ) ),
m_hint( hint )
{}
template
ParserRefImpl( LambdaT const &ref, std::string const &hint )
: m_ref( std::make_shared>( ref ) ),
m_hint(hint)
{}
auto operator()( std::string const &description ) -> DerivedT & {
m_description = description;
return static_cast( *this );
}
auto optional() -> DerivedT & {
m_optionality = Optionality::Optional;
return static_cast( *this );
};
auto required() -> DerivedT & {
m_optionality = Optionality::Required;
return static_cast( *this );
};
auto isOptional() const -> bool {
return m_optionality == Optionality::Optional;
}
auto cardinality() const -> size_t override {
if( m_ref->isContainer() )
return 0;
else
return 1;
}
auto hint() const -> std::string { return m_hint; }
};
class ExeName : public ComposableParserImpl {
std::shared_ptr m_name;
std::shared_ptr m_ref;
template
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr {
return std::make_shared>( lambda) ;
}
public:
ExeName() : m_name( std::make_shared( "" ) ) {}
explicit ExeName( std::string &ref ) : ExeName() {
m_ref = std::make_shared>( ref );
}
template